Claude Code is the adapter everything else is measured against. The briefing
arrives as real session context on SessionStart, and six session
hooks cover a session end to end.
What Runi installs#
Session hooks in ~/.claude/settings.json, which is Claude Code's
user-level config and not a project one, plus an entry for Runi's MCP server.
Because that file is user-level, one connect covers both the terminal CLI and the desktop app. IDE extensions drive the local CLI, so they follow too.
Careful
Claude Code on the web is not covered. It runs in a cloud sandbox, so a
hook there would execute on a remote machine with no ~/.relay
and no local session to observe. Terminal, desktop and IDE are all fine.
The six moments#
| Hook | What Runi does with it |
|---|---|
SessionStart critical |
Returns the team briefing as additionalContext, and adopts or mints the session's task card. This one is the product. |
UserPromptSubmit critical |
The only place a prompt is captured, and the only mid-session point where an approved teammate note or a live overlap warning can reach you. |
PreToolUse |
Notes the tool call about to run. Synchronous and does no I/O, so it cannot delay or block your agent. |
PostToolUse |
Records file edits by relative path, the lines changed, commands run and test results. |
Stop |
Turn end. The visible reply is redacted and read for decisions, discoveries, blockers and failed approaches, and the task brief is refined. |
SessionEnd |
Closes the session record and appends what changed to the task description. |
If SessionStart or UserPromptSubmit is missing, the
doctor reports a FAIL and not a warning. A
machine registered for only the later events publishes steps all day, so the
teammate looks busy, while every session starts with no briefing, no linked
task and no prompt.
How the briefing arrives#
Claude Code fires SessionStart, Runi replies with
hookSpecificOutput.additionalContext, and the CLI puts that in the
session's context. It is ordinary context, not a system prompt override and not
a file on disk, which is why you can ask the session what it received.
The packet asks for one line of attribution at the top of the first reply. That is how Runi knows afterwards whether the briefing was read rather than merely sent. See The brief.
Verify it#
$ runi doctor
…
ok hooks all 6 Claude Code events registered and their scripts exist
ok publish last event published 2 min ago
Registered is not the same as firing. The doctor also compares registration against what has arrived, and says so when an event has never been seen:
warn hooks registered but never observed firing: SessionStart —
other events have arrived, so the hook runs; these
specific ones are not reaching it
Test a hook by hand#
DRY_RUN=1 prints what would be published to stderr
and writes nothing. Stdout is the hook's structured channel, and anything
printed there breaks context injection, which is why diagnostics go the other
way.
$ echo '{"hook_event_name":"UserPromptSubmit","prompt":"key is sk-ant-xxxx"}' \
| DRY_RUN=1 node ~/.relay/daemon/hooks/claude.js
The prompt above carries a secret on purpose. What comes back should have it masked. That is the redaction pass running on your machine, before the event exists.
Known limits#
- Token usage is reported at turn boundaries, not continuously.
- File reads outside the repository root are not tracked.
- Shared work is authored in the app. The adapter does not summarise a session into a handoff for you.
- A note a teammate sends while your turn is already running reaches your next prompt, not the one in flight.
If Claude sessions are not appearing#
Are you in a tracked repository? Run runi doctor from the checkout and read the this repo line.
Add it in Settings → Repositories. See Repositories.
The hook points at a file that has gone. Almost always because Runi was connected from the portable build, whose folder disappears when you quit it.
Install Runi properly, then reconnect Claude Code from Settings → Agents.
Two Runi hook entries in ~/.claude/settings.json, usually left behind by an older install.
Disconnect and reconnect Claude Code once from Settings → Agents. The reconnect clears the duplicate.