0094: Agents hand work to Claude Code and Codex

On this page

Status: accepted

Context

delegate_to_local (0086) lets an agent hand the writing of a change to Short Leash's small local model, saving its own tokens. Sometimes the right helper is a different, stronger agent instead: Claude Code handing a piece to Codex, or the reverse, because that agent is better at it. Many people already have both installed and signed in. Unlike the local model, these agents edit files and run commands themselves, and they send the project's code to Anthropic or OpenAI. Claude Code keeps its sign-in in the macOS login keychain, which leashd can't open: leashd is a LaunchDaemon outside the login session, and claude auth status run from it says signed out.

Decision

  • Two MCP tools, beside the local model's. delegate_to_claude and delegate_to_codex take a branch workspace (0082), a task, files to start from (a hint, not a limit, at most 20) and an optional model. They post to POST /v1/workspaces/{name}/hand-over. delegate_to_local is unchanged. Work is followed and stopped with the same local_work and stop_local_work, in the same list of the last 20 jobs, and one piece of handed-over work runs in each branch workspace at a time. All three tools are NeverInChat.
  • Off until turned on. [agents] claude and codex in config.toml both start false. Settings › Coding assistants (MCP) shows each agent's status (signed in, not installed, not signed in, can't check) and a switch that can be turned on only once the agent is signed in. While an agent is off, missing or signed out, the tool refuses with what to do and names delegate_to_local as the local alternative. Short Leash never falls back on its own: code goes to another company only when the agent asked for that one.
  • Finding them through their own commands. Short Leash looks for claude and codex on the login shell's PATH and runs --version, then claude auth status --json or codex login status, as the user, each limited to 15 seconds. It never opens their files (invariant 3) and never stores their sign-in.
  • Their own settings, plus what a headless run needs. The agent runs with the person's own permissions, sandbox and MCP servers. Short Leash adds only what an edit with nobody to ask needs: claude -p --output-format stream-json --verbose --permission-mode acceptEdits, and codex exec --json --sandbox workspace-write --color never --cd <folder> -. It never adds a flag that bypasses permissions or the sandbox. The model, when asked for, must be a plain name (letters, digits, .-_:, at most 64) and goes to --model or -m.
  • The task on standard input. The task, wrapped in a short prompt (which branch workspace it is, that another agent will review it, not to commit or push, to end with a summary), goes on the agent's standard input. It is never an argument, so nothing in it can become an option, and a Windows .cmd shim has nothing to quote. The environment is cleared down to PATH, HOME, USER, LOGNAME, LANG, TMPDIR and SHELL (on Windows, the profile and system folders), with nothing of Short Leash's own.
  • Where they run. Codex runs from leashd. Claude Code runs from the app: while the app is open it holds /v1/agents/runner open to leashd, a WebSocket like the voice helper's (0057), and leashd asks it to check or run Claude Code. leashd sends only the agent, the folder, the checked model and the prompt; the app finds the program and builds the command itself with the same leash_core::agents functions. With the app closed, Claude Code shows "Open Short Leash", and a run in progress fails when the app closes.
  • Following it. Each line of the agent's JSON output becomes a step ("Editing app/Order.php", "Running composer test"), its final message becomes the notes, and an error event or failed turn becomes the error. local_work shows the latest step and how many there were. Steps, notes and errors are outside text, with invisible characters removed and notes cut to 2,000 characters.
  • What it changed, by comparison. Before the run, Short Leash notes HEAD and the SHA-256 and line count of each file Git shows as changed or new in the site's folder. After it, a file counts as the agent's when its contents differ from before, or it's clean again, or it's in a commit the agent made. Files the person had already changed and the agent didn't touch don't count. At most 200 files are listed, with a count of the rest, and up to 20 of its commits. Git is only read, through the hardened runner (0034), and site_changes on the branch workspace shows the same diff.
  • Limits. Two pieces of work for coding agents at once, because an agent that loads Short Leash's MCP server could hand work on and on. Thirty minutes for one task. A stop or the time limit ends the agent's whole process group: asked first, killed five seconds later.
  • Short Leash Pro. It needs Pro, as its own feature, Feature::Agents, so a team policy can turn it off without turning off local AI (0093). No policy names it yet.
  • Everything else stays local. Chat, meeting summaries, Explain, Draft message, Review and the endpoint keep using only the local model (0080).

We chose separate tools over a setting that swaps the local model for a CLI, because the two do different jobs: the local model saves the caller's tokens, while another agent brings different strengths, and an agent should know which one it is asking. We let each agent keep its own settings rather than locking it to edits only, because people have already set those up the way they want, and a run that can't execute the tests can't check its own work. We compare snapshots rather than reading the agent's report of its edits, because a shell command can change files no edit event names.

Consequences

  • Handing work over sends the task and whatever files the agent reads to Anthropic or OpenAI, under the person's own account and terms. The setting is off until they turn it on, and the switch says where the work goes.
  • Unlike the local model, an agent writes as it goes, so a stop or a failure can leave changes behind. The work lists them and points to site_changes.
  • An agent's own settings decide what else it may do in the branch workspace: run commands, reach the network, use its MCP servers, even commit. Short Leash reports commits but doesn't prevent them, and a change outside the site's folder isn't listed.
  • codex login status can say signed in while the saved session has expired. The run then fails with Codex's own words and how to sign in again.
  • Claude Code needs the app open. Codex doesn't.
  • Their command-line flags and JSON events belong to them and can change. The parsing skips what it doesn't know, and each release checks both agents' current versions.