Skip to content

Execution workers

A worker is a process on a machine you control that takes an approved task from the board and carries it to done — with nobody at the keyboard.

claim → worktree → coding agent → clean-tree check → gates → push → PR → merge → done

Every step reports back to the task, so the task’s comment thread is the run log.

The worker talks to the app over REST with its own credential and never touches the database. The app can run in the cloud while the checkout sits on a laptop — and a machine executing agent-written code has no business holding database credentials.

A run only ships if every gate passes. They run cheapest first, and the first rejection stops the run.

Gate Rejects when
diff-size The diff is larger than the worker’s line or file limit.
protected-paths The change touches files a later step executes or loads as instructions — manifests, lockfiles, hooks, workflows.
test-presence Code changed but no test did.
build The build fails.
test-run The test suite fails.
review A second agent, with a clean context and only the diff in front of it, rejects the change.

A rejection is not a dead end: the branch is always pushed, a comment says which gate said no, and the task is routed to a review column for a person.

  • A usage limit returns the task to the queue with its attempt refunded — that is not the task’s failure.
  • A crash or timeout returns it to the queue and spends the attempt, so a task that keeps failing runs out of retries and lands in front of a human instead of cycling forever.

A worker needs four things before it can start, and nothing else from the environment:

Variable Required Default
CP_API_URL yes
CP_API_TOKEN or CP_API_TOKEN_FILE yes
CP_WORKER_NAME yes
CP_STATE_DIR no ~/.claudeplanner

The admin token is spent once, to register. Everything afterwards uses the credential registration hands back, stored in the state directory at mode 0600.

Registration assigns projects, but not a filesystem: the repository path an administrator proposes still has to be approved on the worker’s own machine. A path outside that allowlist leaves the project unbound and idle, with the reason visible in the fleet console — the worker’s other assignments keep working.

Terminal window
npm install
npm run build
npm start

On a Mac you usually want it as a background service rather than a terminal you must not close. A launchd plist ships with the worker:

Terminal window
cp launchd/com.claudeplanner.worker.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.claudeplanner.worker.plist

The plist carries paths for the machine it was written on — check its program arguments and PATH before loading it somewhere else. Logs land in /tmp. Unload it the same way to stop it, and note that both SIGTERM and SIGINT let the task in flight finish before the loop exits, so a stop is never a half-done run.

Everything else — base branch, poll interval, task timeout, diff caps, model — is policy set by an administrator in the fleet console, not by whoever starts the process. A policy change reaches a running worker on its next refresh, with no restart.

Policy Default
Base branch main
Poll interval 30 s
Task timeout 30 min
Max diff lines 400
Max diff files 10
  • Nothing merges unreviewed. The review gate is a second agent with no memory of writing the code, seeing only the diff.
  • Nothing executes before the static gates have read the diff. Protected paths are checked before the build gate runs anything, and installs run with lifecycle scripts disabled.
  • No subprocess inherits the worker’s secrets. The child environment is an allowlist, so the API token reaches neither the agent nor any dependency’s install script.
  • Nothing can hide from the gates. The worktree is checked for uncommitted files before the gates run, so an agent cannot dodge review by never staging a change.
  • A rejected branch is never lost. It is pushed before its worktree is discarded.
  • Abandoned worktrees are reaped — but only the worker’s own, under its own directory. Your checkout and your worktrees are left alone.

One worker process can serve several projects: it registers once, an administrator assigns it whichever projects it should work, and it claims from each assignment in turn.

The worker fleet