assign-to-claude
v0.1.4
Published
Connect any PM tool to Claude Code. Assign a ticket, get a PR.
Maintainers
Readme
assign-to-claude
Connect any PM tool to Claude Code. Assign a ticket, get a PR.
Generates the webhook server and GitHub Actions workflows to wire your project management tool to Claude Code. Assign a ticket to yourself — a branch is created, Claude implements the changes, CI runs, and a PR opens. Your machine doesn't need to be on.
Quick start
npx assign-to-claude initThe interactive CLI asks which PM tool and hosting platform you use, then generates all the files you need.
Prerequisites
Before running init, make sure you have:
- Node.js >= 20 —
node --versionto check - A GitHub repository with your project code
- A GitHub fine-grained PAT — create one here with these permissions:
- Contents: Read and write
- Pull requests: Read and write
- Actions: Read and write (needed for
repository_dispatch) - Issues: Read and write
- A Claude Code subscription with an OAuth token — run
claude setup-tokento generate one - A hosting account on Netlify, Vercel, or Cloudflare (not needed for GitHub Issues)
How it works
PM tool assigns ticket to you
|
v
Webhook fires to your server (Netlify / Vercel / Cloudflare)
|
v
Server verifies signature + checks trigger email
|
v
GitHub repository_dispatch fires
|
v
GitHub Actions: creates branch, runs Claude Code
|
v
Claude reads .claude/CLAUDE.md, implements the changes
|
v
PR opened with passing CIFor GitHub Issues — the webhook server is skipped entirely. GitHub Actions triggers directly on issues: assigned.
Step-by-step setup
Step 1: Run init
npx assign-to-claude initThe CLI will ask you:
- Which PM tool you use (Linear, Jira, Asana, ClickUp, or GitHub Issues)
- Where to host the webhook server (Netlify, Vercel, or Cloudflare) — skipped for GitHub Issues
- Your GitHub repo in
owner/repoformat - Your trigger email (the email in your PM tool that triggers the pipeline)
- Your site name (for the webhook URL)
Files are generated into your current directory. Existing files are never overwritten.
Step 2: Create a GitHub fine-grained PAT
- Go to github.com/settings/tokens?type=beta
- Click Generate new token
- Give it a name like
assign-to-claude - Set Repository access to your target repo
- Under Permissions, enable:
- Contents: Read and write
- Pull requests: Read and write
- Actions: Read and write
- Issues: Read and write
- Click Generate token and copy it
This token goes into your webhook server's environment variables as GITHUB_PAT.
Step 3: Get your Claude Code OAuth token
claude setup-tokenThis outputs a token. Add it as a GitHub Actions secret:
- Go to
github.com/<owner>/<repo>/settings/secrets/actions - Click New repository secret
- Name:
CLAUDE_CODE_OAUTH_TOKEN - Value: paste the token from
claude setup-token
Step 4: Deploy your webhook server
(Skip this step if you chose GitHub Issues — no server needed.)
# Install CLI
npm install -g netlify-cli
# Login and init
netlify login
netlify init
# Set environment variables
netlify env:set GITHUB_REPO "owner/repo"
netlify env:set GITHUB_PAT "ghp_your_token_here"
netlify env:set TRIGGER_EMAIL "[email protected]"
netlify env:set LINEAR_WEBHOOK_SECRET "$(openssl rand -hex 32)"
# Deploy
netlify deploy --prodYour webhook URL: https://YOUR_SITE.netlify.app/api/webhook
# Install CLI
npm install -g vercel
# Login and link project
vercel login
vercel
# Set environment variables (prompted for values)
vercel env add GITHUB_REPO
vercel env add GITHUB_PAT
vercel env add TRIGGER_EMAIL
vercel env add LINEAR_WEBHOOK_SECRET
# Deploy
vercel --prodYour webhook URL: https://YOUR_SITE.vercel.app/api/webhook
# Install CLI
npm install -g wrangler
# Login
wrangler login
# Set secrets (prompted for values)
wrangler secret put GITHUB_REPO
wrangler secret put GITHUB_PAT
wrangler secret put TRIGGER_EMAIL
wrangler secret put LINEAR_WEBHOOK_SECRET
# Deploy
wrangler deployYour webhook URL: shown after deploy (e.g. https://claude-pipeline-webhook.YOUR_SUBDOMAIN.workers.dev)
Note: Replace
LINEAR_WEBHOOK_SECRETwith the correct secret name for your PM tool:LINEAR_WEBHOOK_SECRET,JIRA_WEBHOOK_SECRET,ASANA_WEBHOOK_SECRET, orCLICKUP_WEBHOOK_SECRET.
Step 5: Create a webhook in your PM tool
- Go to Linear → Settings → API → Webhooks → New webhook
- URL:
https://YOUR_SITE.netlify.app/api/webhook(or your Vercel/Cloudflare URL) - Secret: paste the same value you used for
LINEAR_WEBHOOK_SECRET - Events: check Issue updates only — uncheck everything else
- Click Create webhook
- Go to Jira → Settings → System → Webhooks → Create webhook
- URL:
https://YOUR_SITE.netlify.app/api/webhook - Events: check Issue updated → make sure Assignee changed is included
- Set a webhook secret and use the same value for
JIRA_WEBHOOK_SECRETin your server env
Asana doesn't have a webhook UI. Create one via the API:
curl -X POST https://app.asana.com/api/1.0/webhooks \
-H "Authorization: Bearer YOUR_ASANA_PAT" \
-d "resource=YOUR_PROJECT_GID&target=https://YOUR_SITE.netlify.app/api/webhook"The response includes an X-Hook-Secret header. Copy that value and set it as ASANA_WEBHOOK_SECRET in your server environment.
- Go to ClickUp → Settings → Integrations → Webhooks → Add webhook
- URL:
https://YOUR_SITE.netlify.app/api/webhook - Events: select taskAssigneeUpdated only
- Copy the webhook secret and set it as
CLICKUP_WEBHOOK_SECRETin your server env
Nothing to do here. The generated workflow triggers directly when an issue is assigned to you. No webhook server, no extra configuration.
Step 6: Create .claude/CLAUDE.md
Create a file at .claude/CLAUDE.md in your repo. Claude reads this at the start of every automated task. Include:
# Project Context
## Stack
- Next.js 14, TypeScript, Tailwind CSS
- PostgreSQL with Prisma ORM
- Jest for testing
## Conventions
- Use `src/` directory structure
- All components in `src/components/`
- API routes in `src/app/api/`
## CI Commands
- Lint: `npm run lint`
- Test: `npm test`
- Build: `npm run build`
## Rules
- Always run lint and tests before committing
- Write tests for new features
- Use conventional commit messagesCustomize this for your project. The more specific you are, the better Claude's output.
Step 7: Push and test
git add .
git commit -m "feat: add claude pipeline"
git push origin mainNow assign a ticket to yourself in your PM tool. Within seconds:
- The webhook fires
- A GitHub Action starts
- Claude creates a branch, implements the changes, runs CI
- A PR opens targeting
main
Generated files
| File | Purpose |
|---|---|
| netlify/functions/webhook.ts (or vercel/cloudflare equivalent) | Receives PM tool webhook, verifies signature, dispatches to GitHub |
| .github/workflows/claude-pipeline.yml | Creates branch, runs Claude Code, opens PR |
| .github/workflows/claude-pr-review.yml | Handles @claude feedback on PRs |
| netlify.toml (or vercel.json / wrangler.toml) | Platform routing config |
| .env.example | Required environment variables with descriptions |
No runtime dependency on this package — the generated files work independently forever.
Environment variables
Webhook server (Netlify / Vercel / Cloudflare)
| Variable | Required | Description |
|---|---|---|
| GITHUB_REPO | Yes | Your repo in owner/repo format |
| GITHUB_PAT | Yes | Fine-grained PAT with contents/PRs/actions/issues write |
| TRIGGER_EMAIL | Recommended | Only trigger when the ticket is assigned to this email |
| LINEAR_WEBHOOK_SECRET | Linear only | Secret from Linear webhook settings |
| JIRA_WEBHOOK_SECRET | Jira only | Secret you set when creating the Jira webhook |
| ASANA_WEBHOOK_SECRET | Asana only | X-Hook-Secret returned when creating the Asana webhook |
| CLICKUP_WEBHOOK_SECRET | ClickUp only | Secret from ClickUp webhook settings |
GitHub Secrets (repository settings)
| Variable | Required | Description |
|---|---|---|
| CLAUDE_CODE_OAUTH_TOKEN | Yes | From claude setup-token — never put this in your .env file |
Supported tools and platforms
| PM Tool | Trigger | Webhook needed? | |---|---|---| | Linear | Issue assigned | Yes | | Jira | Issue assignee changed | Yes | | Asana | Task assigned | Yes | | ClickUp | Task assignee added | Yes | | GitHub Issues | Issue assigned | No — built into GitHub Actions |
| Hosting Platform | Config file | Webhook path |
|---|---|---|
| Netlify | netlify.toml | netlify/functions/webhook.ts |
| Vercel | vercel.json | api/webhook.ts |
| Cloudflare Workers | wrangler.toml | src/worker.ts |
Features
- Model selection — add a
quick-fixlabel to your ticket and Claude uses Sonnet (faster, cheaper). Without it, Claude uses Opus (most capable). - PR review — comment
@claudeon any PR to get Claude to address feedback, fix issues, and push. - Auto env detection — if you have a
.envfile withLINEAR_API_KEY,JIRA_API_TOKEN, etc., the CLI auto-detects your PM tool. - Skip existing files — running
initagain won't overwrite files you've already customized. - CI-safe — if installed as a devDependency, it detects CI environments and exits cleanly without prompting.
Upgrading
This package is a code generator — it creates files in your repo and has no runtime dependency. When you run npx assign-to-claude init, npx always fetches the latest version.
If we release improvements to the generated workflow files or webhook handlers, your existing files won't update automatically. To get the latest generated files:
# Regenerate all files (overwrites existing ones)
npx assign-to-claude init --forceWarning:
--forcewill overwrite your existing generated files. Any manual changes you made to those files will be lost.
If you only want to update specific files, delete them first and re-run init without --force:
rm .github/workflows/claude-pipeline.yml
npx assign-to-claude initTroubleshooting
Webhook not firing
- Verify your webhook URL is correct and ends with
/api/webhook - Check that the webhook secret in your PM tool matches the one in your server env
- Confirm you selected the right events (e.g., "Issue updated" for Linear, not "Issue created")
- Check your server logs:
netlify logs/ Vercel dashboard /wrangler tail
GitHub Action not running
- Make sure
CLAUDE_CODE_OAUTH_TOKENis set in GitHub Secrets (Settings → Secrets → Actions) - Verify your
GITHUB_PAThas the correct permissions (contents, PRs, actions, issues — all write) - Check that the PAT has access to the specific repository
- Look at the Actions tab in your repo for error details
Wrong person triggers the pipeline
- Set
TRIGGER_EMAILin your webhook server env to your email - For GitHub Issues, the workflow checks
github.event.assignee.loginagainstgithub.actor
"Invalid signature" errors
- The webhook secret must be identical in both your PM tool and your server env
- Make sure you didn't add extra whitespace when copying
- For Asana: the secret comes from the
X-Hook-Secretheader in the handshake response
Claude doesn't follow project conventions
- Create or update
.claude/CLAUDE.mdwith your stack, conventions, and CI commands - Be specific — list exact commands for linting, testing, and building
License
MIT
