Yet another Contributor License Agreement Manager with webhooks and whatnot.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Yet another Contributor License Agreement Manager with webhooks and whatnot.

Designed to be dead-simple™, Clam helps you manage a single CLA for your GitHub organisation.

The aim is to make it easy...

  • (a) for maintainers to merge compliant contributions
  • (b) for contributors to ensure they're compliant

Using webhooks Clam checks the contributors of a pull request against its signatory database and sets the status of the branch HEAD commit accordingly. GitHub lovingly renders this useful information for you right there in the pull request.

Remember this tool only provides guidance. Clam will not fix your bugs for you. Neither will it do the washing up.

A couple of exemptions apply, neither of which will trigger a failure:

  1. Anyone with who is a member of your GitHub organisation (public or private)
  2. Any collaborators with push access to the repository

Both of these groups are considered to be inside the circle of trust.


To keep things simple, I've hardcoded the organisation name and opted to use a personal access token to authorise calls to the GitHub API where necessary. Set CLAM_GITHUB_ORG and CLAM_GITHUB_TOKEN accordingly. The personal access token requires the repo scope to set commit statuses and query repo collaborators. The user to which the personal access token belongs should also be a member of CLAM_GITHUB_ORG.

To authenticate signatories you'll need to register for a new developer application and set the values of CLAM_GITHUB_CLIENT_ID and CLAM_GITHUB_CLIENT_SECRET accordingly. Access to private information is not required; This process is in place simply to ensure that signatories can only sign for GitHub accounts that they have access to, therefore only the username is stored after authentication. For the callback url use the /_auth endpoint, for example

Last, but by no means least, make sure you've got your CLA checked into the root of the repository as CLA.<extension>. I've enlisted the help of GitHub Markup to render HTML so the CLA can have any extension listed there including none at all (e.g.


Clam was designed to be run on Heroku.

$ git clone
$ cd clam
$ heroku create clam-example-57 # clam-example-57 is just an example!
$ heroku addons:create heroku-postgresql
$ heroku config:set CLAM_GITHUB_ORG=mcneel
$ heroku config:set CLAM_GITHUB_TOKEN=your_github_access_token_with_repo_scope
$ heroku config:set CLAM_GITHUB_CLIENT_ID=your_application_client_id
$ heroku config:set CLAM_GITHUB_CLIENT_SECRET=your_application_client_secret
$ git push heroku master
$ heroku run python
>>> from clam import db
>>> db.create_all()
Use exit() or Ctrl-D (i.e. EOF) to exit

Now add a webhook to your favorite repository and tell it to send "pull request" events.

Local testing

For local testing I use Foreman.

$ git clone
$ cd clam
$ virtualenv venv
$ . venv/bin/activate
$ pip install -r requirements.txt
$ foreman run python

Don't forget to add the required environment variables (see Heroku) to .env.

Running python in this way creates a local sqlite database for testing.

Tips for spoofing a pull request with curl (for my own notes, really)...

curl -d @test/pull.json -H "Content-Type: application/json" -X POST localhost:5000/_github