
April 15, 2026
We just shipped something at Roam that shows when your teammates are actively using Claude Code or Codex, live, on the office map.
Here’s how it works and how it got built.
Lots of us at Roam have individually been using Claude Code and Codex for a while, but we realized that we didn’t have a great sense of who else was using it or how much. The only signals were indirect. Someone mentioning it in standup. A PR landing with suspiciously articulate commit messages with lots of em dashes (or, less favorably, with a hundred tiny commits that each declared certain success but seemed to be going around in circles).
There’s a specific feeling in a physical office when a new tool starts spreading through a team. You glance at someone’s screen, see something unfamiliar, ask about it. That’s how tools actually propagate. Before Roam, remote work mostly killed that, but we are always looking for ways to bring it back.
Both Claude Code and Codex support hooks: small scripts that execute at points in the agent lifecycle. UserPromptSubmit fires at the start of a turn, the PostToolUse hook fires after each tool call, and Stop fires at the end of the turn. We use that to ping a tiny HTTP server that Roam spins up on a unix socket in the Electron main process. When the hook fires, Roam knows the agent is active and sends updates to the server
The full hook command for Claude Code:
cat > /dev/null; curl -sf --max-time 0.2 \
-X POST --unix-socket '~/.roam/roam-local-api.sock' \
"http://localhost/.../post-tool-use?pid=$PPID" \
>/dev/null 2>&1 || true
The cat >/dev/null at the start throws away everything Claude Code sends us. We don’t read your code, we don’t read the AI’s responses. We discard the entire payload and just register that something happened. This is privacy-preserving and auditable by anyone who can read a shell command.
The curl timeout ensures that even if Roam takes time to come back (which it shouldn’t) the hook doesn’t run long enough to trigger annoying status messages in Claude or the Codex TUI. (Unfortunately, for now, there’s no way around that in the Codex GUI, but the messages each have a fun hook icon next to them, so our Codex GUI users declare this not to be a blocker).
For Claude Code, $PPID — the parent process ID — works well for session tracking. Each terminal session is a different process, so concurrent sessions get different IDs naturally.
Codex is different. When you have multiple threads running in the Codex UI, they can share the same parent process. So using $PPID meant stopping one session would clear the presence indicator for all of them.
The fix: Codex hook payloads include a session_id field. So for Codex we actually do read the payload, but only in the shell command and just long enough to extract that one field:
payload=$(cat)
sid=$(printf '%s' "$payload" | grep -oE '"session_id"..."' | head
-1 | sed ...)
unset payload
When Claude Code is active for someone, their office on the map gets an orange halo. Codex is blue. Running both? The colors blend via alpha compositing on a canvas element with a conic gradient rotating at 60 degrees/second, pulsing on a sine wave. Three-layer rendering: a wide 16px-blur halo at 80% opacity, a 4px-blur main body, a sharp core edge. Activity stops, it fades over 800ms.
As with other animations in Roam, we degrade to something much simpler when you’re on battery, on older hardware, if you explicitly choose a lower performance mode, or are in a meeting.
People have already asked for token counts on the map: see how much your teammates are burning and win tokenmaxxing contests. Turns out Claude Code’s hook system doesn’t expose token counts in any of its 24 event types. The data exists in the API response and transcript files, but hooks are deliberately lightweight. But we have some ideas.
It’s opt-in. When you arrive in your office, Roam checks if you have Claude Code or Codex installed (it just looks for ~/.claude/ or ~/.codex/), then shows a modal asking if you want to turn the feature on. You can enable or disable it any time in settings.
I’m also glad to report that Codex was very gracious about being asked to add support for itself knowing that support for Claude was already in the code. Likewise, even after noticing that it was no longer the only coding agent supported by Roam, Claude remained upbeat when asked to make further changes to the feature. It even kept its snark to a 4/10 when confronted with Codex’s nitpicky but completely accurate reviews.