Fixer gives your coding agent a Team of models from other providers.
Fixer is an MCP server. You write a Team file. Each member of the Team has a CLI, a model, and a role. Your agent gets one tool for each member. When your agent calls a tool, Fixer runs that member through the member's CLI, on the member's model, in your workspace. Fixer then gives the member's answer to your agent.
you ─► host (for example Claude Code; its model is the primary)
│ calls the tool "reviewer"
▼
fixer ─► codex exec -m gpt-5.5 ... ─► answer to the primary
Fixer has no agent loop, and it does not change a host. Each member uses the sign-in, tools, and permissions of its own CLI. Fixer is one Python file. It uses only the standard library.
| Term | Meaning |
|---|---|
| Host | The CLI that you type into. |
| Primary | The model in the host. The primary calls the members. |
| Member | One role in the Team. A member has a runner and a model. |
| Runner | The CLI that runs a member. |
| Kind | Memory |
|---|---|
peer |
A peer keeps one session with the primary. Each new call continues that session through the resume function of the CLI. The session stops when the Fixer server stops, normally at the end of the host session. |
specialist |
A specialist starts a new session for each call. |
The tool description tells the primary the kind of each member. Thus the primary knows what it must send. Members do not consult other members.
A CLI can be the host, a runner, or both. These results come from tests with real models on 2026-10-04.
| CLI | As host | Specialist | Peer | Read-only stops edits | Read-only stops shell commands |
|---|---|---|---|---|---|
Claude Code (claude) |
tested | tested | tested | yes | yes |
Codex (codex) |
tested | tested | tested | yes | yes |
OpenCode (opencode) |
tested | tested | tested | yes | no |
fx (fx) |
tested | tested | tested | yes | yes |
Cline (cline) |
not tested | tested | not possible | yes | no |
Cursor (cursor-agent) |
not tested | not tested | not tested | — | — |
- Cline cannot continue a session without a terminal. Thus Cline can run only specialists.
- On OpenCode and Cline, a read-only member can run shell commands. Give these members only tasks where this is safe.
- Cursor support comes from its help text. Cursor did not run with a real model.
- The fx tests used fx 0.0.12 with a Cline connection. The fx runner uses only standard fx flags.
You need:
- Python 3.11 or later, on macOS or Linux.
- The CLI of each member, installed and signed in.
Do these steps:
-
Copy
team.example.tomlto.fixer/team.tomlin your project. -
Edit
.fixer/team.toml. The section Team file gives the keys. -
Check the file:
python3 /path/to/fixer.py check
-
Add Fixer to your host:
Host Command or file Claude Code claude mcp add fixer -- python3 /path/to/fixer.py serveCodex codex mcp add fixer -- python3 /path/to/fixer.py serveOpenCode opencode.json:{"mcp": {"fixer": {"type": "local", "command": ["python3", "/path/to/fixer.py", "serve"]}}}fx .mcp.json:{"mcpServers": {"fixer": {"command": "python3", "args": ["/path/to/fixer.py", "serve"], "operation_timeout_ms": 900000}}}. Then runfx mcp trust approve fixer. -
Start the host in the project directory. Fixer reads
.fixer/team.tomlthere, and the members work there. -
Increase the time limit of the host for MCP tools. One member call can take some minutes.
- Claude Code: set
MCP_TOOL_TIMEOUT=900000(milliseconds). - Codex: in
~/.codex/config.toml, under[mcp_servers.fixer], settool_timeout_sec = 900. - fx: set
operation_timeout_msin.mcp.json, as in step 4.
- Claude Code: set
-
Approve the Fixer tools. A host that runs without a terminal cannot ask for approval, so approve the tools before you start it:
claude -p: add--allowedTools mcp__fixer.codex exec: under[mcp_servers.fixer], setdefault_tools_approval_mode = "approve".
Then use your host as usual. The primary calls a member in three cases:
- The primary decides that the member can help.
- You tell the primary to call the member.
- A rule in your instructions file tells the primary to call the member.
name = "engineering"
max_active = 4 # member runs at the same time
timeout_seconds = 900 # time limit for one call
[members.reviewer]
kind = "peer"
runner = "codex"
model = "gpt-5.5"
description = "Independent reviewer. Give it the diff or the file names."
instructions = "Find correctness bugs. Give file:line for each bug."
read_only = true # the default value| Key | Required | Meaning |
|---|---|---|
kind |
yes | peer or specialist. |
runner |
yes | claude, codex, opencode, fx, cursor, cline, or a name from [commands]. |
model |
yes | Fixer gives this value to the model flag of the runner. |
description |
yes | The primary sees this text. Tell the primary when to call this member. |
instructions |
no | The role of the member. Fixer sends it on the first call. |
read_only |
no | true is the default. false selects the write mode of the runner. |
timeout_seconds |
no | This value replaces the Team value for this member. |
The tool name is the member id. An id has lowercase letters, digits, -,
and _. Fixer refuses unknown keys. Thus fixer check finds a typing
error before you start.
[commands] adds a different CLI for read-only specialists:
[commands]
my-cli = ["my-cli", "--model", "{model}", "--quiet"]Fixer replaces {model}. Fixer sends the prompt on stdin, unless an
argument contains {prompt}. The command must print only the answer.
max_activesets the maximum number of member runs at the same time, for each Team, across all processes.- Each call has a time limit. If the host stops a call, or if the host itself stops, Fixer stops the process group of the member.
- Each member works in the directory of the server. Fixer sets the working
directory and
PWDto the same value, because OpenCode usesPWD. - Fixer sets
FIXER_MEMBERfor each member. If the CLI of a member loads Fixer from your settings, that Fixer gives no tools. - If a prompt is longer than 96 KiB, Fixer writes it to a temporary file. The member then reads the file.
- A member can read all of your workspace. This includes the Team file.
FIXER_LOG=/pathrecords each call as one JSON line: member, runner, model, resume or new session, seconds, and exit status.
- The answer of a member can be wrong. In one test, a peer gave a wrong answer from its memory. The primary examined the answer and found the error. Fixer tells the primary to examine each answer.
- Free models can change without notice. During the tests, one Cline free model stopped. Also, the OpenCode free tier started to refuse other clients.
- Peer sessions stop when the Fixer server stops. A host that starts a new
server for each request loses the sessions. Repeated
claude -pcalls are an example.
python3 -m unittest discover -s tests -vThe unit tests examine the command lines of each adapter. They read real
CLI output from tests/fixtures/. They test the server with a stand-in
CLI.
tests/test_live.py runs real CLIs on real models. For each runner, it
tests a one-time call, a peer session against a specialist, and read-only
mode against write mode:
FIXER_LIVE=claude,codex FIXER_LIVE_CLAUDE=claude-haiku-4-5-20251001 FIXER_LIVE_CODEX=gpt-6-luna \
python3 -m unittest tests.test_live -vObey these rules:
- Keep Fixer above the host. Use only MCP over stdio and the CLI of each member. Do not import, change, or fork a CLI.
- Put all details of one CLI in the adapter class of that CLI. The server must not know a CLI by name.
- Add a runner only with real tests. Run
tests/test_live.pyfor the new runner. Save one real output intests/fixtures/for its parser test. - Use only the standard library.
- Refuse unknown keys in the Team file. Add a key only for a real need.
After a change, do these steps:
- Run the unit tests. All tests must pass.
- If you changed an adapter, run the live tests for that runner. The unit tests use saved output, so they cannot show that the real CLI accepts the flags.
The adapters use these flags. The versions are the versions that Fixer was tested with.
| CLI | Version | One-time call | Session | Read-only |
|---|---|---|---|---|
| Claude Code | 2.1.289 | -p --no-session-persistence |
--session-id <uuid>, then --resume <uuid> |
default -p mode |
| Codex | 0.160.0 | exec --ephemeral |
id from --json, then exec resume <id> |
sandbox_mode="read-only" |
| OpenCode | 1.18.34 | run |
id from --format json, then --session <id> |
--agent plan |
| fx | 0.0.12 | ask --no-save |
id from --json, then --resume-id <id> |
default mode |
| Cline | 3.0.68 | --json "<prompt>" |
not possible without a terminal | --plan |
| Cursor | 2026.10.01 | -p --output-format json |
create-chat, then --resume <id> |
--mode ask |
- Test Cursor with a real account. A fault will probably be in its adapter: a flag, a JSON field name, or session resume.
- Find a way for Cline peers.
cline --acpkeeps a live session. It is not tested. - Add an install command, so that users do not need a file path.
Fixer was first a Zig extension. It compiled into a fork of fx. That design was difficult to maintain, for three reasons:
- Upstream fx changed very quickly: 987 commits in the 26 days after the last sync.
- Fixer connected below the agent loop. Thus most upstream changes broke the fork.
- Each change needed 24 CI jobs on four platforms.
Commit 310ba91 is the last commit of the old design.
Licensed under Apache-2.0.