Skip to content

Agent hooks: let Claude Code, Codex and Pi tell flue when a session needs you, finished, or wants a permission #132

Description

@karngyan

Why

The needs-you queue (#110) and push notifications (#109) plan to infer "waiting on input" from the terminal stream and from transcripts. Both are guesses, and both lag. The agents can say it outright: Claude Code has settings hooks (Notification, Stop, PreToolUse with a matcher on AskUserQuestion|ExitPlanMode, SessionStart, SessionEnd, and a permission request hook), Codex has a hooks system plus notify in config.toml, and Pi has extensions with a JS API. Every one of them can run a command. flue ships a binary, so the command is flue hook.

This is the signal source that the queue, push, Slack (#116) and a mobile chat view all want, and it works whether or not flue started the agent.

Rough scope

  • flue hook <tool> <event>: reads the hook's JSON on stdin, finds the local daemon socket, posts one event {tool, sessionId, cwd, pid, event, payload} and exits. Fast, never blocks the agent, and a missing daemon is a silent no-op so a hook never breaks someone's claude.
  • The daemon matches the event to a flue session. First by pid ancestry (the holder knows its child pid, the hook runs under the agent), then by cwd as the fallback. The same match gives the exact transcript session id for a live session, which today is only guessed once, at shutdown, in internal/session/snapshot.go (agentSessionFor).
  • A small per-session state: running, waiting (with a reason: permission, question, plan approval, idle after stop), exited. Additive on Info and the wire. This is what Needs-you queue: fleet-wide list of sessions blocked on a prompt #110 badges, Push notifications: agent finished, needs input, terminal bell #109 pushes, and Slack notifications for agent events #116 posts.
  • Install story: flue enable offers to add the hooks and flue hooks install|uninstall|status does it by hand. Ask, never silent. ~/.claude/settings.json and ~/.codex/config.toml are the user's files: merge, never clobber, and leave their other hooks alone. Codex has hook trust; document the one-time step.
  • Permission relay, Claude first: the permission hook blocks, the daemon shows the request on every attached device, a tap answers allow or deny, and a timeout falls through to the normal terminal prompt so nothing hangs when no device is watching. This is the piece that lets a phone chat view approve without a terminal.
  • Pi: a tiny extension that posts the same events. Same event shape, same daemon endpoint.

Notes

  • Hook payloads are unversioned and move. Verify every schema against the installed CLIs at build time and follow the agentstore rule: skip what you cannot parse, never fail on it.
  • Terminal heuristics from Needs-you queue: fleet-wide list of sessions blocked on a prompt #110 stay as the fallback for plain shells and agents without hooks. Hooks make the common case exact; they do not replace the general case.
  • Events carry cwd and session ids, the same sensitivity as session metadata. They ride the existing daemon trust boundary and nothing new leaves the machine.

Where to look

  • internal/session/agents.go, internal/session/claude.go, internal/session/snapshot.go:215 (the shutdown-time agent guess this replaces for live sessions)
  • internal/holder/holder.go (child pid ownership)
  • internal/wire/control.go (Info, additive field)
  • ~/.claude/settings.json hooks block on any machine with Claude Code, codex --help (hook trust flag), pi --help (extensions)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestepicLarge feature. Decide and break down before building.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions