| date | 2026-05-14 |
|---|---|
| audience | humans onboarding a new agent into coord |
| status | living doc — update as workflow evolves |
The recipe for taking a Claude Code agent (running as a pty session) and making it a first-class coord participant — visible in coord members, able to send/receive channel messages, running the boot ritual on every resume.
Worked recipe — every step is something I (pty-claude, as manager) ran while onboarding coord-claude, coord-web-claude, pty-relay-claude, and pty-public-relay-claude to the same coord network on a single machine.
ptyinstalled and on PATH (run from worktree, not global install — seefeedback_no_tsx.md).coordinstalled and on PATH (currently a local repo at/Volumes/SSD/src/github.com/myobie/coord; thebin/coordis the entry point).- The coord skill plugin installed in Claude Code:
claude plugin install coord@localif the user's local marketplace at~/.dot-files/ai/is registered.- Skill lives at
~/.dot-files/ai/plugins/coord/skills/coord/SKILL.md.
- The brief-027 hook script exists at
coord/examples/claude-code/hooks/session-start.shand is executable (chmod +x). $COORD_ROOTdefaults to~/.local/state/coord; no override needed for single-machine setups.
Pick an identity name for the new agent. Convention: <repo>-claude (e.g. coord-claude for the agent in coord/, pty-relay-claude for the agent in pty-relay/). Lowercase ASCII + hyphens, 1–32 chars, not a reserved name (inbox, archive, tasks, journal, status, name, available, busy, away, dnd, offline, unknown, members, overview).
Add a [sessions.claude.env] block setting COORD_IDENTITY, and amend the claude command to load coord's MCP channel:
prefix = "<repo-name>"
[sessions.claude]
command = "claude --dangerously-skip-permissions --dangerously-load-development-channels server:coord --resume $(cat .claude-session-id) || claude --dangerously-skip-permissions --dangerously-load-development-channels server:coord --session-id $(cat .claude-session-id)"
tags = { role = "agent" }
[sessions.claude.env]
COORD_IDENTITY = "<identity-name>"The --dangerously-load-development-channels server:coord flag is required during Claude Code's channel preview — without it, MCP notifications/claude/channel frames are silently dropped (see reference_claude_dev_channels_flag.md memory).
pty.toml is gitignored — this is per-machine, not committed.
From the agent's repo directory:
cd /path/to/repo && coord init .This writes a minimal .mcp.json registering the coord MCP server in channel mode:
{
"mcpServers": {
"coord": {
"type": "stdio",
"command": "/path/to/coord/bin/coord",
"args": ["mcp", "--channel"],
"env": {}
}
}
}coord init resolves the coord binary path automatically (PATH lookup with macOS app-bundle fallback). Idempotent — re-running on a repo that already has a matching entry is a no-op; on a divergent entry it prompts y/N.
Create .claude/settings.local.json (gitignored) with the brief-027 hook registered:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"async": true,
"asyncRewake": true,
"command": "/Volumes/SSD/src/github.com/myobie/coord/examples/claude-code/hooks/session-start.sh"
}
]
}
]
}
}asyncRewake: true is the load-bearing flag — it tells Claude Code to wake the agent on the hook's exit code 2 with the hook's stderr surfaced as a system reminder. Without asyncRewake, the boot ritual doesn't fire on --resume.
If the repo already has a SessionStart hook for something else (e.g. pty's autoscan reminder), nest the new entry alongside the existing one (the schema allows multiple matcher groups). See pty/.claude/settings.local.json for an example of two coexisting hooks.
mkdir -p ~/.local/state/coord/<identity-name>/{inbox,archive}The MCP server's chokidar watcher requires the inbox to exist at startup; coord's auto-create-on-first-write only applies to your own identity for direct CLI use. Pre-creating avoids a first-run race.
cd /path/to/repo && pty upOn first launch, Claude Code shows two TUI dialogs in sequence:
- Workspace trust: "1. Yes, I trust this folder / 2. No, exit" — confirm with Enter.
- Development channels warning: "1. I am using this for local development / 2. Exit" — confirm with Enter.
If the session is a --resume of an existing conversation, a third dialog appears:
3. Resume mode: "Resume from summary / Resume full session as-is / Don't ask me again" — pick the default (Enter).
From an outside shell, you can drive these via pty send <session-name> --seq key:return. Wait a few seconds between each peek + Enter to let Claude Code transition between screens.
After dialogs are dismissed, the asyncRewake hook fires its stderr as a system reminder. The agent should autonomously:
coord status <identity-name> --set availablecoord_msg_lsto scan inbox- Address any pending messages (
coord_msg_read+coord_msg_reply+coord_msg_archive) - Log a task if the agent is mid-work
Verify from any shell:
coord membersThe new identity should be available. If it's still offline, the ritual hasn't fired yet — peek the session (pty peek --plain <session-name>) and check whether the asyncRewake reminder landed in the agent's context.
From the manager / another agent / myobie identity:
COORD_IDENTITY=myobie coord message send <new-identity> --subject "welcome" -m "you're on coord now"The new agent should see this arrive as a <channel source="coord" from="myobie">...</channel> block in their context within a second or two, and (if their boot ritual is wired) respond via coord_msg_reply plus archive.
- Don't commit
pty.tomlor.claude/settings.local.jsonor.mcp.jsonto git. The first two are per-machine;.mcp.jsonis commonly per-machine too because the coord binary path depends on where it's installed (the valuecoord initwrites is your local path). - Don't manually create a
tasks/,journal/, orstatusfile. They get created lazily on first use. - Don't add the agent to any roster file.
coord memberswalks$COORD_ROOTand enumerates all identity folders automatically. - Don't worry about cross-identity write permissions — the LAYOUT enforces single-writer (only the owner writes their own status/tasks/journal/archive). Inbox writes from anyone are the one allowed cross-identity write.
- Hook doesn't fire on resume: check
.claude/settings.local.jsonis valid JSON; check the hook script is executable (stat -f %Mp%Lp <hook>should be 755). - Channel notifications don't surface as
<channel source=>blocks: confirm the--dangerously-load-development-channels server:coordflag is in the pty.toml command. Restart withpty kill <name> && pty up. On first launch the dev-channels warning dialog asks for explicit confirmation — make sure Enter was sent. - MCP server fails to boot: check the agent's spawn-args via
cat ~/.local/state/pty/<session-name>.json | jq .argsto confirmCOORD_IDENTITYis exported and the dev-channels flag is present. Checkcoord mcp --helpfor current MCP server CLI shape. coord membersshowsunknownfor the new identity: they're alive but haven't refreshed their status in 15+ minutes. Either run the boot ritual manually (coord status <name> --set available) or wait for the MCP server's 5-minute refresh tick.
Codex doesn't have channel mode — the MCP server's notifications/claude/channel emits are silently dropped by Codex's host. So the Claude Code recipe above doesn't fully apply. For Codex:
Same as Claude Code:
- Pick an identity name (convention:
<repo>-codexor just the bare project name if unambiguous, e.g.vauban). mkdir -p ~/.local/state/coord/<identity>/{inbox,archive}.
Codex agents get TWO pty sessions per project: the codex session itself, plus a coord ding daemon as a sibling. The ding daemon does what the MCP server does for Claude Code agents — pushes inbox arrivals, fires tidy-check drift summaries, and refreshes the identity's status mtime.
prefix = "<repo-name>"
[sessions.codex]
command = "codex resume $(cat .codex-session-id)"
tags = { role = "agent" }
[sessions.codex.env]
COORD_IDENTITY = "<identity>"
[sessions.ding]
command = "coord ding <repo-name>-codex --identity <identity>"
tags = { role = "ding", strategy = "permanent" }The ding session uses strategy = "permanent" so the supervisor restarts it after crashes. When the codex session dies (for any reason), ding's session-watch (brief-031) notices within ~30s and exits cleanly; the supervisor brings it back when the codex session does, or leaves it down if codex stays dead.
Codex sessions have a UUID like Claude Code. Grab it via /status inside the running session if there's an existing session you want to migrate; write it to .codex-session-id.
For a fresh codex agent, omit the .codex-session-id file and use codex (no resume) — but the pty.toml above assumes resume. Adjust the command to codex || codex resume $(cat .codex-session-id) if you want both fresh-start and resume-after-restart paths.
Codex doesn't read those. The ding sibling does the work those files would have done for a Claude Code agent.
Both sessions come up. ding has clean stderr by default (no chatter); look for warnings only.
Verify in coord members — the new identity should be available. ding's status-refresh tick (brief-032, every 5 min) keeps it that way.
Three periodic behaviors:
- Inbox-arrival push: chokidar watches
<identity>/inbox/; on new files, pty-sends acoord: 1 new from X — subjectnotice into the codex session. Busy-aware (skips when status ∈ {busy, dnd}). - Tidy-check drift summary: every 20 min, evaluates drift (inbox stale, doing-task stale, journal lag). Fires a
coord tidy-check: …notice if any condition holds. Busy/dnd/unknown-gated. - Status refresh: every 5 min, atomic-writes the current status value back to bump mtime. Prevents the 15-min staleness fallback to
unknown.
All three are independent timers; share the same evaluateDrift / refresh helpers as the MCP server uses for Claude Code agents.
Today this is 7 steps of manual work. Natural follow-up is a single command:
coord onboard-agent <identity-name> --repo /path/to/repoWhich would:
- Validate the identity name
- Mkdir the identity folder
- Patch the repo's pty.toml (or create one if missing)
- Run the equivalent of
coord initfor.mcp.json - Write
.claude/settings.local.jsonwith the SessionStart hook - Print the next manual steps (the
pty up+ dialog confirms remain manual because Claude Code's first-launch TUIs need a human pressing Enter — unless we auto-confirm viapty send)
Not built yet. Worth a brief when onboarding frequency justifies the automation.