@0xmmo/crew
v0.2.5
Published
Let Claude Code and Codex agents talk to each other: live shared context and agent-to-agent messaging across sessions.
Maintainers
Readme
crew
Let Claude Code and Codex agents talk to each other.
Ship features in parallel, no branches, no worktrees. Hand off work between sessions,steer around each other's in-flight edits, announce deploys to every running agent.
crew auto-injects what your other running Claude Code and Codex sessions are doing (status, recap, and a tail of each transcript) into every session's context. Claude and Codex share one crew, so either can see and message the other. Agents steer around in-flight work while parallel sessions operate from one checkout instead of needing a worktree each. There's also a CLI for watching all of it yourself.
Just like autonomous cars don't need stoplights, agents don't need worktrees.
- Shared context, live — every session knows what the rest of the crew is doing, refreshed as it changes.
- Agent-to-agent mail —
crew senddrops a message into another agent's context within seconds, even mid-turn. - A human view — one command shows every session's status, recap, and transcript tail;
--jsonfor scripts and agents. - Zero config —
npm i -gwires both products' hooks, or install it as a plugin. Token-frugal and fail-safe by design; reads transcripts, never modifies them.
Install
npm install -g @0xmmo/crewThat's the whole setup: installing globally wires the hook into ~/.claude/settings.json and ~/.codex/hooks.json automatically. (If your npm has ignore-scripts=true, postinstall can't run; do it with crew install-hook once instead.) Requires Node.js ≥ 18. macOS and Linux.
Codex reviews user-installed command hooks before running them. Start a new Codex session, open /hooks, and trust crew when prompted. Claude Code uses the hook immediately.
Or as a Claude Code plugin
/plugin marketplace add 0xmmo/crew
/plugin install crew@0xmmoSame thing, zero settings.json edits: the plugin ships the four hooks and its own copy of the binary (fetched from npm), and /plugin manages updates. The repository also includes a native Codex plugin manifest for Codex marketplaces and local plugin installs. When the global crew command isn't installed, injected guidance points agents at the plugin's own entry point instead, so messaging still works. Pick either path; if you end up with both, the plugin defers to the global install so nothing is injected twice. The global install is still the way to get crew on your own PATH and automatically cover both products.
What your agents see, live
From then on, every Claude Code and Codex session starts with (and keeps getting, as things change) a context block like:
2 other agent session(s) running on this machine right now. Consider them
before starting overlapping work; run `crew` for the full view.
• 4d3de8db — claude — busy — /Users/you/Projects/api
recap: Goal was fixing the imagent CPU spin, now resolved and documented.
17:41 › run the test suite
17:41 ⚙ Bash: npm test
17:42 ‹ All 142 tests pass.
• b5e3454f — codex — idle — /Users/you/Projects/web
recap: Diagnosed the sandbox validator bug; awaiting go-ahead to implement.
You can message any of them: `crew send 4d3de8db "text"` drops the text into
that agent's context within seconds.So when an agent in one session is about to touch files another session is mid-way through, it knows, and it knows how to say something about it. A crew send from another agent (or from you in a plain terminal) lands the same way, even mid-turn:
📨 Message from 4d3de8db (/Users/you/Projects/api, sent 2m ago):
heads up — refactoring src/settings.ts, hold off for 20 min
Reply with: `crew send 4d3de8db "text"`Messaging between agents
Any session (or you, from a plain terminal) can drop a message straight into another agent's context:
crew send b5e3 "settings.ts is mine for the next 20 min" # target: shortId prefix, pid, or cwd substring
crew send --all "deploying api to staging now" # broadcast to every other session
crew send fc22 "npm support replied, name is free" --ttl 2h # expire undelivered mail (default 24h)
crew inbox # peek at your own pending mailSender attribution is automatic: crew send walks up the process tree to find which session it was called from, so agents never have to identify themselves.
When it arrives depends on what the target is doing:
| Target state | Delivered | |---|---| | busy, mid-turn | after its next tool call, typically seconds | | finishing a turn | at turn end, and the agent acts on it before going idle | | idle | on its next user prompt |
An idle session can't be woken externally, so undelivered mail waits in ~/.crew/inbox/ until its TTL expires; the crew view shows a 📨 pending count for it in the meantime. Once delivered, a message becomes part of the target's context, like anything else it read. Each message is delivered exactly once, even when hook events race. In Codex, pending mail at Stop deliberately continues the turn once so the agent can act on it before becoming idle.
The CLI
The same view, for humans:
crew # human view, last 50 transcript entries per session
crew 10 # last 10 entries
crew --json # NDJSON: one structured object per session
crew --json --full # NDJSON without tool input/output truncation
crew --dir ~/work # only sessions whose cwd is under ~/work
crew --dir # only sessions under the current directory
crew send <t> "msg" # message a session (t: shortId prefix, pid, cwd substring)
crew inbox # your own pending messages
crew --help🔵 4d3de8db codex pid 66643 status: busy
cwd: /Users/you/Projects/api
started: 6/28/2026, 4:40:36 PM
recap: Goal was fixing the imagent CPU spin, now resolved and documented.
last 3 transcript entries (of 215):
17:41 › run the test suite
17:41 ⚙ Bash: npm test
17:42 ‹ All 142 tests pass.- agent —
claudeorcodex. - status —
busy(working),idle(awaiting input), or Claude'sshellstate. - recap — the session's most recent completion/recap, when available.
- tail — the last N transcript entries:
›you,‹the agent,⚙tool call,⟲tool result.
--json for agents
--json prints newline-delimited JSON (NDJSON), one object per session, with explicit fields instead of glyphs — built for another agent or script to consume:
{"pid":66643,"sessionId":"4d3de8db-…","shortId":"4d3de8db","agent":"codex","status":"busy","cwd":"/Users/you/Projects/api","startedAt":"2026-06-28T23:40:36.000Z","transcript":"/Users/you/.codex/sessions/…/rollout-….jsonl","recap":"…","messageCount":215,"tailCount":3,"tail":[{"ts":"…","role":"assistant","kind":"text","text":"All 142 tests pass."}]}Tool input/output is truncated by default; pass --full for the complete content.
How the injection works
npm i -g adds crew --hook to the same four lifecycle events in Claude Code and Codex (a plugin install registers them inside the plugin instead of user settings):
SessionStart— every new session (and every re-start after context compaction) opens knowing what the rest of the crew is doing.UserPromptSubmit— the picture is refreshed before each of your messages, and queued mail is delivered with it.PostToolUse— mail only: a busy agent receives messages after supported tool calls, typically within seconds ofcrew send.Stop— mail only: an agent finishing its turn handles waiting messages instead of going idle.
The hook is careful about tokens and safety:
- Emits nothing when no other sessions are running, and nothing on
UserPromptSubmitwhen the crew status hasn't changed since the last emit (a per-session hash under your temp dir). - The
PostToolUse/Stopmodes do the bare minimum: refresh the live registry and check one inbox, with no transcript scan and total silence when there's no mail. - Tails are short in hook mode (5 entries per session, truncated) and capped at 8 sessions.
- It always exits 0, so a broken or slow read can never block your prompt, your session, or an agent's turn.
- The auto-install merges into existing Claude/Codex hook settings and refuses to write over a file it can't parse.
Managing it:
crew uninstall-hook # remove it from both products
crew install-hook # add it to Claude Code and Codex (idempotent)
CREW_NO_HOOK=1 npm i -g @0xmmo/crew # install without touching hook settingsOr wire it manually; this hook object works in both ~/.claude/settings.json and ~/.codex/hooks.json:
{
"hooks": {
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "crew --hook" }] }
],
"UserPromptSubmit": [
{ "hooks": [{ "type": "command", "command": "crew --hook" }] }
],
"PostToolUse": [
{ "hooks": [{ "type": "command", "command": "crew --hook" }] }
],
"Stop": [
{ "hooks": [{ "type": "command", "command": "crew --hook" }] }
]
}
}How discovery works
Every interactive Claude Code session writes ~/.claude/sessions/<pid>.json while running. crew reads that native registry and pulls the corresponding transcript tail from ~/.claude/projects/.
Codex supplies session_id, transcript_path, cwd, and lifecycle state to hooks. crew records those fields in a small live registry under ~/.crew/sessions/, verifies the owning process is still alive, and parses the useful user/assistant/tool subset of the rollout. Top-level interactive and codex exec sessions are included; internal Codex subagents are intentionally not listed as separate crew members because they share their parent's lifecycle and mailbox. Codex documents its transcript format as non-stable, so crew skips unknown rollout records defensively.
Both discovery paths are read-only with respect to agent state and transcripts. In hook mode crew excludes the session it is reporting to, so an agent never sees itself listed.
Set CLAUDE_HOME or CODEX_HOME for non-default product state directories. The Claude hook installer also honors CLAUDE_CONFIG_DIR; set CREW_HOME to move shared registry/mailbox state from ~/.crew.
Development
git clone https://github.com/0xmmo/crew && cd crew
npm install
npm run build
echo '{"session_id":"x","hook_event_name":"SessionStart"}' | node dist/crew.js --hook
echo '{"session_id":"x","hook_event_name":"SessionStart","cwd":"'$PWD'","transcript_path":"/tmp/rollout-x.jsonl","model":"gpt-5"}' | node dist/crew.js --hook
node dist/crew.js --json
# regenerate the demo GIF (assets/demo.html is the storyboard)
node assets/record.mjs /tmp/crew-frames 12
ffmpeg -framerate 12 -i /tmp/crew-frames/f%05d.png -vf "scale=960:-1:flags=lanczos,palettegen=max_colors=128:stats_mode=diff" /tmp/crew-palette.png
ffmpeg -framerate 12 -i /tmp/crew-frames/f%05d.png -i /tmp/crew-palette.png -lavfi "scale=960:-1:flags=lanczos[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=4:diff_mode=rectangle" -loop 0 assets/demo.gifLicense
MIT
