Skip to content

Linear issue to pull request

This guide takes you from nothing to this loop:

  1. You add the label jimothy to a Linear issue.
  2. Jimothy picks it up, moves it to In Progress and comments on it.
  3. Claude Code (Opus) writes a plan, Claude Code (Sonnet) implements it on a fresh branch in its own git worktree, your tests run, and Codex reviews the diff. Failed tests or a changes requested review send the work back to the implementer, up to twice each.
  4. You get a notification, look at the change, and click Approve.
  5. Jimothy pushes the branch and opens a pull request with gh, then comments the run summary and PR link on the Linear issue and moves it to In Review.

Budget about 20 minutes for setup.

  • Jimothy installed (Installation).
  • A local git clone of the repository the work happens in, with an origin remote on GitHub, and a working test command (e.g. npm test).
  • Claude Code installed and signed in: npm i -g @anthropic-ai/claude-code, then run claude once.
  • OpenAI Codex CLI installed and signed in: npm i -g @openai/codex, then codex login. (No Codex? You can switch the review step to Claude Code; see step 4.)
  • The GitHub CLI (gh) installed.
  • A Linear workspace where you can create a personal API key.
  1. Open Jimothy and go to Harnesses.
  2. Click Re-detect.
  3. Claude Code and OpenAI Codex CLI should show a green check and a version. If one says "claude" not found on PATH, run which claude in a terminal and add that directory to Settings → Execution → Extra PATH entries, save, and re-detect. See Auto-detection.

The final step of the pipeline runs this in the run’s worktree:

Terminal window
git push -u origin HEAD && gh pr create --base {{run.baseBranch}} --head {{run.branch}} \
--title "$FACTORY_ISSUE_KEY: $FACTORY_ISSUE_TITLE" \
--body "Automated by Jimothy run #$FACTORY_RUN_NUMBER. $FACTORY_ISSUE_URL"

Jimothy runs git with GIT_TERMINAL_PROMPT=0, so pushing must work without a password prompt. Set that up once:

Terminal window
gh auth login # choose GitHub.com, HTTPS or SSH, and authenticate
gh auth setup-git # lets git use gh's credentials for HTTPS remotes
cd ~/code/web-app && git push --dry-run # should not ask for anything

If you’d rather use a token, put GH_TOKEN=… in Settings → Execution → Environment variables (a token that can push to the repo and create pull requests).

  1. In Linear, open Settings → Account → Security & access → Personal API keys and create a key named Jimothy. Grant Read and Write (write is needed to comment and change states), and access to the team you’ll use. Copy the key (lin_api_…).
  2. In Jimothy, open Accounts and click Linear.
  3. Paste the key into API key. Leave Account name empty to name it after you, or call it Linear (work).
  4. Click Sign in. The account card shows signed in with your name and workspace.

Details: Accounts, Linear.

  1. Go to Pipelines → New pipeline.
  2. Under Or start from a template, click Feature: Plan → Build → Review → PR. The pipeline editor opens.
  3. Click Pipeline settings at the top of the step list.
  4. In Workspace, keep Git worktree selected and set Local repository to your clone (type the path or click Browse). Check Base branch (main) and keep the Branch name template jimothy/{{issue.key | slug}}: issue ENG-123 becomes branch jimothy/eng-123.
  5. In Variables, set testCommand to your project’s test command, e.g. npm test, pnpm test --run or pytest -q.
  6. Select the Cross-model review step. Under Harness & model → Model, pick a model from the list or Default (the template’s gpt-5-codex may not exist in your Codex). Without Codex, switch Harness to Claude Code and pick opus.
  7. Press ⌘S (or Save).
# Step Type Harness · model Key settings
1 Plan Agent Claude Code · opus Writes a Markdown plan and must not modify files. Timeout 20 min.
2 Implement Agent Claude Code · sonnet Gets the plan as {{steps.plan.output}} and, on a second pass, the reviewer’s feedback. Must commit, referencing the issue key. Timeout 60 min, 1 retry.
3 Run tests Shell — {{vars.testCommand | raw}}. On failure, loops back to Implement (max 2). Timeout 20 min.
4 Cross-model review Agent OpenAI Codex CLI Reviews git diff {{run.baseBranch}}...HEAD and ends with VERDICT: APPROVE or VERDICT: CHANGES_REQUESTED. Passes only if the output matches VERDICT:\s*APPROVE; otherwise loops back to Implement (max 2). Timeout 20 min.
5 Human approval Approval — Approve to push {{run.branch}} and open a pull request for {{issue.key}}.
6 Open pull request Shell — Push and gh pr create (above). Timeout 5 min.

The pipeline’s Max concurrent runs is 2, so at most two Linear issues are worked on at once (each in its own worktree). More wait in the queue.

Before connecting Linear, run the pipeline once on a small, real task so you can sort out tooling problems without an issue involved.

  1. In the pipeline editor, click Run (or press ⌘N anywhere).
  2. Enter a Task title such as Add a /healthz endpoint that returns 200 and optionally an Issue key like TEST-1.
  3. Click Start run.

