This is a continuation of my "Claude Code environment" series, following How I split Claude Code's memory into four layers. This time I want to write about making Claude Code and Codex CLI divide the work between them inside a single Mac.
The trigger was simple: when I run my main session on a lightweight model, it feels wasteful to burn tokens on the long typing of implementation. Design and review benefit from how smart the model is, but the process of just churning out predetermined implementation is something I'd rather offload to a separate process. So I settled on delegating implementation to Codex while keeping design, research, and review on the Claude side.
I've spelled out the division of labor in CLAUDE.md. The gist is this:
| Process | Owner | Reason |
|---|---|---|
| Design, codebase research, planning | Claude (main) | Requires understanding context and judging trade-offs |
| Implementation, refactoring, test generation | Codex | Offload the boilerplate, large-scale, and repetitive work to the typing side |
| Code review | Both | Add a second engine's eyes to raise quality |
The key point is not to delegate everything. When an implementation is highly difficult, or involves heavy design judgment, the main session that holds the context can write it directly, faster and more accurately. Delegation is strictly limited to the "mass-produce the predetermined stuff" process.
:::message
The axis is separating the processes that need the model's intelligence (design, review) from those that need volume more than intelligence (boilerplate implementation). It's not "since I have two AIs, parallelism makes it faster" — it's "choose which work to seat in the expensive chair."
:::
Codex is installed as a CLI (codex-cli 0.135.0
). I delegate via non-interactive headless execution.
timeout 600 codex exec --skip-git-repo-check "<request>" </dev/null
codex exec review </dev/null
There are three small but effective points:
</dev/null
timeout
for nothing.timeout
--skip-git-repo-check
Codex is installed under nvm. Claude's Bash during an interactive session has already loaded the nvm default, so codex
just works — but from a bare zsh or via cron, you can get command not found. In that case, call it by its full path.
/Users/<you>/.nvm/versions/node/v24.13.0/bin/codex exec ...
When you run it unattended from launchd or cron, nvm isn't in the minimal PATH, so you're guaranteed to trip on this. Specifying the full path is the reliable fix.
The actual operational flow looks like this:
codex exec
and have it implementcodex exec review
for code reviewSplitting steps 3 and 4 across different engines is quietly effective. When the same model reviews as "the person who wrote it," the review tends to go soft, but by having Codex write and Codex review — or having Claude review — you can separate the author from the reviewer.
For long delegations, I pass tasks, handoffs, and state through files. Conversation context is volatile, so writing the state to disk makes resuming and verifying easier. When I run things isolated in a worktree, I write the branch and worktree path into a status file.
- State: running
- Updated: 2026-06-17T...
- Branch: feat/...
- Worktree: `/path/to/worktree`
This is the same philosophy as the four-layer memory piece. Keep the canonical copy of state outside the volatile conversation. Whether it's collaboration or long-term memory, the principle that works turned out to be the same.
</dev/null
and Codex freezing while waiting for inputcodex: command not found
from cron/launchd--skip-git-repo-check
codex exec --skip-git-repo-check "..." </dev/null
wrapped in timeout
Next time I'll write about a hook that mechanically stops secrets from leaking right before that push — Stopping API keys and accidental pushes with a pre-push guard.
Lily (@bokuwalily) — indie developer. I build automation infrastructure with Claude Code while mass-producing iOS apps and web services.
Your ❤️ and shares keep me going!