DEV Community

Jake Barnby
Jake Barnby

Posted on

magents: hand a live session from Claude Code to Codex (or Cursor, Grok, Gemini, OpenCode) without recapping

I use more than one coding agent every day. Claude Code for some things, Codex for others, Cursor when I want the editor, Grok when I want a second opinion. The work moves between them all the time, but the context doesn't. Every switch meant opening a new window and explaining the same branch, the same failing test and the same constraint I had already explained once.

The frustrating part is that the context is already on my disk. Each of these tools writes its session transcript somewhere under my home directory. Nothing reads across them.

So I wrote magents: a Rust MCP server plus a small CLI that is a shared API over those sessions. It is not a second copy of history and it is not a "council of agents". Your existing chats stay the unit of work. magents just lets them see and reach each other.

What it does

It supports Claude Code, Codex, Copilot CLI, Cursor, Gemini CLI, Grok and OpenCode. Inside any of them you get roughly four moves.

Read another session. list_sessions, session_digest and read_transcript let the agent you're in see what another one was doing: the last request, the last action, the working directory and the branch. I can sit in Grok and ask "what was Claude doing on the disaster-recovery branch?", and it reads the live session and carries on.

Send into a specific chat. send_message delivers a user turn into an existing session. That's useful when one agent hits a wall that another agent's session already owns, because the sender already has the failing query and the file in hand. I don't have to be the messenger.

Hand off. handoff compacts the current session and injects it into another live one, so that session continues the same work.

Spawn independent work. spawn_session starts a new headless, persisted session with a complete task, an optional isolated working directory, and a request to reply through magents. Spawned sessions keep their host's own approval policy. magents never adds flags like --dangerously-skip-permissions, --yolo or --full-auto.

Replies come back through a small mailbox (inbox, ack, await_reply, reply) stored under magents' own directory. A spawned Codex session can report back to the Claude session that started it.

One rule matters a lot here. Transcripts from other agents are treated as inert, untrusted history. The agent reads them as data, not as instructions to follow.

How it works

magents doesn't keep its own index. It reads each host's own files when you ask:

  • Claude: ~/.claude/sessions
  • Codex: its SQLite state plus rollout JSONL
  • Cursor: agent-transcripts
  • OpenCode: its SQLite database
  • Gemini CLI: its journals
  • Copilot CLI: session-state
  • Grok: ~/.grok/active_sessions.json

A few details from the Rust side:

  • SQLite. rusqlite opens the host databases with SQLITE_OPEN_READ_ONLY, so a running agent never competes with magents for a write lock.
  • Delivery into existing chats. magents always records the message in its mailbox first, then uses the most direct path the host has. That's a Unix-socket user turn for Claude, length-prefixed JSON-RPC on Codex Desktop's IPC socket, and otherwise a supervised headless resume of that exact session (codex exec … resume, cursor-agent --resume, gemini --resume, and so on). The user turn goes over stdin, never as a process argument.
  • Supervisor. It is plain tokio::process with each child in its own process group (setpgid/setsid in pre_exec), so stopping a session signals the whole group rather than one PID.
  • Format drift. Each host's on-disk format changes underneath you. OpenCode v2 is the latest example: it moved sessions into new session_v2 and session_message tables and dropped run --dir. 0.13.1 reads both the v1 and v2 layouts. CI runs clippy with -D warnings and a 98% line-coverage gate, mostly to catch this kind of drift early.

Install

brew install abnegate/tap/magents   # or: cargo install magents --locked
magents install --all
Enter fullscreen mode Exit fullscreen mode

install --all registers the stdio server (magents mcp) with every host it finds: Claude Code, Codex, Cursor, Gemini CLI, Copilot CLI, OpenCode and Grok. It skips any host that isn't installed, and it adds the magents skill to each one. There are also APT packages, static binaries for macOS and Linux, and a container image at ghcr.io/abnegate/magents.

If you prefer plugins, the repo ships packages for Claude Code, Codex and Cursor under plugins/. Gemini CLI can install it straight from the repo:

gemini extensions install https://github.com/abnegate/magents
Enter fullscreen mode Exit fullscreen mode

Cline and other MCP clients only need {"command": "magents", "args": ["mcp"]}.

A short example

From a terminal:

magents list --live                      # every live session, across all agents
magents digest claude:latest             # last request, last action, cwd, branch
magents handoff codex:latest --reason "continuing in codex"
magents spawn codex --prompt-file task.md --cwd ../wt-flaky-test
Enter fullscreen mode Exit fullscreen mode

In practice I rarely type those myself. I ask the agent I'm in: "what was Codex doing in this repo?" or "send this failing query to the Claude session on the migration branch". It calls the matching tool. Every command also takes --output json if you want to script it.

How it compares to hcom and puenteo

A couple of other projects work on the same problem, and they're worth knowing about.

  • hcom connects agents through hooks. You start an agent with hcom in front (hcom claude, hcom codex). Its hooks record activity into a local SQLite database and deliver messages from it. That gets you real-time messaging, subscriptions to status and file-edit events, and a TUI dashboard. It also supports several CLIs that magents doesn't read yet.
  • puenteo is a Python tool with a wider surface. It has ranked full-text search over many agents' history, live messaging with channels, file and directory claims for parallel agents, and CLI, MCP, HTTP/SSE and A2A interfaces with a web dashboard.

magents is narrower. It's a single Rust binary that speaks stdio MCP. It works on sessions you started normally, with no wrapper command and no hooks, because it reads the files the hosts already write. It delivers into an existing chat through that host's own channel where one exists. If you want channels, file claims or a dashboard, the other two have them. If you want to move a live task between agents without retyping it, or have agents work with each other without you in the middle, that's what magents is built for.

More info

Top comments (1)

Collapse
 
fable7 profile image
fable7 •

Nice timing on the OpenCode v2 point. I hit that same drift from the outside: five calls against v1 and v2 servers gave me three errors, one success-shaped no-op, and one real answer, with run --dir disappearing in the middle of it. Reading both layouts is the right call, because the silent failure is the expensive one.

On handoff: do you compact the session yourself before injecting it, or let the host's own compaction run first? Which slice of a session survives that is the part I keep getting wrong.