Agent History — search, inspect, and resume coding-agent sessions from a single CLI.
ah discovers session files from Claude Code, Codex, Gemini CLI, Cursor, GitHub Copilot CLI, Antigravity CLI (agy), Grok CLI (grok), and opencode (opencode). It works with zero config, defaults to the current directory, and gives you one place to search, inspect, and resume past work.
Read-only by default. ah works directly on agent session files, lets you search and inspect them, and only executes when you explicitly run resume.
On a TTY, ah log outputs in git log style with auto-pager. Defaults to current directory:
$ ah log
session a1b2c3d4-5e6f-7a8b-9c0d-e1f2a3b4c5d6
Agent: claude
Project: my-webapp
Cwd: /home/user/src/my-webapp
Date: 2026-03-23 14:00 - 2026-03-23 18:00
implement OAuth2 authentication flow
session e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b
Agent: cursor
Project: my-webapp
Cwd: /home/user/src/my-webapp
Date: 2026-03-23 12:15 - 2026-03-23 14:22
fix memory leak in worker poolPick a session ID from the log and resume it — ah launches the original agent's resume command (e.g. claude --resume):
$ ah resume a1b2c3d4-5e6f-7a8b-9c0d-e1f2a3b4c5d6Want the exact command first without executing anything?
$ ah resume --print a1b2c3d4-5e6f-7a8b-9c0d-e1f2a3b4c5d6
cd '/home/user/src/my-webapp' && 'claude' '--resume' 'a1b2c3d4-5e6f-7a8b-9c0d-e1f2a3b4c5d6'Or browse and filter sessions with -i (via fzf or compatible finder, with transcript preview):
$ ah resume -iFull-text search across all directories (piped output is plain TSV). -q searches the conversation — user and assistant messages plus tool calls (commands, arguments, file paths) and tool output — not JSON keys or injected instructions. Use -p to search only your prompts, or --raw-search to match the raw session files including metadata:
$ ah log -a -q "OAuth" | head -3
claude my-webapp 2026-03-23 18:00 implement OAuth2 authentication flow ...implement OAuth2 auth... a1b2c3d4-5e6f-7a8b-9c0d-e1f2a3b4c5d6
cursor my-webapp 2026-03-23 14:22 fix memory leak in worker pool ...reviewing the OAuth token... e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b
codex api-server 2026-03-22 11:30 add Redis caching layer ...cache OAuth tokens with 1h TTL... sess_7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2bFind the actual passages instead of just the sessions:
ah search 'OAuth' # every occurrence in the current directory
ah search 'OAuth' -a --json # JSON Lines across all directories
ah search '認証' -p # user prompts only
ah search 'error' --max-matches 20
ah search 'OAuth' --verbose # full log paths and match positions on TTY
ah search 'OAuth' --kind user,assistant # conversation text only
ah search 'error' --kind tool-output # tool results only
ah search 'OAuth' -i # pick a hit, preview context, Enter to showlog -q returns one row per session with its first matching excerpt.
search returns one row per non-overlapping regex occurrence, including
multiple occurrences in a single message and matches in tool input/output.
It uses the same case-insensitive regex and content extraction as log -q.
No index or external search service is required.
On a terminal, passages are grouped by session with an automatic pager.
Like rg --heading or git grep --heading --break, the default display puts
one heading above each group of passages and a blank line between sessions.
Session headings are cyan and bold, titles are bold, and dates are dim.
Each passage appears on its own indented line with a structural kind label
(user, assistant, tool-input, tool-output, or unknown), with the current occurrence
highlighted in bold yellow. Full log paths and position labels are omitted by
default so the passages stay compact. Remote session headings keep a
remote:NAME label to distinguish hosts.
Use -v / --verbose to show the full log path and a dim position line before
each passage. Positions are labeled text #N bytes START..END: text #N
is a search-fragment index, not a transcript line number. Verbose output
also includes an opaque at POSITION token and separates passages with blank lines. This flag only affects terminal
output; JSON/TSV retain all their existing fields and formatting.
If a match is clipped by the snippet limit, only its visible portion is
highlighted. --no-color and
NO_COLOR disable styling; NO_COLOR takes precedence over --color, as with
other commands. JSON/TSV output never receives display colors.
Piped output is TSV without a header, with these columns:
path, agent, project, id, text_index, match_start, match_end, snippet, kind, position.
Tabs, newlines, carriage returns, and backslashes are escaped as \t, \n,
\r, and \\. JSON Lines contains the same fields plus modified_at and
title, with numbers represented as JSON numbers.
text_indexis a 1-based index of nonempty search fragments, counted before kind filtering. It is not a transcript message number. One tool call can yield several fragments. Useposition, not this index, for navigation.kindis derived from log structure, never inferred from the text. Ambiguous records remainunknown(for example, Antigravity's generic model records).--kindaccepts a comma-separated union; the default includes every kind.-pis shorthand for--kind userand includes all user text parts, but not tool results stored in user-role containers. It cannot be combined with other kinds.log -p -qkeeps its existing prompt extraction behavior.positionis an opaque versioned location within the session identified bypath. It includes a fingerprint of the searchable source prefix. Do not construct it yourself. Filtering and snippet length do not change positions; appending records preserves them. An edited/reordered prefix requires a new search instead of silently opening a different occurrence.match_start/match_endare 0-based UTF-8 byte offsets, with an exclusive end, in the decoded fragment (not the snippet or raw file).- Snippets contain at most
--snippet-lengthUnicode characters (default 240), including ellipses. Even a match longer than the limit is truncated; offsets still describe the full match. - Sessions sort by
modified_atdescending, then path ascending for ties. Occurrences within a session follow source order. This is not relevance order or individual-message timestamp order. --max-matchescaps occurrences across all sessions and hosts (default 100;0means unlimited).-nstill limits session files scanned, not results. The cap does not guarantee fewer files scanned; the existing session pipeline first finds candidates, then search enumerates their occurrences.-a,-d,--agent,--project,--since,--until,--running,--no-archived, and--subagentsretain their existing filtering semantics.--remote/-Arun search on the remote host, which also needs this version ofah. Remote failures are errors, not silently incomplete results.- Supply either a positional pattern or
-q, not both. Empty queries and invalid regexes are errors; no matches is success with empty output. --raw-searchremains available throughlog, notsearch.
ah show <session-id-or-path> --at <position-from-search> -C 2
ah search 'OAuth' -ishow --at displays the selected source record and, by default, two searchable
records on either side. -C 0 displays only the selected record. A record is a
message or tool event; it may contain multiple text/argument fragments. Context
is not counted in lines and is not restricted by the search kind filter. Tool
inputs and outputs are displayed even though ordinary show omits them. The
selected fragment is marked >; its exact occurrence is highlighted when color
is enabled. Zero-width occurrences select the fragment without coloring a
character. JSON output with --at has record, fragment, kind, text,
selected, match_start, and match_end (offsets are null on context fragments).
Ordinary show and its existing JSON schema are unchanged.
search -i uses the existing selector setting (-s, $AH_SELECTOR, or fzf).
The fzf/sk preview opens the same position with context; Enter displays it and
Esc cancels. --no-preview disables the preview. Structured result formats
(--json, --tsv) cannot be combined with -i. Remotes execute both search and
position display on the host that owns the data; both hosts need this version.
Search output migration: kind and position are new JSON fields and are
appended as TSV columns 9 and 10; existing columns remain in positions 1–8. text_index
now counts nonempty fragments in the unfiltered stream, including with -p.
Consumers requiring the previous eight-column schema should select those
columns explicitly. -p now searches all user text parts, not just the legacy
transcript reader's first/combined prompt representation.
Compatibility: search used to be a hidden alias for log. For the old
session-list output and its field-selection options, use ah log explicitly.
Show a session transcript:
$ ah show a1b2c3d4
>>> implement OAuth2 authentication flow
I'll implement the OAuth2 flow. Let me start by reading the existing auth module...Sessions grouped by project:
$ ah project -a
PROJECT SESSION_COUNT LAST_MODIFIED_AT AGENTS
my-webapp 18 2026-03-23 18:00 claude, codex, cursor, gemini
api-server 14 2026-03-23 09:15 claude, codex, copilot, cursor
ml-pipeline 11 2026-03-22 08:50 claude, copilot, gemini
infra 5 2026-03-20 17:40 codex, cursor
docs 3 2026-03-19 11:25 claude, geminiList agent memory and instruction files across all agents:
$ ah memory -a
AGENT PROJECT TYPE NAME MODIFIED_AT DESCRIPTION
claude my-webapp feedback always-run-tests 2026-03-23 18:00 Run test suite before committing
claude my-webapp instruction CLAUDE.md 2026-03-22 10:00
shared my-webapp instruction AGENTS.md 2026-03-21 15:30A project-level AGENTS.md is read by several agents, so it is listed as shared and matches any --agent filter.
Files listed per agent (global paths honor each agent's env var; project paths are looked up in the current directory and, inside a git repository, every directory up to its root; -a does this for every known project):
| Agent | Global | Project |
|---|---|---|
| Claude | ~/.claude/CLAUDE.md, rules/**/*.md, agent-memory/*/*.md, auto memory projects/*/memory/*.md |
CLAUDE.md, CLAUDE.local.md, .claude/CLAUDE.md, .claude/rules/**/*.md, .claude/agent-memory{,-local}/*/*.md |
| Codex | ~/.codex/AGENTS.md, AGENTS.override.md, memories/**/*.md |
AGENTS.override.md |
| Gemini | ~/.gemini/GEMINI.md (or context.fileName in settings.json) |
same file names |
| Copilot | ~/.copilot/copilot-instructions.md |
.github/copilot-instructions.md, .github/instructions/**/*.instructions.md |
| Cursor | ~/.cursor/rules/**/*.mdc |
.cursorrules, .cursor/rules/**/*.mdc |
| Antigravity (agy) | ~/.gemini/config/rules/*.md |
.agents/rules/*.md, .agent/rules/*.md |
| Grok | ~/.grok/AGENTS.md, rules/*.md, memory/MEMORY.md, memory topics memory-v2/{global,workspaces/*}/topics/*.md |
.grok/rules/*.md |
| opencode | ~/.config/opencode/AGENTS.md, instructions in opencode.json(c) |
instructions in opencode.json(c) |
| shared | — | AGENTS.md |
Types: instruction (always-loaded files), rule, memory (or the type in a memory file's frontmatter, such as feedback), and skill. Skills (SKILL.md under skills/*/ of Claude, Codex, and agy, and .agents/skills/*/) are listed only with -t skill.
Show session summary per agent:
$ ah agent
AGENT SESSIONS LATEST
claude 50 2026-03-24 17:55
codex 42 2026-03-24 16:32
copilot 18 2026-03-23 19:00
cursor 12 2026-03-22 13:40
gemini 5 2026-03-21 10:50| Agent | List | Search | Show | Resume | Running | Memory |
|---|---|---|---|---|---|---|
| Claude | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Codex | ✓ | ✓ | ✓ | ✓ | ✓¹ | ✓ |
| Gemini | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Copilot | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Cursor | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Antigravity (agy) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Grok | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| opencode | ✓ | ✓ | ✓ | ✓ | ✓ |
Running detection reads each agent's own bookkeeping: Claude's sessions/<pid>.json (checking procStart so a reused PID is not reported), Grok's active_sessions.json, Copilot's session-state/<id>/inuse.<pid>.lock, and Codex's thread-writer-locks/<id>.lock. ¹ Codex is detected on Linux only, from the kernel lock table (/proc/locks); its PID is the lock holder, which for the interactive TUI is the Codex app-server. Running detection needs a PID liveness check, which is not implemented on Windows.
- Cross-agent — one tool for 8 agents (see
ah list-agents) - Zero-config — scans the standard session locations for each supported CLI
- Fast — parallel file collection with rayon, regex search via memmap2, no subprocesses for search/parsing
- Resume-friendly —
ah resumeandah showcan target the latest matching session without pasting IDs - Structured output —
git log-style multi-line format with auto-pager on TTY, plain TSV when piped, plus--table,--json,--ltsv - Interactive —
-iadds fuzzy selection with transcript preview (via fzf or compatible finder)
brew install nihen/tap/ahSupported in the tap: macOS (Apple Silicon and Intel) and Linux (x86_64 and arm64).
cargo install ah-cliDownload a prebuilt binary from GitHub Releases.
Available for macOS (arm64, x86_64) and Linux (x86_64, arm64). The Linux binaries are statically linked (musl).
cargo install --git https://github.com/nihen/ah# zsh
mkdir -p ~/.zfunc && ah completion zsh > ~/.zfunc/_ah
# Add to .zshrc: fpath=(~/.zfunc $fpath); autoload -Uz compinit && compinit
# bash
ah completion bash > ~/.local/share/bash-completion/completions/ah
# fish
ah completion fish > ~/.config/fish/completions/ah.fishMost commands support -i for fuzzy selection with transcript preview. Requires fzf or a compatible finder (e.g. sk) in PATH. Override with $AH_SELECTOR.
fzf compatibility:
- Selection and transcript preview work with older fzf too, including 0.44 from Debian/Ubuntu apt.
- Preview search (the query is highlighted in the preview and the preview scrolls to the first match;
ctrl-sswitches list filtering on and off) needs fzf 0.62 or newer. On older fzf it is turned off automatically. fzf 0.63+ calculates the scroll position in the background so typing stays responsive.
Useful as a shell function — pick a project, browse its sessions, resume:
ahr() { local d; d="$(ah project -i)" && ah resume -i -d "$d"; }Search, inspect, and resume coding-agent sessions from one CLI
(read-only except resume)
Defaults to the current directory. Use -a to search across all known sessions.
Usage:
ah <COMMAND> [OPTIONS]
Commands:
log List sessions
search Show matching passages
project List known projects
show Show session transcript
resume Resume an agent session
memory List agent memory and instruction files
agent Show session summary per agent
Help / setup:
list-agents List supported agents
completion Generate shell completion script
man Generate man page
Global options:
-a, --all Show all sessions (disable default cwd filtering)
-A Show all sessions including all configured remotes
--agent <NAME> Filter by agent name (e.g. claude, codex, gemini)
--project <NAME> Filter by project name
-d, --dir <PATH> Filter by working directory (default: current directory)
-q, --query <REGEX> Search messages and tool input/output (regex, case-insensitive)
-p, --prompt-only Search only user prompts (use with -q)
--raw-search Search raw session files incl. metadata (use with -q)
-n, --limit N Max session files to scan (default: 0, no limit)
-i, --interactive Interactive mode via fuzzy finder (fzf/sk)
-s <CMD> Override fuzzy selector (default: $AH_SELECTOR or fzf)
--no-preview Disable preview in interactive mode
--interactive-display <FIELDS> Override fuzzy selector display columns (log -i / show -i only)
--running Show only currently running sessions (Claude, Codex, Copilot, Grok)
--no-archived Hide sessions the agent has archived (Codex)
--subagents Include subagent sessions (spawned by another session)
--remote <NAME> Include sessions from remote host (requires ah on remote; see ~/.ahrc [remotes.*])
--since <SPEC> Show sessions newer than (e.g. "2026-03-20", "3d", "1w", "2m" = ~60 days)
--until <SPEC> Show sessions older than (e.g. "2026-03-20", "3d", "1w", "2m" = ~60 days)
--color Force colored output (even through pipes)
--no-color Disable colored output
--no-pager Disable automatic pager
-h, --help Show this help
-V, --version Show version
Examples:
ah log # latest sessions for the current directory
ah log -a -q "auth" # search across all known sessions
ah log -A # all sessions including all remotes
ah resume # resume the latest matching session
ah show -q "OAuth" # show the latest matching session
ah resume -i # browse sessions with fzf/sk and resume
Run `ah <COMMAND> --help` for subcommand-specific options.
Configuration:
~/.ahrc (TOML) — optional config file for agent customization and remote hosts.
See https://github.com/nihen/ah#configuration-ahrc for details.
List sessions
Usage:
ah log [OPTIONS]
Options:
-o, --fields <FIELDS> Select output fields (replaces defaults, see --list-fields)
Default: agent, project, modified_at, title, id
With -q: agent, project, modified_at, title, matched, id
-O, --extra-fields <FIELDS> Add fields to defaults (comma-separated)
--table Aligned table with header row
--tsv Tab-separated values (no header, no color)
--ltsv Labeled Tab-Separated Values (in -i mode: selector display format)
--json JSON Lines output
-S, --sort <FIELD> Sort by field (default: modified_at)
--asc Sort ascending
--desc Sort descending (default)
--transcript-limit N Max characters for transcript field (default: 500)
--title-limit N Max characters for auto-generated title (default: 50, 0 = no limit)
-L, --list-fields List available output fields and exit (use with --json for machine-readable output)
Default output (when no format flag is given):
git-log style multi-line with auto-pager on TTY, plain TSV when piped
Interactive mode:
-i, --interactive Browse sessions via fuzzy finder; prints selected path
With -o: prints selected fields as TSV instead of path
--interactive-display <FIELDS> Override display columns in fuzzy finder
-s <CMD> Selector command (default: $AH_SELECTOR or fzf)
--no-preview Disable transcript preview (enabled by default for fzf, sk)
Global options are also available (see ah -h).
Show matching passages from conversations and tool input/output
Usage:
ah search [OPTIONS] <PATTERN>
ah search [OPTIONS] -q <REGEX>
Options:
--json One JSON object per occurrence (JSON Lines)
--tsv TSV without a header (default when piped)
--kind <KINDS> Comma-separated: user,assistant,tool-input,tool-output,unknown
-i, --interactive Select an occurrence, preview context, then show it
-v, --verbose Show full log paths and match positions on TTY
--max-matches N Maximum occurrences across sessions/hosts (default: 100, 0 = unlimited)
--snippet-length N Maximum Unicode characters per snippet (default: 240, minimum: 1)
One result per non-overlapping regex occurrence, not per session.
Sessions are ordered by modified_at descending; occurrences are in source order.
Default: session headings and compact passages with auto-pager on TTY;
plain TSV when piped. Paths and positions are hidden on TTY unless --verbose.
Verbose positions use "text #N" for search fragments, not transcript line numbers.
--verbose does not change JSON or TSV output.
TSV columns: path, agent, project, id, text_index, match_start, match_end, snippet, kind, position.
Text indices count nonempty source fragments before kind filtering (not transcript messages).
Use position with `ah show SESSION --at POSITION -C 2` to open the source.
Match offsets are 0-based UTF-8 byte offsets within the decoded search fragment.
Empty search fragments are skipped. No matches is successful with empty output.
Use PATTERN or -q, not both. Empty queries are rejected.
-p is shorthand for --kind user (all user text parts, excluding tool results).
-i uses fzf (or -s / $AH_SELECTOR); --no-preview disables the context preview.
-i cannot be combined with --json or --tsv. --raw-search is not supported;
use `ah log -q ... --raw-search` instead.
The former `search` alias for `log` is now this command; use `log` for session lists.
Examples:
ah search 'OAuth' # matching passages in the current directory
ah search 'OAuth' -a --json # occurrences across all directories
ah search -p '認証' # user prompts only
Global options:
-a, --all Show all sessions (disable default cwd filtering)
-A Show all sessions including all configured remotes
--agent <NAME> Filter by agent name (e.g. claude, codex, gemini)
--project <NAME> Filter by project name
-d, --dir <PATH> Filter by working directory (default: current directory)
-q, --query <REGEX> Search messages and tool input/output (regex, case-insensitive)
-p, --prompt-only Search only user prompts (use with -q)
--raw-search Search raw session files incl. metadata (use with -q)
-n, --limit N Max session files to scan (default: 0, no limit)
--since <SPEC> Show sessions newer than (e.g. "2026-03-20", "3d", "1w", "2m" = ~60 days)
--until <SPEC> Show sessions older than (e.g. "2026-03-20", "3d", "1w", "2m" = ~60 days)
--running Show only currently running sessions (Claude, Codex, Copilot, Grok)
--no-archived Hide sessions the agent has archived (Codex)
--subagents Include subagent sessions (spawned by another session)
--remote <NAME> Include sessions from remote host (requires ah on remote; see ~/.ahrc [remotes.*])
--color Force colored output (even through pipes)
--no-color Disable colored output
--no-pager Disable automatic pager
--debug Show debug info (glob expansion, scan counts, timing) on stderr
Show session transcript
Usage:
ah show [OPTIONS] [SESSION]
If SESSION is omitted, ah reads it from piped stdin (first line); if stdin is
a terminal or empty, ah shows the latest session matching -q and other filters.
Use - as SESSION to read it from stdin explicitly. An empty SESSION is an error.
Transcript output:
--head N Show first N messages only
--at <POSITION> Open a search position, including tool input/output
-C, --context N Surrounding source records with --at (default: 2, max: 1000)
--pretty Pretty-print with colors (default)
--raw Output raw session file content
--json Output normalized JSON Lines ({"role":"user","text":"..."})
--md Output as Markdown (## User / ## Assistant headers)
-f, --follow Follow session output in real-time (like tail -f)
--highlight <PATTERN> Highlight matching text in pretty output (case-insensitive; requires color)
With --at, context counts nonempty searchable source records (a message or tool
event), not lines. Positions remain stable across kind filters and appends;
changed source prefixes require a new search. JSON emits record, fragment, kind,
text, selected, match_start, and match_end. --at conflicts with --head, --follow,
--raw, metadata output, and --highlight. Ordinary show output is unchanged.
Metadata output:
-o, --fields <FIELDS> Output session metadata as TSV instead of transcript
--tsv Metadata mode without -o (default field: title)
Interactive mode:
-i, --interactive Select session via fuzzy finder then show it
--interactive-display <FIELDS> Override display columns in fuzzy finder
-s <CMD> Selector command (default: $AH_SELECTOR or fzf)
--no-preview Disable transcript preview
ctrl-s (fzf only) Toggle preview search: highlight + scroll to match / reset
Examples:
ah show # show latest session transcript
ah show -o title # output title of latest session
ah show -o agent,title # output agent and title as TSV
ah show -i -o title # select session, output title
Global options:
-a, --all Show all sessions (disable default cwd filtering)
-A Show all sessions including all configured remotes
--agent <NAME> Filter by agent name (e.g. claude, codex, gemini)
--project <NAME> Filter by project name
-d, --dir <PATH> Filter by working directory (default: current directory)
-q, --query <REGEX> Search messages and tool input/output (regex, case-insensitive)
-p, --prompt-only Search only user prompts (use with -q)
--raw-search Search raw session files incl. metadata (use with -q)
-n, --limit N Max session files to scan (default: 0, no limit)
--since <SPEC> Show sessions newer than (e.g. "2026-03-20", "3d", "1w", "2m" = ~60 days)
--until <SPEC> Show sessions older than (e.g. "2026-03-20", "3d", "1w", "2m" = ~60 days)
--running Show only currently running sessions (Claude, Codex, Copilot, Grok)
--no-archived Hide sessions the agent has archived (Codex)
--subagents Include subagent sessions (spawned by another session)
--remote <NAME> Include sessions from remote host (requires ah on remote; see ~/.ahrc [remotes.*])
--color Force colored output (even through pipes)
--no-color Disable colored output
--no-pager Disable automatic pager
--debug Show debug info (glob expansion, scan counts, timing) on stderr
Resume an agent session
Usage:
ah resume [OPTIONS] [SESSION] [-- EXTRA_ARGS...]
If SESSION is omitted, ah reads it from piped stdin (first line); if stdin is
a terminal or empty, ah resumes the latest session matching -q and other filters.
Use - as SESSION to read it from stdin explicitly. An empty SESSION is an error.
Arguments after -- are passed directly to the agent command.
The only command that launches an agent process; other commands are read-only.
Options:
--print Print the resolved resume command and exit (read-only; does not execute)
Interactive mode:
-i, --interactive Select session via fuzzy finder then resume it
-o, --fields <FIELDS> Display fields in interactive mode (default: agent,project,modified_at,title)
-s <CMD> Selector command (default: $AH_SELECTOR or fzf)
--ltsv Use LTSV format for interactive selector display
--no-preview Disable transcript preview
Examples:
ah resume # resume latest matching session
ah resume --print # print the resolved resume command
ah resume a1b2c3d4 # resume by ID
ah resume -i # interactive selection
ah resume -- --dry-run # pass extra args to agent
Global options are also available (see ah -h).
List known projects
Usage:
ah project [OPTIONS]
Options:
-o, --fields <FIELDS> Select output fields (replaces defaults, see --list-fields)
Default: project, session_count, last_modified_at, agents
In -i mode default: cwd, project, session_count, last_modified_at
-O, --extra-fields <FIELDS> Add fields to defaults (comma-separated)
--table Aligned table with header row
--tsv Tab-separated values (no header, no color)
--ltsv Labeled Tab-Separated Values (in -i mode: selector display format)
--json JSON Lines output
-S, --sort <FIELD> Sort by field (default: last_modified_at)
--asc Sort ascending
--desc Sort descending (default)
-L, --list-fields List available output fields and exit (use with --json for machine-readable output)
Default output (when no format flag is given):
Aligned table with auto-pager on TTY, plain TSV when piped
Interactive mode:
-i, --interactive Browse projects via fuzzy finder; prints selected cwd
-s <CMD> Selector command (default: $AH_SELECTOR or fzf)
--no-preview Disable preview
Global options are also available (see ah -h).
List agent memory files
Usage:
ah memory [OPTIONS]
Options:
-o, --fields <FIELDS> Select output fields (replaces defaults, see --list-fields)
Default: agent, project, type, name, modified_at, description
-O, --extra-fields <FIELDS> Add fields to defaults (comma-separated)
-t, --type <TYPE> Filter by memory type (instruction/rule/memory/skill, or a memory's own type such as feedback)
--table Aligned table with header row
--tsv Tab-separated values (no header, no color)
--ltsv Labeled Tab-Separated Values
--json JSON Lines output
-S, --sort <FIELD> Sort by field (default: modified_at)
--asc Sort ascending
--desc Sort descending (default)
-L, --list-fields List available output fields and exit (use with --json for machine-readable output)
Default output (when no format flag is given):
Aligned table with auto-pager on TTY, plain TSV when piped
A project-level AGENTS.md is listed as agent `shared` and matches any --agent filter.
Skills (SKILL.md) are listed only with -t skill.
Interactive mode:
-i, --interactive Browse memory files via fuzzy finder
-s <CMD> Selector command (default: $AH_SELECTOR or fzf)
--no-preview Disable preview
Global options are also available (see ah -h).
Show session summary per agent
Usage:
ah agent [OPTIONS]
Shows how many sessions were found for each agent and the latest modified time.
Options:
--table Output as aligned table
--tsv Output as TSV (tab-separated values)
--ltsv Output as LTSV (Labeled TSV)
--json Output as JSON Lines
Default output (when no format flag is given):
Aligned table with auto-pager on TTY, plain TSV when piped
Global options are also available (see ah -h).
ah works out of the box with no configuration. Optionally, create ~/.ahrc (TOML) to customize agent settings and remote hosts.
~/.ahrc has two top-level sections: [agents.*] for agent configuration and [remotes.*] for SSH remote hosts.
# ~/.ahrc — ah configuration file (TOML)
# --- Agent configuration ---
# Disable a built-in agent
[agents.codex]
disabled = true
# Add extra session file locations to a built-in agent
[agents.claude]
extra_patterns = ["~/claude-archive/projects/*/*.jsonl"]
# Define a custom agent using an existing plugin's parser
[agents.mybot]
plugin = "claude"
file_patterns = ["~/.mybot/sessions/*.jsonl"]
# --- Remote hosts for SSH session aggregation ---
[remotes.mydev]
host = "mydev" # SSH host name (as in ~/.ssh/config)
ah_path = "/usr/local/bin/ah" # path to ah binary on remote (optional, default: "ah")| Field | Required | Description |
|---|---|---|
disabled |
No | Set to true to hide this agent from all commands |
extra_patterns |
No | Additional glob patterns to scan (built-in agents only) |
plugin |
Yes* | Parser to use: claude, codex, gemini, copilot, cursor, agy, grok, opencode (*required for custom agents) |
file_patterns |
Yes* | Glob patterns for session files (*required for custom agents) |
All glob patterns must start with ~/ or / (absolute paths only). ~ is expanded to the home directory.
[agents.codex]
disabled = true[agents.claude]
extra_patterns = ["~/claude-archive/projects/*/*.jsonl"]Sessions found through extra_patterns are attributed to the agent by the pattern's literal part (before the first glob character), so keep each agent's extra files in a dedicated directory or under a distinct name prefix. If the literal part cannot be told apart from your home directory or another agent's default directory (e.g. ~/*.jsonl, ~/.c*.db, ~/backup-*/x.db), ah warns and uses only the matches that fall inside the agent's own locations (e.g. ~/*/.claude/projects/*/*.jsonl still maps to Claude via its default .claude directory; with CLAUDE_CONFIG_DIR set, only paths under that directory do); other matches are skipped.
[agents.mybot]
plugin = "claude"
file_patterns = ["~/.mybot/sessions/*.jsonl"]The plugin field tells ah how to parse the session files. Available plugins: claude, codex, gemini, copilot, cursor, agy, grok, opencode.
Aggregate sessions from remote machines over SSH. The remote host must have ah installed.
[remotes.mydev]
host = "mydev" # SSH host (must be reachable via `ssh <host>`)
ah_path = "/usr/local/bin/ah" # optional, default: "ah"
[remotes.prod-bastion]
host = "bastion.example.com"| Field | Required | Description |
|---|---|---|
host |
Yes | SSH host name (as configured in ~/.ssh/config or a hostname) |
ah_path |
No | Absolute path to ah on the remote host or a bare command name (default: "ah"). ~/bin/ah and other ~/... paths are not supported |
Use --remote <name> to include a specific remote, or -A to include all configured remotes:
ah log --remote mydev # include sessions from mydev
ah log -A # include all configured remotes
ah log -A -q "deploy" # search across local + all remotesEach built-in agent respects the environment variable its CLI uses to relocate session storage:
| Agent | Session Files | Env Var | Default |
|---|---|---|---|
| Claude | projects/*/*.jsonl |
CLAUDE_CONFIG_DIR |
~/.claude |
| Codex | sessions/**/*.jsonl |
CODEX_HOME |
~/.codex |
| Gemini | tmp/*/chats/session-*.jsonl (.json before v0.39) |
GEMINI_CLI_HOME |
~/.gemini |
| Copilot | session-state/*/workspace.yaml |
COPILOT_HOME |
~/.copilot |
| Cursor | projects/*/agent-transcripts/**/*.jsonl |
CURSOR_DATA_DIR |
~/.cursor |
| Antigravity (agy) | antigravity-cli/brain/*/.system_generated/logs/transcript.jsonl |
— | ~/.gemini |
| Grok | sessions/*/*/chat_history.jsonl |
GROK_HOME |
~/.grok |
| opencode | opencode/opencode*.db (SQLite) |
XDG_DATA_HOME |
~/.local/share |
opencode stores all sessions in one SQLite database. ah reads it read-only and lists each session under the virtual path <db>/<session-id>, which works with ah show, ah resume, and -o path like a regular session file. ah show --raw prints one JSON line per message with its parts.
Codex sessions archived with codex archive stay listed and resumable (codex resume still finds them). They carry archived=true (-o archived); hide them with --no-archived.
Subagent sessions (started by another session, e.g. Claude's Task tool) are hidden from log, project, and agent unless --subagents is given; -o parent_id shows the session that spawned them. A subagent's id or path still works with ah show directly. Claude, Cursor, and Gemini subagent transcripts cannot be resumed on their own, so they have no resume command.
| Agent | Subagent sessions | parent_id |
|---|---|---|
| Claude | projects/*/<parent>/subagents/agent-<id>.jsonl (id is the agent id) |
✓ |
| Codex | sessions whose session_meta source is a subagent |
✓ (spawned threads) |
| Gemini | tmp/*/chats/<parent>/<id>.json(l) |
✓ |
| Cursor | projects/*/agent-transcripts/<parent>/subagents/*.jsonl |
✓ |
| Grok | summary.json with session_kind: subagent |
not recorded |
| opencode | child sessions (parent_id column) |
✓ |
Run ah list-agents to see the full configuration including glob patterns and capabilities.
Additional environment variables:
| Env Var | Description |
|---|---|
AH_PAGER |
Override pager command (default: less). Set to empty string to disable |
PAGER |
Fallback pager command (used if AH_PAGER is not set) |
AH_COLOR |
Set to 1 to force colored output (like --color) |
NO_COLOR |
Set to disable colored output (no-color.org) |
SQL with trdsql
ah log -a --ltsv | trdsql -iltsv "SELECT * FROM - WHERE agent='claude'"
ah log -a --ltsv | trdsql -iltsv "SELECT agent, COUNT(*) as cnt FROM - GROUP BY agent"JSON with jq
ah log -a --json | jq '.project'
ah log -a --json -n 1 | jq '.'
ah project --json | jq '.project' # list project namesah log -q "auth" -o path | head -1 | ah show # show latest match
ah log -q "auth" -o path | head -1 | ah resume # resume latest match
ah log -a -o project | sort | uniq -c | sort -rn # project rankingAdd this line to your project or global instructions so your coding agent knows about ah:
`ah` — cross-agent session history CLI. Run `ah -h` for usage; key commands: `ah log` (list sessions), `ah show` (view transcript), `ah log -a -q "keyword"` (search all).