太刀tachi-agent · run_coding_agent

Claude coordinates. Other CLIs do the typing.

The tachi-agent-mcp front-end lets a Claude Code session delegate bounded coding tasks to external CLI agents while Claude stays the coordinator. Every result comes back with a public trace and, optionally, a dokoro handoff. Review is the default and is safe; write mode is opt-in.

Six workers, one tool

Codex, Grok, Gemini, Claude, Hermes, OpenRouter.

Each call spawns a real local CLI process. The result carries the answer, a public trace and an optional Dokoro handoff to the coordinator.

agent: "codex"
codex
Codex CLI (codex exec --json) — structured public events: reasoning summaries, commands, file changes, plans.
agent: "grok"
grok
Grok CLI — read-only sandbox in review mode.
agent: "gemini"
gemini
Gemini CLI headless — review isolated in a throwaway worktree with a tamper guard.
agent: "claude"
claude
Headless Claude Code (claude -p) — the “vice versa” worker.
agent: "hermes"
hermes
Hermes Agent — file, terminal and skill toolsets in an isolated worktree.
agent: "openrouter"
openrouter
Any OpenRouter model (GLM, Kimi, DeepSeek, Qwen, …) through one private, swappable harness.
Setup

Build it, then mount it in .mcp.json.

Run npm install && npm run build, then register dist/frontends/mcp-server.js in the target repository's .mcp.json. TACHI_CODING_ROOTS is a comma-separated allowlist: requested working directories are resolved through real paths and rejected when they escape those roots.

For a reusable bridge, create a project subagent in .claude/agents/, scope mcpServers to tachi-agent, and allow only mcp__tachi-agent__run_coding_agent. The bridge forwards the full task once and returns the worker result without implementing the task itself.

.mcp.jsonjson
1{
2 "mcpServers": {
3 "tachi-agent": {
4 "type": "stdio",
5 "command": "node",
6 "args": ["/absolute/path/to/tachi-agent/dist/frontends/mcp-server.js"],
7 "env": {
8 "TACHI_CODING_ROOTS": "/absolute/path/to/allowed/repository",
9 "TACHI_OPENROUTER_CODING_MODEL": "qwen/qwen3-coder"
10 }
11 }
12 }
13}
The tool

run_coding_agent inputs.

InputPurpose
agentcodex, grok, gemini, claude, hermes, or openrouter
taskComplete worker prompt, including acceptance criteria.
cwdRepository under TACHI_CODING_ROOTS.
modereview for read-only / isolated analysis; write for explicit implementation.
modelOptional model override. OpenRouter falls back to TACHI_OPENROUTER_CODING_MODEL, then OPENROUTER_MODEL.
visibilityfinal, trace (default), or live.
plannedFilesExact files to lease through Dokoro before edits.
reportToDokoroPersist a directed handoff; defaults to true.
targetAgentHandoff recipient; defaults to claude-code.
visibility
final
Returns only the final worker answer.
visibility · default
trace
Also returns a compact public execution trace after completion.
visibility
live
Sends MCP notifications/progress while the worker runs, and still returns the completed trace. Raw private chain-of-thought is never exposed.
Security posture

Hardened against an injected task.

Workers run as real local processes, so the tool keeps an injected task — or untrusted repository content — from escalating.

Review is the default, and safe
Read-only for Codex / Grok (sandbox flags) and Claude (--permission-mode plan), worktree-isolated for Hermes / OpenRouter / Gemini. Auto-approve flags are emitted only in write mode.
Gemini review is contained twice
Runs in a throwaway detached-HEAD git worktree and a post-run tamper guard fails the run on file changes or mutating tool calls — so the Gemini reviewer sees HEAD, not uncommitted changes.
Recursion is refused
Every worker env carries TACHI_CODING_DEPTH=1; a tachi-spawned worker can't spawn workers. The Claude worker also gets --strict-mcp-config.
Write mode is opt-in
mode: "write" is refused unless TACHI_CODING_ALLOW_WRITE=1 is set on the server.
Minimal worker environment
The full process.env is not inherited — each worker gets OS basics plus only its own credential. Add passthrough names with TACHI_WORKER_ENV_ALLOW.
Auth preflight
The binary and a usable credential are verified before spawning; a missing key fails fast with an actionable error. tachi-agent doctor reports the same readiness per agent.
Bounded concurrency
In-flight workers are capped by TACHI_CODING_MAX_CONCURRENCY (default 3); extra calls queue for a slot.
Advisory leases, surfaced
Dokoro file leases for plannedFiles are advisory; an unconfirmed lease shows as ⚠ leases unconfirmed, never implied exclusivity.
Env varEffect
TACHI_CODING_ROOTSComma-separated realpath allowlist for cwd (default: MCP server cwd).
TACHI_CODING_ALLOW_WRITE1 / true to permit write mode (default: disabled).
TACHI_CODING_MAX_CONCURRENCYMax concurrent workers, clamped 1–16 (default 3).
TACHI_WORKER_ENV_ALLOWExtra env var names to pass through to workers.
TACHI_OPENROUTER_HARNESSPrivate harness behind agent: "openrouter": hermes (default) or codex.
TACHI_CODING_AGENTSComma-separated agents for doctor to probe (default: all six).
OpenRouter coding agents

