Agents
insensical learns a coding agent's state in two ways.
- With no setup, from what agents already write to their terminal: progress, notifications and the bell, as described in States and attention.
- Exactly, from the agent's own hooks, which call
isc status. insensical can add those hooks for Claude Code, Codex, Gemini CLI, opencode and pi.
Only the Claude Code integration has been used. The other four are written from each agent's documentation and source code as of October 2026, and tested with the events those describe. They haven't been tried against the agents themselves.
Setting up from the window
When the window opens and there's an agent on the system that doesn't report yet, the top bar says so. For example: "Codex does not show its state yet · Set up".
- Press it to list those agents, with the file each change goes in.
- Press Enter to add them. Nothing is ever added without that Enter.
- Press Escape to leave it for later. The notice stays.
- Press
N, or click the cross on the notice, to say never. Those agents aren't offered again. - After adding, a line tells you what's still yours to do. For Codex, that's trusting the hooks with
/hooks. - "Have the agents on this system say what they are doing" in the palette asks at any time, and includes the agents you declined.
The agents you declined are kept in ~/.local/state/insensical/agents-declined, one per line. Delete a line to be offered that agent again.
Setting up from the command line
| Command | Does |
|---|---|
isc integrate | Finds the agents on this system and offers each one. It says which were found and which weren't, then for each one found it shows what would change and asks. |
isc integrate claude | The same for one agent: claude, codex, gemini, opencode or pi. |
isc integrate --yes | Adds every agent that was found, without asking. |
isc integrate --remove | Removes them all. If you name an agent, removes that one. |
isc integrate --status | Prints what was found and what already reports, as JSON. Changes nothing. |
- An agent counts as found when its program is on
PATHor its settings directory exists. - An agent that's already integrated says "nothing to change".
- Nothing is added without asking, and nothing is added for an agent that isn't on the system.
- When there's no terminal to ask on,
isc integratechanges nothing unless you pass--yes, and exits with status 1. - You can't combine
--statuswith--removeor--yes. For each agent it printsagent(the name used on the command line),title,found,integrated,file(where its hooks go) andthen(what's left for you to do afterwards, or null).
The hooks name the isc binary by the full path it had when you ran integrate. If you move isc or reinstall it somewhere else, the hooks point at nothing. The agent's state stops being reported, --status says it isn't integrated, and the window offers to set it up again. Run isc integrate for that agent to rewrite the hooks so they name the isc you ran.
Claude Code
isc integrate claude adds hooks to Claude Code's settings: ~/.claude/settings.json, or under $CLAUDE_CONFIG_DIR.
- Hooks that are already there are kept, and stay first.
- A copy of your original settings is saved next to them, as
settings.json.before-insensical. It's written once. --removetakes the hooks out and leaves what was there before.- The hook prints nothing, never fails, runs separately from Claude's own work, and does nothing outside a pane.
| Claude Code event | State |
|---|---|
| A prompt is submitted; a tool has run | running |
| Permission is asked for; it asks a question | waiting, with what it's asking |
| It has finished responding | done, with the first line of what it said. It stays done no matter how long it then sits at its prompt. |
| It stopped on an error | failed |
| A session starts or ends | idle |
Each event also names Claude's session. That's how the pane can offer claude --resume … after the daemon has stopped (Stopping, restarting and new versions).
Codex
isc integrate codex adds hooks to ~/.codex/hooks.json, or under $CODEX_HOME. A copy of the original file is saved next to it, as hooks.json.before-insensical. It's written once.
- Codex does not run a hook until you have trusted it. After integrating, open Codex, run
/hooks, and trust the new ones. Until you do, nothing is reported. - If
iscmoves and you add the hooks again, you have to trust them again. - A prompt or a finished tool gives
running. A request for approval giveswaiting. The end of a turn givesdone, with the first line of what it said. An interrupted turn givesidle. - A turn that fails isn't reported, because Codex has no event for it.
- The pane offers
codex resume <session>after the daemon has stopped.
Gemini CLI
isc integrate gemini adds hooks to ~/.gemini/settings.json, or to $GEMINI_CLI_HOME/.gemini/settings.json. A copy of your original settings is saved next to them, as settings.json.before-insensical. It's written once.
- A prompt or a finished tool gives
running. Asking to use a tool giveswaiting, with its question. The end of a turn givesdone, with the first line of its answer. - A failed or cancelled turn isn't reported. Gemini CLI has no event for either, so the pane stays
runninguntil the next prompt. - No resume command is offered.
- Gemini waits for its hooks. The hook answers at once. If the daemon is stuck, Gemini is held up for three seconds at most.
opencode
isc integrate opencode writes one file, ~/.config/opencode/plugins/insensical.js (under $XDG_CONFIG_HOME if that's set). opencode loads it when it starts. --remove deletes it.
- Working gives
running. Asking for permission or asking a question giveswaiting. Going quiet after working givesdone. An error givesfailed, with its message. A turn you stopped givesidle. - Sessions that opencode starts itself (subagents) aren't reported.
- The pane offers
opencode --session <id>after the daemon has stopped.
pi
isc integrate pi writes one file, ~/.pi/agent/extensions/insensical.ts, or under $PI_CODING_AGENT_DIR. pi loads it when it starts. --remove deletes it.
- Working gives
running. A dialog that an extension puts up giveswaiting, with its title (pi itself never asks before using a tool). Finishing givesdone, with what it said last. Ending in an error givesfailed. Stopping it yourself givesidle. - pi reports only when it's running with a screen. Its other modes don't report.
- The pane offers
pi --session <id>after the daemon has stopped.
Any other agent or script
Any agent or script can call isc status and isc notify from its own hooks.
isc status running
isc status waiting -m "Allow \`cargo publish\`?"
isc status done
isc status running --resume "mytool --continue 42"
isc notify "Build" "Finished"--resumesays how to pick the work up again. The pane offers that command at its prompt after the daemon has stopped.isc statusandisc notifyspeak for a pane, and never guess which one. Inside a pane they need nothing more. Outside one they need--pane.- These two commands, and the agents' hooks, work even when
iscand the daemon are different versions.