Runi Help

Claude Code

Covers the terminal, the desktop app and your IDE from one connect. What it watches, and how to test it.

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#

HookWhat 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#

terminal
$ 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:

output
 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.

terminal
$ 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#

Hooks registered, nothing published
Check

Are you in a tracked repository? Run runi doctor from the checkout and read the this repo line.

Fix

Add it in Settings → Repositories. See Repositories.

“registered but pointing at missing file(s)”
Cause

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.

Fix

Install Runi properly, then reconnect Claude Code from Settings → Agents.

Every event arrives twice
Cause

Two Runi hook entries in ~/.claude/settings.json, usually left behind by an older install.

Fix

Disconnect and reconnect Claude Code once from Settings → Agents. The reconnect clears the duplicate.

Did this solve it?