Skip to content

samling/agent-explorer

Repository files navigation

agent-status

A hook collector and live status board for local coding-agent sessions.

Screenshot

Install

Release tarball

curl -L https://github.com/samling/agent-status/releases/latest/download/agent-status_<version>_linux-amd64.tar.gz | tar xz
sudo install agent-status_*/agent-status /usr/local/bin/

From source

go install github.com/samling/agent-status/cmd/agent-status@latest

Build it yourself

git clone https://github.com/samling/agent-status.git
cd agent-status
make install

How It Works

AI agents like Claude Code, Codex, and opencode support hooks or plugins that enable users to execute actions at various points in the agent's lifecycle (new session, prompt submitted, tool used, etc.). We configure Claude Code and Codex hooks to execute a forwarder script, and configure opencode to load a plugin, to POST events to the collector (agent-status server). The collector receives those events over local HTTP and persists per-session state. Agent state files and databases are also checked for locally to discover live sessions and reap stale ones. Clients (the TUI agent-status ui, agent-status statusline, agent-status focus <session_id>) read live state through the collector's GET /state HTTP endpoints, so the daemon is the single source of truth.

The data read by agent-status is local and only data provided by the supported agents. Nothing ever leaves your machine. agent-status uses the presence of certain files (e.g. ~/.claude/sessions/*.jsonl) to infer the existence of sessions; it uses the contents to provide information on that session (model name, agent version, a preview of the last submitted prompt). This data already exists unencrypted on your machine; poke around ~/.claude, ~/.codex, ~/.local/share/opencode, etc. if you're curious. Absolutely no data is collected by me from service nor will it ever be. A non-exhaustive list of data and locations checked includes:

  • Claude Code hook payloads (event-specific data - prompt submitted, tool used, session started/ended, awaiting input, etc.)
  • Claude Code data in ~/.claude, specifically sessions and projects (session-specific data - model used, creation date, current session status, etc.)
  • Codex hook payloads (event-specific data - prompt submitted, tool used, session started/ended, awaiting input, etc.)
  • Codex data in ~/.codex, specifically state_*.sqlite, logs_*.sqlite, and sessions (session-specific data - model used, creation date, current session status, etc.)
    • shell_snapshots/ is checked for the presence of a session file as it's currently the only way I've found to determine when a new Codex session is started before sending the first message
  • opencode plugin events: session/message/tool/permission activity posted to the local collector
  • opencode data in $XDG_DATA_HOME/opencode (default ~/.local/share/opencode), specifically opencode.db for session metadata and messages

This tool aggregates that data, tracks state by agent and session id, and presents it in a terminal UI.

Compatibility

I made this tool for me initially, which means I've prioritized my own use cases first. It builds for ARM and so I presume it will work there too.

Note on arm64: the SQLite driver is modernc.org/sqlite (pure Go, no CGo) so cross-compilation stays simple, but it is meaningfully slower than the CGo-based driver on arm64. Personal use is fine; if you ever pin this against larger Codex state databases on an arm64 host and notice query latency, that's the trade-off.

The mechanism to bring focus to active sessions (called "activating a window") varies greatly across OSes, desktop environments and sometimes applications. I primarily work in tmux and using the VSCode extension in CLI mode, so those were my initial targets. It has limited or (more likely) no support (yet) for other DEs/compositors.

OS Shell/DE/Compositor Supported Notes
Windows (WSL) Windows Shell Can focus VSCode and VSCode-variant host applications from WSL terminal
Linux tmux Can focus tmux panes directly
niri Can focus other windows running claude-code
hyprland
gnome
kde
others
MacOS MacOS

Setup

Run the bootstrap subcommand from the installed binary:

agent-status bootstrap

It configures Claude Code, Codex, and opencode and will:

  1. Install a single shared forwarder script to $XDG_CONFIG_HOME/agent-status/post-agent-status.sh (default ~/.config/agent-status/post-agent-status.sh). Claude Code and Codex hook configs point at this one location.
  2. Install the opencode plugin asset to $XDG_CONFIG_HOME/agent-status/opencode-agent-status-plugin.js.
  3. Render the embedded hook templates with the absolute path to the forwarder.
  4. Merge the rendered Claude Code hooks into ~/.claude/settings.json, Codex hooks into ~/.codex/hooks.json, and the opencode plugin path into the opencode config. If a file already exists, the merge leaves a .bak.<timestamp> next to the original. Existing hook entries that reference any prior post-agent-status.sh, and existing opencode plugin entries that reference any prior opencode-agent-status-plugin.js, are replaced (not duplicated) with the new one.
  5. Remove any per-agent script copies left behind by earlier installs (~/.claude/scripts/post-agent-status.sh, ~/.codex/scripts/post-agent-status.sh); modified copies are backed up first.

The planned changes are printed before any files are written, and the command asks for confirmation. Useful flags:

  • --yes skip the confirmation prompt
  • --dry-run print the plan without writing anything
  • --agents=claude, --agents=codex, or --agents=opencode configure just one agent
  • --claude-dir / --codex-dir / --opencode-dir override the config dir for an agent

CLAUDE_CONFIG_DIR, CODEX_HOME, and OPENCODE_CONFIG_DIR are honored when their respective --*-dir flags aren't passed.

The forwarder and opencode plugin discover the collector's address at runtime, so changing --addr / --port (or the matching config keys) only requires restarting the server — no need to re-run bootstrap. Both assets use this shared resolution order:

  1. $AGENT_STATUS_ENDPOINT (e.g. 127.0.0.1:7878) if set in the agent's environment.
  2. $XDG_STATE_HOME/agent-status/endpoint (default ~/.local/state/agent-status/endpoint), which the server writes on startup.
  3. 127.0.0.1:7878 fallback.

Manual setup

If you'd rather wire the hooks yourself, the templates, forwarder, and opencode plugin asset live at internal/bootstrap/assets/. Copy post-agent-status.sh and opencode-agent-status-plugin.js to $XDG_CONFIG_HOME/agent-status/, replace path-to-post-agent-status in claude-code.json / codex.json with that absolute path, then merge the rendered JSON into ~/.claude/settings.json and write it to ~/.codex/hooks.json. Add the opencode plugin asset path to the plugin array in your opencode config (opencode.jsonc, opencode.json, or config.json). The script and plugin read the collector's address from $XDG_STATE_HOME/agent-status/endpoint at runtime, so the same assets work regardless of which port the server runs on.

Configure

Configuration is stored in $XDG_CONFIG_HOME/agent-status/config.yaml. On most systems XDG_CONFIG_HOME=$HOME/.config.

The state file is stored in $XDG_STATE_HOME/agent-status/state.json. On most systems XDG_STATE_HOME=$HOME/.local/state.

Run

Start the server:

agent-status server

By default the collector listens on 127.0.0.1:7878. Override with agent-status server --addr <addr> --port <port>.

Open the UI:

agent-status ui

See agent-status -h and subcommand -h output for configuration.

HTTP API

The collector exposes a local JSON API:

  • POST /hook records agent hook events.
  • GET /state lists live sessions.
  • GET /state/{session_id} returns one live session.
  • GET /state/{session_id}/transcript returns parsed transcript metadata.
  • GET /meta returns discovery metadata keyed by session id.
  • GET /healthz returns collector health.
  • GET /version returns the running collector version.

Notifications

Desktop notifications are enabled by default when the server runs, and fire immediately when a session starts waiting. Disable them with --notify=false or server.notify.enabled: false in config:

agent-status server --notify=false

Useful notification flags include --notify-initial-delay, --notify-repeat, --notify-title, --notify-body, and --notify-action-label.

Run the collector as a user service

A reference systemd user unit lives at contrib/systemd/user/agent-status.service. To install it:

make install-service
systemctl --user enable --now agent-status

Or by hand:

mkdir -p ~/.config/systemd/user
cp contrib/systemd/user/agent-status.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now agent-status

The unit assumes agent-status is on PATH at /usr/bin/agent-status. Edit ExecStart= if yours lives elsewhere (e.g. ~/go/bin/agent-status).

Launch from a tmux popup

Bind the UI to a tmux popup so it overlays the current pane and dismisses itself once you focus a session (requires tmux >= 3.2 for popup support):

set-hook -g session-created 'if -F "#{==:#{session_name},agent-status}" "set-option -t agent-status status off"'

bind o if-shell -F "#{==:#{session_name},agent-status}" {
  detach-client
} {
  display-popup -E "tmux new-session -A -s agent-status 'agent-status ui --quit-after-focus'"
}

The --quit-after-focus flag exits the TUI after enter focuses a session, which lets display-popup -E close the popup automatically. Omit the flag if you'd rather the popup stay open until you press q.

Logging

Logging is log/slog-based and gated by LOG_LEVEL (or log.level in config / --log-level). Set LOG_FORMAT=json for machine-friendly output.

Develop

make build      # bin/agent-status
make test       # go test ./...
make clean

About

An API and live status board for AI agent session management.

Resources

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages