session-search · diff
v1.1.0 to v1.1.0
3 added, 5 removed. Audit A to A.
---
name: session-search
version: 1.1.0
description: >-
- Use this skill to find, locate, or search previous coding agent sessions or
- conversations. Triggers on requests to search session transcripts or
- conversation history, recover commands or outputs from earlier sessions,
- compare recent sessions for a repository, or search across Claude Code,
- Codex CLI, Gemini CLI, Goose, Amp, or Buzz relay session history.
+ Search previous agent sessions and conversations (Claude Code, Codex, Gemini,
+ Goose, Amp, Buzz). Use to find session transcripts, recover prior outputs, or
+ compare recent sessions for a repository.
allowed-tools: Agent, Bash, Glob, Grep, Read
model: sonnet
---
## Context
- Current directory: !`pwd`
- Git repo root: !`git rev-parse --show-toplevel 2>/dev/null || echo "NOT_IN_GIT"`
- Repo name: !`basename $(git rev-parse --show-toplevel 2>/dev/null) 2>/dev/null || echo "UNKNOWN"`
# Session Search
Searches session transcripts across all detected coding agents: Claude Code, Codex CLI, Gemini CLI, Goose, Amp, and Buzz (Nostr relay chat). Results are ranked by current repo match, then by recency.
## Quick Start
Resolve `<skill-dir>` as the directory containing this SKILL.md file.
```bash
# Find sessions by title, ID fragment, or cwd (metadata only — use grep for content)
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search find "authentication"
# Search transcript content for a regex pattern
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search grep "authentication refactor" --limit-sessions 20
# List recent sessions for the current repo
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search list --limit 10
```
## Context Hygiene
For broad or exploratory searches, delegate to a subagent and return only IDs, titles, timestamps, cwd values, paths, and short snippets. Never dump raw transcripts into the main context window — a single session file can be hundreds of kilobytes.
When returning results to the user, summarize what was found and offer to retrieve specific sessions on request.
## Find Sessions
```bash
# Look up a session by ID fragment
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search find "3f8a"
# Find by title/cwd keyword across all repos
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search find "database migration" --all-repos
# List sessions for a specific repo
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search list --repo my-service
# Restrict to one agent
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search find "webhook handler" --agent claude
# Sessions since a date
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search list --since 2026-04-01
```
## Grep Sessions
```bash
# Regex search across recent sessions (default: current repo)
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search grep "TODO|FIXME" --limit-sessions 25
# Search within a specific session by ID fragment
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search grep "import requests" --id 3f8a
# Case-insensitive search, wider output, capped matches
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search grep "config" -i --max-matches 20 --width 200
# Broader search across all repos
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search grep "pg_dump" --all-repos --limit-sessions 50
```
`--limit-sessions` controls how many session files are scanned. `--max-matches` controls output volume. Prefer lower values for exploratory searches; increase when a specific pattern is known to be rare.
## Scoped Search
If `rg` is needed for low-level transcript inspection, first use `find` or `list` to get candidate session file paths, then scope `rg` to those specific files. Never run an unscoped recursive grep from `~` or `/` — session stores can contain gigabytes of transcript data.
```bash
# Step 1: get candidate paths
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search find "auth flow" --json | jq -r '.[].path'
# Step 2: grep only those files
rg "Bearer token" /path/to/session1.jsonl /path/to/session2.jsonl
```
## Common Flags
| Flag | Purpose |
|------|---------|
| `--agent {claude,codex,gemini,goose,amp,buzz}` | Restrict to one agent |
| `--all-repos` | Search beyond current repo |
| `--since YYYY-MM-DD` | Lower bound on session date |
| `--until YYYY-MM-DD` | Upper bound on session date |
| `--oldest` | Reverse sort (oldest first) |
| `--limit N` | Max sessions returned |
| `--json` | Machine-readable JSON output |
| `--cwd DIR` | Treat DIR as the working directory for ranking |
| `--repo NAME` | Filter by repo name |
## Ranking
Sessions are ranked in this order:
1. Exact current `cwd` match
2. Same git repository root
3. Same repository name
4. Recency (newest first by default)
Use `--all-repos` to include sessions from unrelated repositories.
## Agent Storage Notes
| Agent | Storage location |
|-------|----------------|
| Claude Code | `~/.claude/projects/<encoded-cwd>/<uuid>.jsonl` |
| Codex CLI | `~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<id>.jsonl` |
| Gemini CLI | `~/.gemini/tmp/<project-slug>/chats/session-*.jsonl` |
| Goose | `~/.local/share/goose/sessions/sessions.db` (SQLite) |
| Amp | `~/.local/share/amp/threads/T-<uuid>.json` |
| Buzz | Nostr relay via the `buzz` CLI (one channel = one session) |
## Buzz (Relay Backend)
Buzz history lives on a Nostr relay, not on disk, so its reader behaves differently from the local-file backends:
- **Detection** gates on the `BUZZ_PRIVATE_KEY` and `BUZZ_RELAY_URL` environment variables, not a directory. An unreachable relay yields a warning and zero Buzz results — not an error and not a crash.
- **One channel = one session.** The channel UUID is the session ID and the channel name is the title.
- **Recency-base ranking.** Buzz channels have no working directory, so every Buzz session scores `repo_score=0`; `list` and `find` order purely by recency. For a complete `grep`, candidate channels are reranked by match density before the `--limit-sessions` cut (see below). Buzz results are inherently `--all-repos`.
- **Grep is global-search-first.** A selective pattern resolves in a single relay round-trip via `buzz messages search`. The relay caps that search at 100 results; when a pattern is broad enough to saturate the cap (or has no literal substring to pre-filter on, e.g. `\d{4}`), the reader falls back to a bounded per-channel sweep over the top `--limit-sessions` channels by recency and prints a one-line stderr notice. The result is either complete or explicitly bounded and announced — never a silent partial. For a complete grep (the search did not saturate), candidate channels are reranked by match density — channels with the most matching messages are searched and printed first, even when they are older than noisier recent channels — so the most relevant thread surfaces at the top instead of being buried by recency. This reranking operates *within* the `--limit-sessions` window; it does not raise the window, so a match below the densest `--limit-sessions` channels can still be cut. When the search saturates, ranking is skipped and the bounded per-channel sweep is unchanged; `--id`-scoped greps are never reranked.
```bash
# Restrict to Buzz history
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search grep "deployment" --agent buzz
# Scope to a single channel by UUID fragment
PYTHONPATH=<skill-dir>/scripts uv run python -m session_search grep "rollback" --agent buzz --id 2a5c4f66
```