agentps is a Linux command-line tool for inspecting local CLI coding-agent sessions. It scans live processes and on-disk session artifacts, then presents them as a ps-like inventory with resume and cleanup operations.
It currently includes built-in handlers for:
- OpenAI Codex CLI
- Claude Code
- Gemini CLI
- opencode
For an introduction and walkthrough, see the agentps blog post.
- Lists live and historical agent sessions across supported tools
- Maps a live process back to its session artifact when possible
- Shows agent, PID, user, last-used time, cwd, session id, and launch context
- Resumes a session from its recorded working directory
- Deletes orphaned sessions or duplicate copies
- Provides a curses TUI for browsing, grouping, copying resume commands, and deleting sessions
- Linux only
- Python 3.11+
agentps requires /proc and is designed around the session layouts used by the supported CLIs on a local Linux machine.
From the repository:
python -m pip install .For development:
python -m pip install -e .This package uses only the Python standard library at runtime.
List sessions:
agentps listOpen the interactive view:
agentpsPrint JSON:
agentps --json listShow recent sessions found directly in agent config directories:
agentps --traces listStop a runaway agent, or every agent under a directory:
agentps kill 9b1c6f2eJoin a running agent — its tmux pane, or claude attach for a Claude
background session:
agentps attach 9b1c6f2eResume a session by id or unambiguous prefix:
agentps resume 9b1c6f2ePrint the resume command without executing it:
agentps resume --print 9b1c6f2eDelete sessions by id prefix:
agentps delete 9b1c6f2eDelete sessions whose recorded cwd no longer exists:
agentps delete --orphansDelete duplicate session copies across configured instances:
agentps delete --dupesagentps [OPTIONS] [top|list|resume|delete] [OPTIONS]
Global options are accepted on either side of the subcommand, so both of these work:
agentps --json list
agentps list --jsonSubcommands:
top: interactive TUI; also the default when no subcommand is givenlist: print the table to stdoutresume PREFIX: open the agent on a session, resumed from its recorded cwd. Where the agent has its own command for a running session it is used instead (claude attachfor a Claude background session). This never switches to a tmux pane — for an agent started by a wrapper the pane shows the wrapper, not the agent; useattachfor thatattach PREFIX: join a running session: its tmux pane, or the agent's own attach command where it has onekill ...: stop the sessions matched by id prefix or cwd pathdelete ...: delete sessions by id prefix or by cwd path
Global options:
--json: emit JSON instead of the table--traces: include per-agent recent-session scans from config dirs--all: looser process detection, with higher false-positive risk-d,--delay: TUI refresh interval in seconds;0disables auto-refresh--config PATH: alternate config file; governs both the UI settings and which agent instances exist. Missing file is an error rather than a silent fallback to the default
Kill options:
-9,--force: sendSIGKILLinstead ofSIGTERM-y,--yes: skip confirmation
kill stops a session through the agent's own stop command where it has one
(claude stop for a Claude background session, which keeps the conversation
resumable), and otherwise signals every process behind it. --force always
signals. It refuses to touch the session agentps itself was launched from, and
skips any process that exited and whose PID was reused while it waited for
confirmation.
Delete options:
--orphans: delete sessions whose cwd no longer exists. A cwd that was never recorded, or that cannot be checked (permissions, a hung mount), does not count--dupes: delete duplicate copies of the same session id-y,--yes: skip confirmation
AGENT: the instance name, which is the handler name unless an[[extra]]gave it another onePID: the process holding the session, or-for a session with nothing running. A trailing+Nmeans N further processes share the same session — opencode opens one per attached client — and the number shown is the lowestS: process state —Rrunning,Ssleeping,Duninterruptible,Tstopped,ZzombieUSER: owner of the sessionLAST_USED: from the session artifact, or from the agent's own database for agents that do not keep per-session filesAGE: how long the process has been runningIDLE: time since the session was last written — the activity signal for an agent nobody is watching. A longIDLEon a running process is an agent that is waiting or stuckCWD: the recorded working directory. Sessions whose cwd no longer exists are grouped below a separator inlist, and dimmed in the TUISESSION: shortened session idWHERE: tmux pane, screen, or ssh when the process can be traced to one;bg:<id>for a Claude background session (join it withagentps attach); otherwisevia:<name>for whatever launched it — a systemd unit, cron, or a script — which is the usual case for agents started headlessly
The TUI is a curses interface over the same inventory used by list.
Key actions:
j/kor arrow keys: moveEnteroro: open the agent on the session, or expand a groupSpace: mark row or groupa: join a running session: its tmux pane or the agent's attach commandc: copy the command that opens the session, using OSC52K: stop the focused or marked sessions (agent's stop command, else SIGTERM)d: delete focused or marked sessionsg: toggle group-by-cwds: toggle sort between date and pathr: refreshh: helpqorEsc: quit
Checked against Claude Code 2.1.300, Codex 0.155 (and the 0.162 source), Gemini CLI 0.41.2 (and the 0.64 source), and opencode 1.18 (and the 2.0 schema).
- Scans
~/.codex/sessions/ codex resume <id>restores the thread's own model, effort and provider, so none of them is replayed. Before codex 0.160 the approval policy and sandbox mode are replayed from the session's last turn context; from 0.160 codex restores them itself- Deletion runs
codex delete --force <id>, which also clears the thread's history, goals, queue and memory databases and refuses while a fork still references it. Direct SQL is a fallback only when the binary is missing - The app-server daemon, sandbox helpers and non-session subcommands
(
mcp,app-server, …) are not listed as sessions
- Scans
~/.claude/projects/ - Live processes are matched through Claude's own registry
(
~/.claude/sessions/<pid>.json), then--session-idon the command line, and only then by cwd - Background sessions (
claude --bg, and agents launched from another session) show asbg:<id>. Opening one runsclaude attach <id>—claude --resumerefuses a session that is still running — andkillrunsclaude stop <id> - Reads each session's own recorded
cwdfrom its JSONL. The encoded directory name is lossy —/home/u/my-projand/home/u/my/projencode identically — so it is only used for sessions that record nocwdof their own - Replays persisted permission mode on resume
- Deletion also removes the session's subagent transcripts, file history, saved environment, tasks and todos, and its background-job record unless that job owns a worktree
- Scans
~/.gemini/tmp/ - Deduplicates per-project snapshot files by inner
sessionId - Resumes with
gemini --resume <uuid>. Gemini accepts a full session id there even though--helponly mentions numbers; numbers count oldest-first and shift as sessions come and go - Replays launch-only flags such as yolo or approval settings only when a live process is available
- Reads
~/.local/share/opencode/opencode.db(SQLite); there are no per-session files - Supports both schemas:
session(1.x) andsession_v2(2.x). While 2.x is still migrating old sessions, the ones not yet copied are shown too - Only top-level sessions are listed; subagent sessions belong to their parent
- Archived sessions are hidden; the session id itself is used as the display id
- 1.x: replays the persisted model and agent on resume. 2.x reads them from the
session itself. Launch-only flags such as
--autoonly when a live process is available - Deletion removes the session, its subagent sessions and their event logs.
On 2.x it goes through
opencode session delete, since the shared background service owns the database while it runs - 2.x's shared background service (
opencode serve --service) is not listed as a session
Default config path:
~/.config/agentps/config.toml
Supported UI settings:
[ui]
sort = "date" # "date" or "path"
date = "%m-%d-%Y" # strftime format for LAST_USED
delay = 60You can add extra agent instances, such as alternate config roots:
[[extra]]
name = "codex-api"
handler = "codex"
dir = "~/.codex-api"
[[extra]]
name = "claude-work"
handler = "claude"
dir = "~/work/.claude"
[extra.env]
EXAMPLE_FLAG = "1"Each [[extra]] entry binds a handler to another base directory and optional environment variables used during resume. dir is the handler's base directory, which is not always a dotfile config dir — for opencode it is the data dir holding opencode.db (default ~/.local/share/opencode).
User-defined handlers can be placed in:
~/.config/agentps/handlers/
Each handler module must expose a top-level HANDLER object derived from the internal Handler interface. User handlers shadow built-in handlers of the same name.
- Linux only
- Session detection depends on the supported CLIs' current on-disk layouts
- Resume fidelity varies by agent; some launch flags are reconstructable only for live sessions
--allcan match unrelated processes if their command lines look similar to a supported agent
MIT. See LICENSE.