A complete guide to using CLAHub for managing Contributor License Agreements on GitHub.
Table of Contents
- Overview
- Getting Started
- For Project Owners
- Creating an Agreement
- CLA Templates
- Custom Form Fields
- Organization-Wide CLAs
- Corporate CLAs (CCLA)
- Managing Exclusions
- Viewing Signatures
- Manual Signature Entry
- CSV Import
- Revoking Signatures
- Ownership Transfer
- Email Notifications
- CLA Versioning
- CONTRIBUTING.md Generation
- Audit Log
- README Badges
- Exporting Data
- For Contributors
- REST API
- Self-Hosting
- Custom Branding
- Troubleshooting
Overview
CLAHub automates Contributor License Agreement management for GitHub projects. The flow is:
- Owner creates a CLA agreement for a repo or organization
- A contributor opens a pull request
- CLAHub checks if all commit authors have signed the CLA
- If not, the PR gets a ❌ "CLA not signed" check — with a link to sign
- The contributor signs in with GitHub, reads the CLA, and clicks "I agree"
- CLAHub automatically re-checks the PR → ✅ green checkmark
No PDFs. No emails. No manual tracking.
Getting Started
Roles
CLAHub has two user roles:
| Role | How to Sign In | What They Can Do |
|---|---|---|
| Owner | "Sign in as Owner" | Create/edit agreements, view signatures, manage exclusions, transfer ownership, access API |
| Contributor | "Sign in as Contributor" | View and sign CLAs |
Owners sign in with elevated GitHub permissions (repo access, org read). Contributors sign in with minimal permissions (public profile only).
First-Time Setup
- Go to cla-hub.io
- Click "Sign in as Owner"
- Authorize CLAHub with GitHub
- Install the CLAHub GitHub App on your account or organization
- Create your first agreement
For Project Owners
Creating an Agreement
- Click "New Agreement" from the dashboard
- Select the scope:
- Repository — covers a single repo
- Organization — covers all repos in an org
- Select the repository or organization from the dropdown
- Choose a CLA template or write custom text in Markdown
- Optionally add custom form fields
- Click "Create Agreement"
CLAHub will start checking PRs on that repo immediately.
CLA Templates
Three built-in templates:
| Template | Description |
|---|---|
| Apache Individual CLA (ICLA) | Standard Apache-style individual contributor agreement covering copyright and patent grants |
| Developer Certificate of Origin (DCO) | Linux Foundation DCO v1.1 — certifies the contributor has the right to submit the code |
| Custom (Blank) | Start from scratch with your own Markdown text |
Templates are starting points — edit the text however you like after selecting one.
Custom Form Fields
Add fields that contributors must fill out when signing. Supported field types:
| Type | Description |
|---|---|
| Text | Single-line text input |
| Email address with validation | |
| URL | URL with validation |
| Checkbox | Boolean agreement (e.g., "I confirm I am authorized...") |
| Date | Date picker |
Each field can be marked as required or optional, and includes an optional description shown to the contributor.
Organization-Wide CLAs
Instead of creating a CLA per repo, create one agreement that covers your entire GitHub organization:
- When creating a new agreement, select "Organization" scope
- Choose the GitHub organization
- The CLA will apply to PRs across all repos in that org
Contributors only need to sign once — the signature covers every repo in the organization.
Corporate CLAs (CCLA)
For companies whose employees contribute to your project:
- A company representative signs the CLA as a Corporate signature
- They provide their company name and email domain (e.g.,
example.com) - Any contributor whose GitHub email matches that domain is automatically covered
This means individual employees don't need to sign separately — the corporate signature covers everyone with a matching email.
Managing Exclusions
Not everyone needs to sign a CLA. Exclude:
| Exclusion Type | What It Does |
|---|---|
| Auto-detect bots | Automatically excludes GitHub accounts ending in [bot] (Dependabot, Renovate, etc.) |
| Individual user | Exclude a specific GitHub username (e.g., core team members) |
| GitHub team | Exclude all members of a GitHub team (e.g., @org/core-team) |
Excluded users don't need to sign — their commits are bypassed during CLA checks.
To manage exclusions, go to your agreement's edit page and use the Exclusions section.
Viewing Signatures
From your agreement page, you'll see:
- Total number of signatures
- List of all signatories with their GitHub username, sign date, and signature type (individual/corporate)
- Custom field values for each signature
- Signature source (online, manual, CSV import)
Manual Signature Entry
For contributors who signed a CLA outside of CLAHub (e.g., via email or paper):
- Go to your agreement's edit page
- In the Signature Manager section, enter the GitHub username or email
- Click "Add Signature"
The contributor will be marked as signed without needing to go through the online flow.
CSV Import
Bulk-import signatures from a CSV file:
- Prepare a CSV with columns:
github_username(oremail) - Go to your agreement's edit page
- Upload the CSV in the Import section
- Preview the import — CLAHub shows which users will be added, which are duplicates, and any validation errors
- Confirm the import
Revoking Signatures
If a signature needs to be invalidated:
- Go to your agreement's signatories list
- Click the revoke button next to the signature
- Confirm the revocation
Revoked signatures can be restored. When a signature is revoked, CLAHub automatically re-checks open PRs — any PR from that contributor will switch from ✅ to ❌.
Ownership Transfer
Transfer an agreement to another registered CLAHub owner:
- Go to your agreement's edit page
- In the Transfer Ownership section, enter the new owner's GitHub username
- Confirm the transfer
The new owner must already have a CLAHub account (signed in as Owner at least once). The transfer is transactional — all data (signatures, exclusions, versions) moves with the agreement.
Email Notifications
Get notified when someone signs your CLA:
- Go to your agreement's edit page
- Toggle "Notify on new signatures"
- Notifications are sent to the email associated with your GitHub account
Powered by Resend. Notifications include the signer's GitHub username and which agreement they signed.
CLA Versioning
When you update your CLA text:
- Edit the agreement text
- Optionally add a changelog entry explaining what changed
- Save — this creates a new version
Previous signatures are linked to the version they signed. The version history is preserved in the audit log.
CONTRIBUTING.md Generation
CLAHub can generate a CONTRIBUTING.md snippet for your repo:
- Go to your agreement's edit page
- Find the CONTRIBUTING.md section
- Copy the generated Markdown
The snippet includes instructions for contributors on how to sign the CLA, plus a badge showing the CLA status.
Audit Log
Every action in CLAHub is logged:
- Agreement created, updated, deleted
- Signatures signed, revoked, restored
- Exclusions added, removed
- Ownership transfers
- Manual signature entries
- CSV imports
View the audit log from your agreement's edit page. Each entry shows who performed the action, when, and the before/after state.
README Badges
Add a CLA status badge to your README:
For a repo agreement:
[](https://cla-hub.io/agreements/OWNER/REPO)
For an org-wide agreement:
[](https://cla-hub.io/agreements/OWNER)
The badge shows "CLA: signed" (green) or "CLA: not signed" (red) based on the current PR's status.
Exporting Data
CSV Export: Download all signatures as a CSV file with columns for GitHub username, email, sign date, signature type, and custom field values.
PDF Export: Generate a PDF document of your CLA agreement text.
Both exports are available from the agreement page and via the REST API.
For Contributors
Signing a CLA
- Open a pull request on a project that uses CLAHub
- You'll see a ❌ "CLAHub" check on your PR
- Click "Details" on the check — this takes you to CLAHub
- Click "Sign in as Contributor" (minimal GitHub permissions)
- Read the CLA text
- Fill in any required fields
- Click "I agree and sign"
That's it. You'll be redirected back, and your PR will update to ✅ within seconds.
What Happens After Signing
- Your signature is recorded permanently
- All open PRs on that repo (or org) are automatically re-checked
- You don't need to re-sign for future PRs on the same project
- If the CLA is updated to a new version, you may be asked to re-sign (if the project owner enables re-sign on version bump)
REST API
CLAHub provides a full REST API for programmatic access.
Authentication
Generate an API key from Settings → API Keys in the CLAHub dashboard.
All API requests use Bearer token authentication:
curl -H "Authorization: Bearer clahub_xxxx" https://cla-hub.io/api/v1/...
API keys are prefixed with clahub_ for easy identification.
Rate Limits
| Tier | Limit |
|---|---|
| Authenticated (read) | 100 requests/minute |
| Authenticated (write) | 60 requests/minute |
| Unauthenticated | 30 requests/minute |
Rate limit headers are included in every response:
X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset
Endpoints
Agreements
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/agreements | List your agreements |
GET | /api/v1/agreements/{owner}/{repo} | Get a repo agreement |
GET | /api/v1/agreements/{owner} | Get an org-wide agreement |
Signatures
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/agreements/{owner}/{repo}/signatures | List signatures for a repo agreement |
GET | /api/v1/agreements/{owner}/signatures | List signatures for an org agreement |
POST | /api/v1/agreements/{owner}/{repo}/signatures | Add a manual signature |
Check Status
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/agreements/{owner}/{repo}/check/{username} | Check if a user has signed (repo) |
GET | /api/v1/agreements/{owner}/check/{username} | Check if a user has signed (org) |
Exports
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/agreements/{owner}/{repo}/export/csv | Export signatures as CSV |
GET | /api/v1/agreements/{owner}/{repo}/export/pdf | Export agreement as PDF |
Health
| Method | Endpoint | Description |
|---|---|---|
GET | /api/health | Health check (no auth required) |
Self-Hosting
CLAHub can be self-hosted using Docker:
git clone https://github.com/DamageLabs/clahub.git
cd clahub
cp .env.docker.example .env
# Edit .env with your GitHub App credentials
docker compose up -d
Requirements
- Docker and Docker Compose
- A GitHub App (for PR checks and webhooks)
- Two GitHub OAuth Apps (owner and contributor)
What's Included
- Next.js application
- SQLite database (persisted in a Docker volume)
- Auto-migration on startup
- Health check endpoint for container monitoring
Database
CLAHub uses SQLite by default — a single file with zero configuration. The database is created automatically on first run.
To back up your data:
cp clahub.db clahub-backup-$(date +%Y%m%d).db
Prisma supports swapping to PostgreSQL if you need to scale.
Custom Branding
White-label your CLAHub instance with environment variables:
| Variable | Default | Description |
|---|---|---|
APP_NAME | CLAHub | Application name shown in the UI |
APP_LOGO_URL | (CLAHub logo) | URL to your logo image |
APP_PRIMARY_COLOR | #000000 | Primary brand color (hex) |
Troubleshooting
"UntrustedHost" error
Add to your .env:
AUTH_TRUST_HOST=true
NEXTAUTH_URL=https://your-domain.com
Rebuild: npm run build
PR checks not appearing
- Verify the GitHub App is installed on the repo/org
- Check that
GITHUB_APP_IDandGITHUB_APP_PRIVATE_KEYare set - Check webhook delivery in GitHub App settings → Advanced → Recent deliveries
OAuth login fails
- Verify callback URLs in your OAuth apps match your domain:
- Owner:
https://your-domain.com/api/auth/callback/github-owner - Contributor:
https://your-domain.com/api/auth/callback/github-contributor
- Owner:
- Verify
GITHUB_OWNER_CLIENT_ID,GITHUB_OWNER_CLIENT_SECRET,GITHUB_CONTRIBUTOR_CLIENT_ID,GITHUB_CONTRIBUTOR_CLIENT_SECRETare correct
Database errors
# Run migrations
npx prisma migrate deploy
# Verify database
sqlite3 clahub.db ".tables"
Repos/orgs not showing in dropdown
- The GitHub App must be installed on the account/org
- You must be signed in as an Owner (not Contributor)
- The Owner OAuth app needs
repo:status admin:repo_hook read:orgscopes
Webhook signature verification fails
Ensure GITHUB_WEBHOOK_SECRET in your .env matches the secret configured in your GitHub App settings.
CLAHub is maintained by DamageLabs. Source: github.com/DamageLabs/clahub. Licensed under MIT.