{"id":51192412,"url":"https://github.com/janole/session-bandit","last_synced_at":"2026-06-27T16:31:31.613Z","repository":{"id":366684924,"uuid":"1274147818","full_name":"janole/session-bandit","owner":"janole","description":"Offline CLI and agent skill to search, browse, and summarize local Claude Code and Codex session transcripts.","archived":false,"fork":false,"pushed_at":"2026-06-22T21:38:49.000Z","size":258,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T23:19:11.347Z","etag":null,"topics":["agent-skills","claude-code","cli","codex","coding-agents","developer-tools","npm-package","session-transcripts","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/janole.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-19T08:15:07.000Z","updated_at":"2026-06-22T21:38:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/janole/session-bandit","commit_stats":null,"previous_names":["janole/session-bandit"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/janole/session-bandit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janole%2Fsession-bandit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janole%2Fsession-bandit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janole%2Fsession-bandit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janole%2Fsession-bandit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janole","download_url":"https://codeload.github.com/janole/session-bandit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janole%2Fsession-bandit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34860892,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-skills","claude-code","cli","codex","coding-agents","developer-tools","npm-package","session-transcripts","typescript"],"created_at":"2026-06-27T16:31:09.996Z","updated_at":"2026-06-27T16:31:29.763Z","avatar_url":"https://github.com/janole.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Session Bandit\n\nSearch, browse, and extract information from the local session transcripts\nwritten by your coding agents — Claude Code and Codex.\n\nEvery major coding agent writes its full session history to disk as JSONL.\nSession Bandit indexes those files locally — no API calls, no auth, no network.\nJust point it at your session directories and search across everything you've\never done with every agent.\n\n## Features\n\n- **Unified listing** across Claude Code and Codex sessions, sorted by most\n  recent first, with filters by agent, project, and time period.\n- **Full transcripts** — read any session's normalized transcript with tool\n  calls, inputs, outputs, and status indicators.\n- **Full-text search** across all session messages, with agent, project, and\n  time-period filters.\n- **Agent recaps \u0026 compactions captured** — Claude's while-you-were-away recaps\n  and Codex's context-window compactions are no longer silently dropped; they're\n  carried as `summary` messages (with a `recap` / `compaction` subtype) and fed\n  to the digest so the synthesizing LLM can use them.\n- **Parsing health check** — `doctor` command validates that Session Bandit's\n  parsing assumptions match your real session files (format drift, injection\n  markers, unrecognized types, silent skips).\n- **Works as a library too** — `@session-bandit/core` exposes a programmatic\n  API for indexing and querying sessions from your own code.\n\n## Install\n\n### As a global CLI (npm)\n\n```sh\nnpm install -g session-bandit\n```\n\nRequires Node.js 22+.\n\n### From source (for development or pre-npm)\n\n```sh\ngit clone https://github.com/janole/session-bandit.git\ncd session-bandit\npnpm install\npnpm -r build\nnpm install -g packages/cli\n```\n\nRequires Node.js 22+ and pnpm 10+. The `npm install -g packages/cli` step\ninstalls the CLI globally from the built output (core is bundled into the\nCLI, so no separate install needed).\n\n### Agent skill\n\nSession Bandit ships an agent skill in the `skill/` directory. The skill\nteaches Claude Code, Codex, and other `npx skills`-compatible agents how to use\nSession Bandit to write handoff notes and memory notes from past sessions.\n\nInstall it globally for Claude Code:\n\n```sh\nnpx skills add janole/session-bandit --skill session-bandit -g -a claude-code -y\n```\n\nInstall it globally for Codex:\n\n```sh\nnpx skills add janole/session-bandit --skill session-bandit -g -a codex -y\n```\n\nYou can also install directly from the skill path:\n\n```sh\nnpx skills add https://github.com/janole/session-bandit/tree/main/skill -g -a claude-code -y\n```\n\nOr manually copy the `skill/` directory to the relevant agent skill directory,\nfor example `~/.claude/skills/session-bandit/` for Claude Code or\n`~/.codex/skills/session-bandit/` for Codex.\n\nThe skill's `SKILL.md` includes instructions for the agent to install the CLI\nvia `npm install -g session-bandit` if it's not already available.\n\n## CLI usage\n\n```sh\n# List all sessions (JSON lines, most recent first)\nsession-bandit list\n\n# List with a human-readable table\nsession-bandit list --pretty\n\n# Filter by agent\nsession-bandit list --agent claude\nsession-bandit list --agent codex\n\n# Filter by project (substring match on project path / cwd)\nsession-bandit list --project botbandit\n\n# Show the full transcript of a session (accepts ID prefix)\nsession-bandit show 342647fa-5bf\n\n# Full-text search across all session messages\nsession-bandit search \"tool approval\" --pretty\n\n# Search within a specific agent\nsession-bandit search \"adapter\" --agent claude --pretty\n\n# Emit a structured digest of a session (substance, files, key turns,\n# recaps/compactions) for LLM ingestion — the payoff feature for\n# handoffs / memories\nsession-bandit extract 342647fa-5bf --pretty\n\n# Wrap the digest in a ready-to-send synthesis prompt\nsession-bandit extract 342647fa-5bf --prompt handoff\nsession-bandit extract 342647fa-5bf --prompt memory\n\n# Find the sessions where something actually happened (by substance score)\nsession-bandit list --sort importance --pretty\n\n# Drop the trivial / hello-only sessions\nsession-bandit list --min-importance moderate --pretty\n\n# Limit to the last week (relative: 7d, 24h, 2w, 3m)\nsession-bandit list --since 7d --pretty\n\n# Limit to a date window\nsession-bandit list --since 2026-06-01 --until 2026-06-15 --pretty\n\n# Search within a time period\nsession-bandit search \"adapter\" --since 3d --pretty\n```\n\n### Commands\n\n```\nsession-bandit list [--agent \u003cname\u003e] [--project \u003cpath\u003e] [--sort recent|importance] [--min-importance \u003ctier\u003e] [--since \u003cdate\u003e] [--until \u003cdate\u003e] [--pretty]\nsession-bandit show \u003csessionId\u003e [--agent \u003cname\u003e]\nsession-bandit search \u003cquery\u003e [--agent \u003cname\u003e] [--project \u003cpath\u003e] [--since \u003cdate\u003e] [--until \u003cdate\u003e] [--pretty]\nsession-bandit extract \u003csessionId\u003e [--agent \u003cname\u003e] [--prompt handoff|memory] [--full] [--pretty]\n```\n\n| Flag | Description |\n|---|---|\n| `-a, --agent \u003cname\u003e` | Filter by agent: `claude` or `codex` |\n| `-p, --project \u003cpath\u003e` | Filter by project (substring match on project/cwd) |\n| `--sort \u003cfield\u003e` | `list`: sort by `recent` (default) or `importance` (substance score) |\n| `--min-importance \u003ctier\u003e` | `list`: drop sessions below tier (`trivial`\\|`light`\\|`moderate`\\|`substantive`\\|`heavy`) |\n| `--since \u003cdate\u003e` | `list`/`search`: only entries at/after this time — absolute date (`2026-06-01`) or relative (`7d`, `24h`, `2w`, `3m`) |\n| `--until \u003cdate\u003e` | `list`/`search`: only entries at/before this time — absolute date or relative (`7d`, `24h`, `2w`, `3m`) |\n| `--prompt \u003ckind\u003e` | `extract`: wrap the digest in a synthesis prompt (`handoff`\\|`memory`) |\n| `--full` | `extract`: include the complete de-noised transcript |\n| `--pretty` | Print human-readable output instead of JSON lines |\n\n**Output defaults to JSON lines** (one object per line) for machine\nconsumption and piping. Use `--pretty` for terminal browsing.\n\n### Example output\n\n`list --pretty`:\n\n```\nagent   sessionId     startedAt            msgs  model              project\n--------------------------------------------------------------------------------\ncodex   019ee0ad-2eb  2026-06-19T16:18:26  64    gpt-5.5            /Users/ole/projects/chat-bandit\nclaude  342647fa-5bf  2026-06-19T10:38:38  153   claude-opus-4-8    /Users/ole/projects/chat-bandit\ncodex   019eda02-434  2026-06-18T09:14:02  65    gpt-5.5            /Users/ole/projects/chat-bandit\n...\n```\n\n`list` (JSON lines):\n\n```json\n{\"agent\":\"claude\",\"sessionId\":\"342647fa-5bf0-41b4-b21d-1e7d0d78b371\",\"project\":\"/Users/ole/projects/chat-bandit\",\"cwd\":\"/Users/ole/projects/chat-bandit\",\"startedAt\":\"2026-06-19T10:38:38.122Z\",\"endedAt\":\"2026-06-19T14:41:00.972Z\",\"model\":\"claude-opus-4-8\",\"messageCount\":153}\n```\n\n`show \u003csessionId\u003e`:\n\n```\nSession: 342647fa-5bf0-41b4-b21d-1e7d0d78b371\nAgent:   claude\nProject: /Users/ole/projects/chat-bandit\nModel:   claude-opus-4-8\nStarted: 2026-06-19T10:38:38.122Z\nMessages: 153\n\n--- #1 USER  [2026-06-19T10:38:38.122Z] ---\n  Do you remember us working on the tool approval yesterday?\n--- #2 ASSISTANT  [2026-06-19T10:38:44.405Z] ---\n  I don't have a running memory of our actual conversation yesterday, but I do have a saved note that matches what you're describing.\n--- #4 ASSISTANT  [2026-06-19T10:38:45.880Z] ---\n  ✓ Read\n    input: {\"file_path\":\"/Users/ole/.claude/projects/.../memory/plan085.md\"}\n    output: \u003csystem-reminder\u003eThis memory is 7 days old...\u003c/system-reminder\u003e\n```\n\n`search \u003cquery\u003e --pretty`:\n\n```\n[claude] 005f7977-937  #440  user\n  So what about going for simple saving of tool approvals / denials with regexes...\n[claude] 005f7977-937  #535  assistant\n  Written to `docs/architecture.md` — the repo's canonical systems doc...\n\n2 matches\n```\n\n## Library usage\n\nThe `@session-bandit/core` package exposes the indexing engine and adapters\nfor programmatic use — no CLI required.\n\n```ts\nimport {\n  indexSessions,\n  claudeAdapter,\n  codexAdapter,\n} from \"@session-bandit/core\";\n\n// Index all sessions from both adapters\nconst sessions = indexSessions([\n  { adapter: claudeAdapter },\n  { adapter: codexAdapter },\n]);\n\n// Or just one agent\nconst claudeSessions = indexSessions([{ adapter: claudeAdapter }]);\n\n// Each session is normalized to a common shape:\n// {\n//   agent, sessionId, filePath, project, cwd,\n//   startedAt, endedAt, model, messageCount, messages[]\n// }\n//\n// Messages use a `role` of user | assistant | system | tool | summary.\n// `summary` messages carry runtime-generated summaries (Claude recaps,\n// Codex compactions) with a `subtype` of \"recap\" or \"compaction\".\n```\n\n### Adapter interface\n\n```ts\ninterface Adapter {\n  readonly agent: AgentName;       // \"claude\" | \"codex\" | \"gemini\"\n  defaultRoot(): string;           // e.g. \"~/.claude/projects\"\n  discover(root: string): string[];// find session files under root\n  parse(filePath: string): Session;// parse one file → normalized Session\n}\n```\n\nA new agent is a new adapter file — nothing else changes. See\n`packages/core/src/adapters/` for reference implementations.\n\n## Where sessions live\n\nSession Bandit scans these directories by default:\n\n| Agent | Default location |\n|---|---|\n| Claude Code | `~/.claude/projects/\u003cencoded-cwd\u003e/*.jsonl` |\n| Codex | `~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl` (+ legacy flat files) |\n\nCodex has used three file formats over time — legacy `.json` (single object),\nflat `.jsonl` (no envelope), and modern envelope `.jsonl`. The Codex adapter\nhandles all three transparently.\n\n## Development\n\n```sh\npnpm install          # install deps\npnpm -r build         # build both packages\npnpm -r typecheck     # type-check (strict mode)\npnpm -r test          # run all tests\n\n# Run the CLI from source (no build needed, uses tsx):\npnpm dev list --pretty\npnpm dev show \u003csessionId\u003e\npnpm dev search \"query\" --pretty\npnpm dev doctor --pretty\n```\n\n### Project structure\n\n```\npackages/\n  core/                          @session-bandit/core — indexing engine\n    src/\n      types.ts                   normalized Session/Message/ToolCall model\n      adapter.ts                 Adapter interface\n      index.ts                   indexSessions() + exports\n      jsonl.ts                   JSONL reader\n      diagnose.ts                doctor diagnostics (format drift, injection markers)\n      adapters/\n        claude.ts                Claude Code adapter\n        codex.ts                 Codex adapter (3 formats)\n    test/                        fixtures + tests\n  cli/                           session-bandit — CLI\n    src/\n      bin.ts                     entry point\n      index.ts                   Commander program + cli()\n      scan.ts                    scanAll() + filters + sorting\n      format.ts                  output formatters (JSON, table, transcript)\n      commands/\n        list.ts                  list command\n        show.ts                  show command\n        search.ts                search command\n        extract.ts               extract command\n        doctor.ts                doctor command (parsing health)\n    test/                        tests\ndocs/\n  prd.md                         product requirements document\n  extract.md                     session extracts \u0026 digest design (primary v2 feature)\n  decisions.md                   decision log (the \"why\" behind the structure)\n  adapters.md                    how to add an agent / adapt to format drift\n  format-claude.md               Claude Code on-disk format reference\n  format-codex.md                Codex on-disk format reference (3 historical formats)\nskill/\n  SKILL.md                       Codex agent skill (handoff + memory note generation)\n```\n\n## Extending\n\nSee [`docs/adapters.md`](docs/adapters.md) for how to add a new agent adapter\nor adapt an existing one when a provider changes its on-disk format. Per-agent\nformat details live in [`docs/format-claude.md`](docs/format-claude.md) and\n[`docs/format-codex.md`](docs/format-codex.md). The rationale behind the\nstructural choices is in [`docs/decisions.md`](docs/decisions.md).\n\n## Roadmap\n\n**Done:**\n- **Session extracts** — the primary v2 feature. `extract` computes a\n  structured digest (substance score, files touched, commands, errors, key\n  turns) and can emit a ready-to-send synthesis prompt. See\n  [`docs/extract.md`](docs/extract.md).\n- **`doctor` command** — parsing health check that validates adapter\n  assumptions against real files (format drift, injection markers,\n  unrecognized types).\n\n**Next:**\n- **Skill definition** (separate repo) that calls `session-bandit extract\n  --prompt \u003ckind\u003e` and feeds the result to an LLM to write handoffs/memories\n  into a doc store.\n- **Gemini adapter** — the adapter guide uses Gemini as its worked example;\n  implementing it would dogfood the guide and round out the big three agents.\n- **Usage tier** — read Claude's `~/.claude/stats-cache.json` for offline\n  token/cost estimates. Codex `token_count` events already cleanly skipped.\n\n## Origin\n\nv0.1.0 — the full search, browse, extract, and doctor feature set, plus the\nagent skill and npm packaging — was built by [GLM-5.2](https://z.ai/blog/glm-5.2) in a single session.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanole%2Fsession-bandit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanole%2Fsession-bandit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanole%2Fsession-bandit/lists"}