skip to content

Claude Code

Claude Code integrates with xmsg through automatic session discovery (~/.claude/sessions), the xmsg mcp server, and xmsg register claude --hook for delegated subagent sub-addresses.

xmsg serve discovers live Claude Code sessions from ~/.claude/sessions by default. In multi-tenant setups where multiple CLAUDE_CONFIG_DIR trees exist under the same UID, pass repeatable --sessions-dir flags or colon-separated paths in XMSG_SESSIONS_DIR:

Terminal window
xmsg serve --sessions-dir /path/one/sessions --sessions-dir /path/two/sessions
# or colon-separated:
export XMSG_SESSIONS_DIR="/path/one/sessions:/path/two/sessions"
xmsg serve
  • Liveness verification: xmsg checks process liveness and start time continuity via /proc/<pid>/stat on Linux and proc_pidinfo on macOS (matching to the second the UTC ps -o lstart timestamp Claude Code records as procStart).
  • Instance claims & forks (X~2): When the same conversation ID X is active in multiple processes or directories, the first observed live process claims plain X and subsequent processes receive monotonic fork suffixes X~2, X~3, … in instance_claims, accompanied by a one-time fork notice to each process.
  • Parked queue & cross-machine handoff: When a Claude Code process exits, its conversation ID stays parked for the reply TTL (7 days by default). Messages sent to it queue in SQLite and drain when the conversation is resumed — or transfer over POST /fed/v2/handoff if the conversation resumes on another machine belonging to the same user.

Add xmsg mcp to your Claude Code mcpServers configuration:

{
"mcpServers": {
"xmsg": {
"command": "xmsg",
"args": ["mcp"]
}
}
}

For responder-only sessions that should only answer incoming messages without discovering or initiating new exchanges, pass --reply-only (which exposes only reply and replies).

Subagent hooks (xmsg register claude --hook)

Section titled “Subagent hooks (xmsg register claude --hook)”

Claude Code subagents spawned in-process via the Agent tool share the parent’s session_id and MCP server process. xmsg register claude --hook wires four Claude Code hook events to agent.sock so each subagent gets a delegated sub-address (<P>/<name>@<node> and <P>/<agent_id>@<node>):

  • SubagentStart: Sends {"action":"subagent","event":"start","agent_id":…,"agent_type":…} on agent.sock, binding <P>/<agent_id>@<node> under parent P and marking the subagent’s turn active.
  • PostToolUse (matcher ^(Agent|SendMessage)$):
    • On Agent, reads tool_input.name and tool_response.agentId (or subagents/agent-<id>.meta.json beside transcript_path) and sends a subagent bind frame so both <P>/<name>@<node> and <P>/<agent_id>@<node> resolve to the subagent.
    • On SendMessage, when tool_input.to targets a bound subagent whose in-memory teammate channel is unreachable after a restart, queues the message in the subagent’s xmsg mailbox.
  • PreToolUse (matcher ^mcp__(plugin_hm_)?xmsg__(send|reply|inbox|list|replies)$): Returns hookSpecificOutput.updatedInput with as_agent set to the hook payload’s agent_id (when called by a subagent) or session_id (when called by the parent), overwriting any model-supplied value.
  • SubagentStop: Sends {"action":"subagent","event":"stop","agent_id":…} on agent.sock, clearing the active turn so subsequent messages to <P>/<child>@<node> fall back to parent P with a to=<P>/<child> agent_id=<agent_id> header.

Enabling programs.xmsg.harnesses.claude.enable = true in Home Manager installs the MCP server, the xmsg skill, tool permission rules under mcp__plugin_hm_xmsg__ and mcp__xmsg__, and all four subagent hooks automatically. See NixOS & Home Manager.

palette
dark
light
↑↓ select↵ apply esc close

Palettes adapted from Catppuccin (Macchiato) (MIT), Tokyo Night (Apache-2.0), gruvbox (MIT), Catppuccin (Latte) (MIT), Rosé Pine (Dawn) (MIT).