Hooks
Optional. braids works without them, and says which state it is in on every screen.
What a hook adds
Files cannot tell you the difference between a session that is running and one that has stopped to ask your permission. Both look like a transcript that has not changed in a while. A hook can, because the harness tells it.
With the hook installed, the map's state column separates
stopped, needs you from working from
idle, and n walks between the ones waiting on you.
Without it, braids falls back to what the transcript can prove: whose turn was
last, and how long ago. The Hooks: line in the header says which
you are getting.
Installing and removing
braids hooks # what is installed now
braids hooks --install
braids hooks --remove
braids hooks --json
This edits ~/.claude/settings.json and subscribes to six events:
PermissionRequest, Notification, Stop,
SubagentStop, SessionStart and
SessionEnd. Use --settings to point at another file.
It merges. Hooks you already have on those events are left exactly where they are, and --remove takes back only the entries braids added, entry by entry.
If you installed the plugin, you already have these
The plugin registers the same six events, so running
braids hooks --install on top of it leaves two hooks on every
one. Claude Code runs a plugin's hooks alongside the ones in your settings
file and does not notice they are the same tool, so both fire and every
event is recorded twice.
Nothing looks wrong when this happens, which is the awkward part. Waiting
states are read from the newest event for a session, and a duplicate is the
same event again, so the map stays correct. What grows is
~/.braids/events.jsonl, at twice the rate, for good.
braids doctor reports it and names the copy that is safe to
remove.
braids hooks --remove # keep the plugin's, drop the ones in settings.json
Identified by program, not by path
A braids hook is recognised by the program name in its command, not by the
full path. Otherwise a binary at ~/go/bin/braids and one built in
a checkout are two different hooks: the repo build reports
not installed while the installed one is reporting, and
--install adds a second entry that does the same job.
braids hook is not for you
braids hook is the command the harness runs. It reads a JSON
event on stdin and records it. Typed by hand it used to sit there waiting for
input that was never coming, so it now refuses a terminal and says what it is
for.
braids hook # braids: hook reads an event on stdin and is run by Claude Code, not by hand # (try: braids hooks)