Any model, one stable adapter.

agent: "openrouter" is the generic multi-provider lane: any OpenRouter model runs as a coding worker, with no per-vendor worker types. With the default hermes harness it keeps Hermes toolsets, checkpoints destructive file operations and uses a git worktree by default; isolate: false is honored only for an authorized write task.

Swap the harness with TACHI_OPENROUTER_HARNESS=hermes|codex — any other value fails closed. The codex harness points Codex CLI at OpenRouter through process-local overrides (never touching ~/.codex/config.toml) and streams its structured JSONL events. Compare both with npm run eval:openrouter-harness.

prerequisitesshell
1export OPENROUTER_API_KEY="..."
2export TACHI_OPENROUTER_CODING_MODEL="qwen/qwen3-coder"
3export HERMES_CLI="/absolute/path/to/hermes" # optional when hermes is on PATH
example tool argumentsjson
1{
2 "agent": "openrouter",
3 "model": "qwen/qwen3-coder",
4 "task": "Implement the bounded change, run focused tests, and report modified files.",
5 "cwd": "/absolute/path/to/repository",
6 "mode": "write",
7 "isolate": false,
8 "visibility": "live",
9 "plannedFiles": ["src/example.ts", "src/example.test.ts"],
10 "reportToDokoro": true,
11 "targetAgent": "claude-code"
12}
agent: "gemini"
Gemini worker
Headless gemini -p … --output-format json. Review uses --approval-mode plan inside a throwaway worktree; write (gated) uses --yolo on the requested checkout. Credentials: GEMINI_API_KEY, GOOGLE_API_KEY, GOOGLE_APPLICATION_CREDENTIALS, or a cached OAuth login; Vertex mode also needs GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION. Install with npm i -g @google/gemini-cli; override with GEMINI_CLI.
agent: "claude"
Claude worker
Headless claude -p … --output-format json --strict-mcp-config. Review uses --permission-mode plan and returns the extracted plan; write (gated) uses --permission-mode acceptEdits — headless runs deny Bash-class calls, so a degraded run is flagged ⚠ N tool call(s) denied. Credentials: ANTHROPIC_API_KEY or an existing claude login. Override with CLAUDE_CLI.
Billing. Grok workers use the grok.com login session by default (SuperGrok pool), which takes precedence over XAI_API_KEY; Codex workers currently bill the ChatGPT-plan login. To force API billing for Grok, provide XAI_API_KEY and point GROK_HOME at a directory with no session file. The Grok --disallowed-tools flag needs grok CLI ≥ 1.0.13.
Vice versa

Use it from Codex, Gemini or Grok, too.

tachi-agent-mcp is a standard stdio MCP server, so the same run_coding_agent works from other CLIs — including delegating to headless Claude Code (agent: "claude").

Run one server instance per client, each with its own env block. TACHI_CODING_ALLOW_WRITE=1 grants write mode to every model that can reach that instance — set it only where you trust the author. The recursion guard keeps these mounts from chaining.

Every concurrent call is a separate process; give each worker disjoint files or an isolated worktree, and use plannedFiles so Dokoro can detect conflicting leases before edits begin.

~/.codex/config.tomlenv
1# Codex CLI — ~/.codex/config.toml
2[mcp_servers.tachi-agent]
3command = "node"
4args = ["/absolute/path/to/tachi-agent/dist/frontends/mcp-server.js"]
5env = { TACHI_CODING_ROOTS = "/absolute/path/to/allowed/repository" }
~/.gemini/settings.jsonjson
1// Gemini CLI — ~/.gemini/settings.json (Grok CLI uses the same mcpServers shape)
2{
3 "mcpServers": {
4 "tachi-agent": {
5 "command": "node",
6 "args": ["/absolute/path/to/tachi-agent/dist/frontends/mcp-server.js"],
7 "env": { "TACHI_CODING_ROOTS": "/absolute/path/to/allowed/repository" }
8 }
9 }
10}