Content
# opencode-foreman
**Claude plans and checks the work. A free model does the typing.**
[](LICENSE)
[](package.json)
[](https://github.com/Namit-nair/opencode-foreman/actions/workflows/ci.yml)
[](#mcp-server)
`opencode-foreman` is a foreman for your codebase: it hands the bricklaying — the actual
file-by-file implementation — to [OpenCode CLI](https://opencode.ai) running a **free** model,
while Claude stays on site to write the spec and sign off on the finished work. You get a working
diff without spending Claude's own tokens on the iterative, heavy part of writing code.
It ships as both a **CLI** you can script and an **MCP server** Claude can call mid-conversation.
---
## Why
Claude Code / Cowork sessions burn a lot of tokens on the part that matters least for Claude to do
itself: writing and rewriting implementation code. `opencode-foreman` flips the division of labor —
| | Claude | opencode-foreman |
|---|---|---|
| Writes the task spec | ✅ | |
| Writes the implementation | | ✅ (via a free model) |
| Runs your tests / build | | ✅ |
| Diffs the result against git, independently | | ✅ |
| Judges whether it's actually done | ✅ | |
Claude never has to take the delegated agent's word for it — every result is checked against a
real `git diff` and a real verify command before Claude ever sees it.
## How it works
```
Claude opencode-foreman OpenCode CLI + free model
────── ──────────────── ─────────────────────────
"fix the bug, ─────▶ 1. git checkpoint
here's the 2. ensure safety guardrails
verify cmd" 3. run ───────────────────────▶ reads, edits, runs bash
4. git diff (ground truth) ◀──── claims it's done
5. run your verify command
6. compact bundle
◀─────────────── (summary + diff + verify result)
"looks good" / "try
again" / "switch
models" / "revert"
```
The agent's own claims are never trusted — changed files and the diff come from `git`, and
pass/fail comes from actually running your verify command.
## Features
- **CLI and MCP server**, same underlying engine, so you can script it or let Claude call it directly.
- **Free-model-first**: discovers whatever free models are actually available (OpenCode Zen's
free tier out of the box, `openrouter/*` once you set `OPENROUTER_API_KEY`) and lets you pick
one per project, per session, or per call.
- **Session resume with mid-task model/agent/effort switching** — a follow-up `continue` call can
swap models without losing OpenCode's session context.
- **Git-checkpointed, one-command revert** — every delegated run is preceded by a snapshot; `revert`
restores the directory exactly, including deleting files the agent newly created.
- **Guardrails like a real foreman — enforce site safety, don't dictate method.** Hard limits that
hold even under `--auto`: a merged deny-list (`rm -rf`, `git push`, `npm publish`, `sudo`, ...) and
`external_directory: deny` to confine the agent to the target directory. But `doom_loop` is set to
`allow` — the worker is trusted to iterate its own way (retry, backtrack, rethink) rather than being
hard-stopped mid-process; runaway iteration is bounded from the *outside* by the timeout, no-output
watchdog, and no-progress/oscillation detection. `--auto` itself is unconditional — OpenCode has no
non-interactive mode that skips permission granting, so it's always passed; the deny rules hold regardless.
- **High reasoning by default, and room to think** — delegated runs use high reasoning effort
(`defaultVariant`) unless a call dials it down, and the no-output watchdog is deliberately patient
(minutes of true silence, not seconds) so a model that goes quiet *while reasoning* isn't killed
mid-thought.
- **Richer task context, non-invasively** — `delegate_task` takes an optional `context` field for
supporting background (file paths, snippets, constraints) the worker can draw on, kept separate from
the task and explicitly *not* instructions on how to implement.
- **Timeout + no-output watchdog, with automatic model fallback** — a genuinely hung or rate-limited
model (this happens for real) is killed and the run is transparently retried on the next free model,
bounded by `maxModelFallbacks`, before ever reporting failure. `opencode/deepseek-v4-flash-free`
is the recommended default for general dev/file-editing work and sits first in the fallback chain.
- **Objective diff stats and token/cost usage** in every bundle (`diffStats`, `tokens`, `cost`) —
the files-changed/+/- counts come straight from `git diff --numstat`, independent of anything the
agent says about its own work.
- **Tooling-tamper warning** — flags (doesn't block) if a run's diff touches `package.json` scripts,
lockfiles, `.npmrc`, or similar before your verify command executes them via shell.
- **Secret scrubbing** — known API key shapes and any explicitly-known secret values are redacted
from everything handed back to Claude.
- **Built to never run unless you ask** — every MCP tool description explicitly instructs Claude
not to call it autonomously, and pairs with an `ask`-mode permission rule (see below) that forces
an approval prompt on every single call regardless of what Claude decides.
- Cross-platform: Windows, WSL, macOS, Linux.
## Prerequisites
- [Node.js](https://nodejs.org) ≥ 18
- [OpenCode CLI](https://opencode.ai) installed and on `PATH`
- Free to use immediately with OpenCode Zen's free-tier models — no API key needed. Set
`OPENROUTER_API_KEY` in your environment if you want `openrouter/*` models too.
## Install
```bash
git clone https://github.com/Namit-nair/opencode-foreman.git
cd opencode-foreman
npm install
npm run build
npm link # puts `opencode-foreman` and `opencode-foreman-mcp` on PATH
```
## CLI
```bash
opencode-foreman models # list free models available right now
opencode-foreman agents # list agents (build, plan, ...)
opencode-foreman set-model <id> --dir <dir> [--agent build] [--variant high]
opencode-foreman run "<task>" --dir <dir> [--verify "npm test"] [--context "..."] [--model <id>] [--variant high] [--max-attempts 3]
opencode-foreman continue "<message>" --session <id> --dir <dir> [--model <id>]
opencode-foreman status --session <id> --dir <dir>
opencode-foreman revert --dir <dir> [--session <id> | --checkpoint <commit>]
```
Every command prints a JSON result and exits non-zero on failure — easy to script or pipe.
## MCP server
Register it once, globally, so it's available across every project:
```bash
claude mcp add opencode-foreman -s user -- opencode-foreman-mcp
```
Or by hand, in your MCP client config:
```json
{
"mcpServers": {
"opencode-foreman": {
"command": "opencode-foreman-mcp"
}
}
}
```
**Tools:** `list_models`, `list_agents`, `set_session_defaults`, `get_session_defaults`,
`delegate_task`, `delegate_continue`, `delegate_status`, `delegate_revert`, `fetch_full_diff`.
If no model has been chosen yet for a directory, `delegate_task` returns a prompt listing available
free models instead of running — call `set_session_defaults` once, and every later call in that
directory reuses it silently. Any call can still override `model` / `agent` / `variant` just for
itself, and pass optional `context` (supporting background the worker draws on — not method).
**Want Claude to only ever touch this on request, never on its own initiative?** Add a permission
rule so every call requires your explicit approval:
```json
// ~/.claude/settings.json
{
"permissions": {
"ask": ["mcp__opencode-foreman__*"]
}
}
```
## Config
Layered: built-in defaults → `~/.opencode-foreman/config.json` → `<dir>/.opencode-foreman.json` →
session defaults → per-call overrides.
| Key | Meaning |
|---|---|
| `timeoutMs` | hard wall-clock timeout per run (default: 20 min — generous, so a long but productive high-reasoning run isn't cut off) |
| `noOutputTimeoutMs` | kill the run only after this much *true silence* (default: 5 min). The model goes quiet while it reasons; this must stay well above a single thinking step or you'll disable the model mid-thought |
| `maxAttempts` | internal auto-retry loop on verify failure (default: 3 — gives a free model room to iterate, since first-try success is unlikely). Pass `1` per call to force a single Claude-driven run |
| `defaultVariant` | reasoning effort passed to OpenCode's `--variant`, applied unless a call/session overrides it (default: `high`) |
| `maxModelFallbacks` | how many alternate models to try if one hangs (default: 2 — always on, independent of `maxAttempts`) |
| `preferredModels` | ordered list suggested first when choosing a model, and the head of the fallback chain (default: `["opencode/deepseek-v4-flash-free"]`) |
| `diffTruncateLines` | how much diff to inline before truncating (full diff always fetchable) |
| `verify` | default verification command |
| `denyList` | extra bash patterns to deny, on top of the built-in list |
| `allowedRoot` | confine all `dir` arguments to this root |
| `defaultAgent` | agent to use when none is set (default: `build`) |
| `pure` | run OpenCode with `--pure`, bypassing your global OpenCode plugins (default: `true`) |
## Safety
- Every delegated run is git-checkpointed first; `revert` restores the directory to that exact
state in one command.
- `opencode.json` in the target directory gets a merged-in deny list plus `external_directory: deny`
(confinement) — these hold even under `--auto`, since `--auto` only auto-approves rules that would
otherwise ask. `doom_loop` is left `allow` so the worker can iterate freely; runaway loops are
caught by the outer timeout, no-output watchdog, and no-progress/oscillation detection instead.
- Refuses to operate on filesystem/system roots or the bare home directory.
- Known secret shapes — and any explicitly-known secret values, like `OPENROUTER_API_KEY` — are
redacted from everything returned to Claude.
- A wall-clock timeout and a no-output watchdog kill hung runs; the opt-in auto-retry loop detects
no-progress and oscillating diffs and stops instead of looping forever.
## Contributing
Issues and PRs welcome — this is an MVP, and there's plenty of room to grow (cost/token accounting,
parallel delegations, richer diff summarization, more free-model providers).
## License
[MIT](LICENSE) © 2026 Namit Nair
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available