Crysto: how I run Claude, Codex and other AI models as one team. The models were the easy part.

2026-11-05来源 dev.toEnglish
Crysto: how I run Claude, Codex and other AI models as one team. The models were the easy part.

Early on, two of my AI agents tried to use the same browser at the same time. The browser fell over. Neither of them had really done anything wrong. They had each followed their instructions to the letter. They just had no idea the other one was there.

That was when I realised the hard part of running AI agents isn't the AI. Getting a model to write decent code is close to solved. Getting four of them to work on the same projects for weeks, without stepping on each other, redoing each other's work, or cheerfully telling me something was done when it wasn't, is where all my time has gone.

I call the whole setup Crysto. It started as a way to keep my own projects organised, and grew into something I lean on for my professional work too, with the two sides kept completely separate. Here's how it works, and what broke along the way.

Why I built it

I'm an AI engineer, so I spend most of my day with these tools anyway. But my own projects were scattered: side projects, research, writing and the important things I needed to keep on top of, all half-done across different chat windows. Every new chat started from nothing, and I was the only one keeping track of where anything was up to.

Who's on the team

The crysto repo on GitHub
The crysto repo on GitHub

Claude Code runs the show. It plans the work, writes briefs for the others, reviews everything they hand back, and decides what actually ships. I run it on two separate accounts, one for work and one personal, and a small shell hook switches between them depending on which folder I'm in.

Codex gets the long jobs. Give it a clear brief and it will build a small project, or grind through a pile of browser forms, while I get on with something else.

Smaller models, through a tool called OpenCode, handle the bounded fixes. I can hand the same task to five of them at once and keep whichever result is best.

Claude on my phone connects through a small MCP server on Cloudflare Workers, with KV storage behind it. That gives the phone and laptop access to the same stored data without relying on a shared chat.

The coding agents also run headless. These are the command shapes I use, with a model and brief supplied for each run:

opencode run --format json -m <model> "<brief>" 
codex exec -s workspace-write "<brief>" 

Each run gets its own copy of the repo. OpenCode runs one model per invocation; Codex works inside its workspace-write sandbox. Separate copies matter when I'm comparing results: otherwise a later model could inherit an earlier model's edits, and I'd have no clean way to tell who did what.

The catch is that none of them share a conversation. Everything below comes from that.

Nobody remembers anything

Codex can't see my Claude chats. Tomorrow's Claude session can't see today's. Every agent wakes up with amnesia.

What fixed it was embarrassingly low-tech: files. Every project lives in a folder with a STATUS.md that says where things are up to. Every session reads it first and updates it before it finishes. Longer-term memory is one fact per file with a one-line summary, and only a short index of those gets loaded each time. Each memory file has front matter for its name, description and type. The four types are user, feedback, project and reference. The index tells the agent what exists; it can read the relevant file when the task needs it.

The part that surprised me was how much it helps to give every rule a reason. "Only one agent uses the browser at a time" is a rule. Add "because two agents on the same debugging port will crash each other" and an agent can work out the case I never wrote down, like a second browser tool on the same machine.

It sounds almost too simple to write about. But it's the reason any agent, on any model, can pick up a project cold.

Who's doing what

Back to the browser crash. The fix was one more file, COORDINATION.md, which lives in the hub. Before an agent touches files or the browser, it writes down that it's taking the job:

# Website copy review, 4 November: CLAIMED BY CODEX Owner: Codex. Claimed 4 Nov 10:05. Done: 12 of 18 claims checked. Evidence: drafts/about.md diff. Next: check the last 6, then hand back to Claude. 

A real terminal run of new-project.sh and make check
A real run: creating a project, then the 17 tests in make check

The rules fit on an index card. Check the file before you start. If someone else has claimed a task, leave it and ask me. Only one agent on the browser. And nothing actually enforces any of it. There's no lock. It works because every agent's instructions tell it to respect the file, and so far they do.

It earned its keep this week. A work session already had the browser, so my personal session switched to a different browser tool instead of grabbing it.

Tests that pass and still lie

The whole setup depends on the smaller models building and Claude reviewing. That only works if the review actually catches things, so I tested it.

The bug was pydynox issue #560. Its MemoryBackend decorator wrapped an async function, but exited its context before the coroutine ran. That's a useful failure to test because returning a coroutine and executing it aren't the same event. The context has to cover the actual async execution.

I gave it to 9 models, with tests I'd written beforehand and kept hidden from them. Eight passed those hidden tests; the fastest finished in 84 seconds. Nemotron 3.5 Lightning passed, but also deleted an existing test. If I'd only read the final test result, I'd have missed that change entirely.