If the run fails in Setup & run log, fix the workspace (see Troubleshooting). When it reaches Human approval, you can Reject it to stop, or approve and let it open a PR you then close.

  1. Go to Triggers → Add trigger → Linear.

  2. Name: Linear: ENG. Runs pipeline: Feature: Plan → Build → Review → PR. Linear account: the account from step 3.

  3. Team key: your team’s key, e.g. ENG. Labels (any of): jimothy (already filled in).

  4. States: leave empty to match any open issue, or restrict to where hand-offs happen, e.g. Todo.

  5. Poll every (seconds): 60 is a reasonable start (minimum 15).

  6. Under Write back to the issue:

    • Run starts: Comment on, transition In Progress
    • Succeeds: Comment on, transition In Review
    • Fails: Comment on, transition empty (or Todo)

    Use your team’s exact state names.

  7. Click Preview matching issues. It should say Connected and list the issues that would start runs right now. Every issue listed will start a run as soon as you save, so if you see issues you don’t want worked on, remove their label or tighten the filter first.

  8. Click Save trigger. The trigger card shows live.

Details: Linear trigger, Write-back.

In Linear, open an issue on that team, make sure its description says what “done” means, and add the label jimothy.

Within one poll interval (click Check now on the trigger to skip the wait) you’ll see:

  • a new run on the Dashboard under In progress;
  • the issue moved to In Progress with a comment: 👋 Jimothy started run #7 (Feature: Plan → Build → Review → PR).

The issue is now remembered by the trigger and won’t start another run, even though it still has the label. See Polling & dedup.

Click the run. You’ll see:

  • The graph with each step lighting up as it runs; loops appear as amber arcs.
  • Setup & run log: git fetch origin main, git worktree add -b jimothy/eng-123 …, then Workspace ready: …/workspaces/run-7-eng-123 (branch jimothy/eng-123).
  • Plan: select it and open Logs to follow Claude Code’s tool calls (Read: src/…, Grep: …), thinking and the final result line with cost. Output shows the plan rendered as Markdown. Prompt shows exactly what was sent.
  • Implement: edits, test runs and a commit in the logs.
  • Run tests: your test command’s output.
  • Cross-model review: Codex’s commands and its verdict. If it says VERDICT: CHANGES_REQUESTED, the step fails its verdict and the log shows ↺ Cross-model review requested another pass: looping back to "implement" (1/2). Implement runs again with the review in its prompt (the step list shows loop 1), then tests and review run again.

The header’s Cost and Tokens update as steps finish.

When the review passes, the run stops at Human approval:

  • a desktop notification Approval needed · run #7 (click it to open the run);
  • the Dashboard’s Needs your approval card and the ✋ badge in the sidebar and tray.

Before approving, look at the change:

  • click Open workspace in editor (</>) in the run header to open the worktree in VS Code or Cursor, or
  • in a terminal: cd to the workspace path shown in the run log and run git log --oneline main..HEAD and git diff main...HEAD.

Then type an optional comment in the banner and click Approve. (Or Reject to fail the run; the comment is recorded.)

Open pull request pushes jimothy/eng-123 and runs gh pr create. gh prints the PR URL, which Jimothy detects:

  • a PR #57 button appears in the run header;
  • the run’s success notification and the Linear comment include it:
✅ Jimothy run #7 succeeded (Feature: Plan → Build → Review → PR) in 21m 40s · $1.84
Branch: jimothy/eng-123
PR #57: https://github.com/acme/web-app/pull/57
✓ Plan
✓ Implement
✓ Run tests
✓ Cross-model review
✓ Human approval
✓ Open pull request
  • the issue moves to In Review.

If Linear’s GitHub integration is enabled, the PR also links itself to the issue because the title starts with the issue key.

<data folder> e.g. ~/Library/Application Support/Jimothy/factory on macOS
├── runs/run_…/
│ ├── run.json run record: steps, outputs, prompts, cost, links
│ └── logs/ one JSONL log per step attempt
└── workspaces/run-7-eng-123/ the git worktree on branch jimothy/eng-123

The worktree stays after the run, so you can inspect it or retry. To remove worktrees of successful runs automatically, enable Settings → Delete a run’s workspace after it succeeds (branches are kept).

  • A step fails: the run page shows the error in red. Fix the cause (a prompt, the test command, a harness setting), then click Retry from here on that step. The run continues in the same worktree with the updated pipeline. See Runs.
  • Tests keep failing after two loops: the run fails with (feedback loop limit of 2 reached), Linear gets a ❌ comment, and the branch stays for you to finish by hand.
  • gh pr create says there are no commits: the implementer didn’t commit. Make sure the prompt asks it to commit (the template does), or add a shell step before the PR that commits: git add -A && git commit -m "$FACTORY_ISSUE_KEY: $FACTORY_ISSUE_TITLE" || true.
  • git push fails with a credentials error: redo step 2.
  • Write-back errors (e.g. Linear workflow state "In Reveiw" not found) show on the trigger card and as a notification; the run itself is unaffected.

More in Troubleshooting.