Skip to content Skip to content

Connect an agent to a GitHub repo and have it open PRs

Wire a coding agent to a real GitHub repo so every issue you assign produces a branch, a working commit, and a pull request, all visible in both the Paperclip issue thread and the GitHub PR page.

On Paperclip.inc your agents run in cloud-managed environments. You don’t provision a machine or install anything: you point a project workspace at the right repo, give the agent a credential it can use to push, and tell it (via AGENTS.md) to work in PRs.

Paperclip issue GitHub
┌──────────────────────┐ ┌─────────────────────┐
│ assign to coder │ │ branch + commits │
│ status: in_progress │ git push + │ PR opened by agent │
│ comments mirror PR │◀──gh pr create──▶│ CI checks run │
│ status: in_review │ API webhook │ reviewer approves │
│ status: done │ │ PR merged │
└──────────┬───────────┘ └──────────┬──────────┘
│ │
└────────── isolated git worktree ─────────┘
(one per Paperclip issue)

Paperclip provisions an isolated git worktree when the issue is checked out: a normal git clone on its own branch. Pushes go to the upstream remote you configured on the project workspace.

  • A coding agent already hired. See Hire Your First Agent.
  • A GitHub repo you have push access to, and the ability to issue a fine-grained Personal Access Token or install a GitHub App against it.

The execution workspace gives the agent its working directory, the upstream repoUrl, and the base branch to branch off. Set it on the project, not the agent, so every agent assigned to the project inherits the same git context.

Open Projects → {project} and set or create a workspace with:

FieldValueNotes
repoUrlhttps://github.com/acme/api.gitThe HTTPS clone URL. Used to link out and to set the worktree upstream.
repoRef (base)mainThe branch new worktrees branch off.
Workspace modeIsolatedOne git worktree per issue. This is what makes parallel PRs work without conflicts.

Isolated mode is what turns on per-issue worktrees. Without it every agent runs against one shared checkout and you lose the parallel-PR story. See Workspaces for the full field list.

The agent needs a credential to git push and to run gh pr create. Store it as a company secret on the Secrets page under Company Settings (/company/settings/secrets), then reference it from the agent’s adapter config so it is injected at run time, never sitting in a JSON file.

Option A: Personal Access Token (fast path)

Section titled “Option A: Personal Access Token (fast path)”
  1. GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token.
  2. Repository access: Only select repositories, pick the one repo.
  3. Permissions: Contents: Read and write, Pull requests: Read and write, Metadata: Read-only (auto-set).
  4. Generate, copy the github_pat_... value once, and save it as a company secret.

Then reference the secret on the coder agent’s adapter config:

"env": {
"GH_TOKEN": { "type": "secret_ref", "secretId": "<secret-id>", "version": "latest" },
"GITHUB_TOKEN": { "type": "secret_ref", "secretId": "<secret-id>", "version": "latest" }
}

gh reads GH_TOKEN; git’s HTTPS helper reads GITHUB_TOKEN. Setting both means git push works without an extra credential helper.

Tradeoff: PATs are tied to a user. If that user leaves, the token rots and the agent stops being able to push.

A GitHub App installed on the org issues short-lived installation tokens, isn’t tied to any one human, and shows up as its own author on the PR.

  1. Org Settings → Developer settings → GitHub Apps → New GitHub App.
  2. Permissions: Contents: Read and write, Pull requests: Read and write. No webhook needed.
  3. Generate a private key, download the .pem. Note the App ID and the installation ID for the target repo.
  4. Store the App ID, installation ID, and private key as company secrets, and have the agent exchange them for an installation token at the start of each run.

Tradeoff: more moving parts. Worth it the moment you have more than one coding agent or you care about audit trails.

The agent’s AGENTS.md is what turns “do the task” into “do the task on a branch and open a PR”. You need three rules in the entry file the agent reads on every heartbeat. See Agents for the full bundle layout; this snippet drops into the working-rules section of AGENTS.md for any coder role.

## Working rules: PR-driven
You always work on a feature branch, never on `main` directly. Paperclip provisions an isolated git worktree per issue; that worktree is already on the right branch when you check the issue out.
Before you exit a heartbeat:
1. **Commit your changes.** One conventional-commit message per logical change.
`git add -A && git commit -m "fix(api): handle null org ids on signup"`
2. **Push the branch.**
`git push -u origin HEAD`
3. **Open a PR if one doesn't exist.** Use `gh pr create --fill --base main` and copy the resulting URL into the issue thread.
4. **Move the issue to `in_review`** when the PR is up and CI is green.
If CI fails, do not merge. Re-open the task, fix the failure, push another commit on the same branch, and tell the reviewer what changed.
Never use `--no-verify`, `git push --force` to a shared branch, or `gh pr merge --admin`. If you can't pass CI, mark the issue `blocked` and name the failing check.

Create an issue and assign it to the coder agent. Within a heartbeat or two:

  • The agent checks the issue out and Paperclip switches its worktree to a fresh branch off main.
  • The agent edits the right files, runs the test suite, commits, and pushes.
  • The agent calls gh pr create --fill --base main and pastes the resulting PR URL into the Paperclip issue thread.
  • The issue moves to in_review.

If you see the worktree path on disk but no commits, that’s almost always a missing GITHUB_TOKEN. See Troubleshooting below.

You have two parallel review surfaces. Use them for different things.

SurfaceWhat you do here
GitHub PRRead the diff, comment line-by-line, watch CI, request changes. The coder agent is configured (Step 4) to refuse merging on its own.
Paperclip issueTrack status (in_reviewdone), pipe approvals to chat, link the PR to the goal/project, gate the next step.

When the PR merges, a human (or your CI’s auto-merge bot) merges through GitHub, and a reviewer moves the Paperclip issue to done with the merge SHA. If you want Paperclip to move it automatically, set up a GitHub → Paperclip routine webhook that listens to pull_request.closed with merged: true and PATCHes the linked issue.

Permission denied (publickey) on push. The worktree’s remote is HTTPS, but the agent’s environment doesn’t have GITHUB_TOKEN set. Check the agent’s adapter config and confirm the env block resolves the secret.

gh: command not found. The managed environment running the agent doesn’t have the GitHub CLI on PATH. Make sure the runtime image includes gh.

Merge conflicts on the agent’s branch. A coder agent should refuse to resolve conflicts blindly: it should mark the issue blocked with a comment naming the conflicting files, and a human or senior reviewer rebases or resolves.

CI fails but the agent moved the issue to in_review anyway. Tighten the rules in AGENTS.md (Step 4): move to in_review only after gh pr checks --watch exits 0.

For deeper heartbeat-level debugging, see Debug a stuck heartbeat.