The refactor task was in awslabs/stickler, with a 4,091-test suite. Five models kept it green without editing a test. Flint 40B also ran ruff --fix over 8 unrelated notebooks. Its diff touched 11 files, while the others touched 3. The extra changes weren't necessary for the task, even though the suite still passed.

Glasses in front of screens of code
Photo by Kevin Ku on Unsplash

So now Claude does three things with every change. It writes tests up front that the building agent never sees, runs them afterwards, and reads the whole diff. A green test run tells you the tests passed. That's all it tells you.

The build loop sequence diagram
The build loop, rendered from the Mermaid diagram in the crysto README

Everyone exaggerates a little

When an agent finishes, it writes a handover: what it changed, the proof, what went wrong, and what it didn't get to test. The rule is that "done" means a command ran and the output is in the file. Plans and good intentions don't count.

Even so, claims creep. When the smaller models built my retrieval benchmark, their handover was upfront that one feature, the Claude answer path, had never actually run. Their README still made it sound like part of the results. The review also found a threshold that had been tuned on the very questions it was being scored on. Both are fixed now, and the README says so.

That project, rag-eval-lab, uses 745 Python PEPs split into 17,933 chunks, stored in PostgreSQL with pgvector and an HNSW index. Vector search scored recall@1 of 0.70 against 0.36 for full-text search. Hybrid search with reciprocal rank fusion, or RRF, scored 0.66. Here, recall@1 asks whether the expected result came first. Adding another retrieval method didn't automatically improve that score.

Those numbers describe this benchmark. They don't prove that vector search wins on every corpus, and they say nothing about an answer path that never ran. That's the distinction I need the handover and README to preserve.

Claude isn't immune either. While drafting my last article, it wrote that my fixes had been sent to the project maintainers. They hadn't, not yet. We only caught it because the check went back to the actual pull requests.

I've stopped hoping for a model that never overstates things. What I want is a check that doesn't take its word for it.

The rules that weren't about AI

Two of my most expensive lessons had nothing to do with models.

My work and personal Claude accounts are kept apart by separate config folders. But both read the same keychain entry, so logging out of one to switch logs out every session on the machine. Now the shell hook handles the switch and prints a line every time it happens, and I never log out.

The account folders use CLAUDE_CONFIG_DIR for Claude and GH_CONFIG_DIR for the GitHub CLI. The hook checks the current directory and selects the matching config. These lines come straight from account-switch.zsh:

autoload -Uz add-zsh-hook add-zsh-hook chpwd _crysto_claude_account add-zsh-hook chpwd _crysto_gh_account _crysto_claude_account _crysto_gh_account 

The chpwd hook runs the account functions when the directory changes. The final calls also select the accounts when the shell starts. Separate config folders solve the selection problem; they don't remove the shared keychain behaviour.

Then the voice assistant. My first design for "Hey Crysto" was a small Cloudflare Worker that called Claude with my subscription login. Anthropic's terms don't allow that: a subscription is for their own apps, and anything running on your own server needs a paid API key. So I split the problem. The part that matters most, Crysto's connection to my data, is built and running: a personal MCP gateway on Cloudflare Workers with OAuth and PKCE, read-only by default, where any write needs my explicit consent. Codex signs in to it and reads my mail, calendar and project data through one endpoint. For voice, I use the Claude app and Siri today. The always-on brain, a model that runs by itself and also runs the lights at home, is designed and waiting. The main thing stopping me is the API bill: I'm not ready to pay per request for a side project yet. Next time I'll read the terms before I draw the diagram.

Under the hood

Crysto is mostly Markdown files and shell commands. Claude Code coordinates the work, while headless OpenCode and Codex runs produce changes for review. Project status and task claims live beside the work, so the next session can read them with ordinary file tools.

The public repo includes a bash script to create a project, plus 17 tests, shellcheck and GitHub Actions CI. The Cloudflare Workers MCP server uses KV for stored state. PostgreSQL, pgvector and HNSW belong to the retrieval benchmark, rather than the coordination protocol. I don't need a database query to find out who owns the browser.

What it costs

Not much beyond the subscriptions I already had. Money isn't really the limit. Attention is, so the whole thing is set up to spend it on briefs and reviews rather than on typing code.

If you want to try this

  • Keep shared state in files, not in chats.
  • Have agents claim work before they start, and give the browser one driver.
  • Write your own tests and keep them away from the agent writing the code.
  • Read every diff, even when it's green.
  • Ask for proof, then check it.

The design, the coordination rules, the templates and a script that sets up a new project are all open source at github.com/vanshaj1999/crysto. My memory, notes and data aren't, and that's on purpose.

Cover photo by James Harrison on Unsplash.

原文:https://www.a8q9.cn/en/article/crysto-how-i-run-claude-codex-and-other-ai-models-as-one-team-the-models-were-th-c2a908.html

相关文章