Your kitty tabs show what each coding agent is doing.
Blue while it works, amber when it needs you, back to normal when it's done.
Run several agents across kitty tabs and you lose track of which one is grinding, which one is blocked on you, and which one finished ten minutes ago. kitty-agent-status paints each tab by state, so a glance at the tab bar tells you where to look. No daemon, no dependencies - just your agents' own lifecycle events wired to kitten @ set-tab-color.
| Tab color | State | Means |
|---|---|---|
| π΅ blue | working |
the agent is generating right now |
| π amber | needs-input |
it is blocked on you - a permission prompt, or Codex finished its turn |
| βͺ default | done |
idle / finished - nothing for you to do |
A finished agent reverts to your normal tab color, so amber always means act on me.
Each agent exposes a different signal, so the tab is driven from whatever each one offers:
- Claude Code - three hooks:
UserPromptSubmitβ blue,Stopβ default, andNotification(only thepermission_promptmatcher) β amber. Idle "waiting for input" notifications are ignored on purpose, so a finished session does not get stuck amber. - Any agent in your shell - a tiny
preexec/precmdintegration (bash and zsh) turns the tab blue while a known agent command runs and reverts it at the next prompt. Configure which commands count withKAS_AGENT_RE. - Codex - point its
notifyat the bundled chain script; it goes amber on each completed turn and forwards your existing notify program untouched. - The bell - kitty's built-in
bell_on_tabalready flags any tab whose program rings the bell, a free catch-all for agents that signal that way.
Everything funnels through one script, agent-status.sh <state>, which is a no-op outside kitty.
One line - copies the scripts into ~/.config/kitty/agent-status, sources the shell integration from your ~/.zshrc / ~/.bashrc, and wires the Claude Code hooks:
curl -fsSL https://raw.githubusercontent.com/oleg-koval/kitty-agent-status/main/install.sh | bashOpen a new kitty tab (or source ~/.zshrc) and it's live. Pass --no-claude to skip the Claude Code hooks. Re-running is idempotent.
Manual install
# 1. grab the scripts
DEST=~/.config/kitty/agent-status
mkdir -p "$DEST/shell"
base=https://raw.githubusercontent.com/oleg-koval/kitty-agent-status/main
for f in agent-status.sh codex-notify.sh shell/integration.sh; do
curl -fsSL "$base/$f" -o "$DEST/$f"
done
chmod +x "$DEST"/*.sh
# 2. shell integration β add to ~/.zshrc and/or ~/.bashrc
echo 'source ~/.config/kitty/agent-status/shell/integration.sh' >> ~/.zshrc
# 3. Claude Code hooks β add to ~/.claude/settings.json "hooks":
# "UserPromptSubmit": [{"hooks":[{"type":"command","command":"~/.config/kitty/agent-status/agent-status.sh working"}]}]
# "Stop": [{"hooks":[{"type":"command","command":"~/.config/kitty/agent-status/agent-status.sh done"}]}]
# "Notification": [{"matcher":"permission_prompt","hooks":[{"type":"command","command":"~/.config/kitty/agent-status/agent-status.sh needs-input"}]}]Codex allows a single notify program. Point it at the chain script, which tints the tab and then forwards to whatever you had before:
# ~/.codex/config.toml
notify = ["/Users/you/.config/kitty/agent-status/codex-notify.sh"]Already using notify (e.g. a desktop notifier)? Keep it running:
export CODEX_NOTIFY_FORWARD="/path/to/your/old/notify"Everything is environment variables - set them before the integration is sourced (e.g. earlier in your rc).
| Variable | Default | Purpose |
|---|---|---|
KAS_AGENT_RE |
^(codex|gemini|cursor-agent|aider|opencode|crush|goose)([[:space:]]|$) |
which commands tint the tab blue. Add your own; Claude Code is excluded because its hooks are more precise |
KAS_WORKING_BG / KAS_WORKING_FG |
#1f6feb / #ffffff |
working color |
KAS_ATTENTION_BG / KAS_ATTENTION_FG |
#d29922 / #000000 |
needs-you color |
KAS_BIN |
auto | path to agent-status.sh (resolved automatically) |
Colors accept a #rrggbb value, a kitty color name, or NONE.
- kitty with
allow_remote_controlenabled (yesorsocket-only) - bash or zsh for the shell integration
- python3 (only the installer uses it, to edit
settings.json)
rm -rf ~/.config/kitty/agent-statusThen remove the source .../integration.sh line from your shell rc, the three
agent-status.sh hooks from ~/.claude/settings.json, and the notify line
from ~/.codex/config.toml if you set it.
- No dependencies, no daemon, no network. It only calls
kitten @ set-tab-color. - Read-only toward your work. It reads the name of the command you ran and the state your agent reports. It never reads your code or an agent's output.
- Never breaks a prompt. Color calls are best-effort; outside kitty every entry point is a clean no-op.
Issues and PRs welcome - see CONTRIBUTING.md. It's a handful of shell scripts; let's keep it tiny.
MIT Β© Oleg Koval