Metadata-Version: 2.5
Name: session-recall
Version: 0.4.1
Summary: Slice, search, and recover Claude Code session JSONL transcripts — MCP tools, a CLI, and an automatic post-compaction recovery hook.
Project-URL: Homepage, https://github.com/msrashed2018/session-recall
Project-URL: Repository, https://github.com/msrashed2018/session-recall
Project-URL: Changelog, https://github.com/msrashed2018/session-recall/blob/main/CHANGELOG.md
Author: Mohamed Salah Rashed
License-Expression: MIT
License-File: LICENSE
Keywords: claude-code,compaction,context-recovery,mcp,transcript
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Debuggers
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: click>=8.1.7
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.2; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: fastmcp>=3.2.4; extra == 'mcp'
Description-Content-Type: text/markdown

# session-recall

> Slice, search, and **recover** Claude Code session JSONL transcripts —
> primarily designed to repair the most painful moment in any long
> Claude Code session: **post-compaction amnesia.**

`session-recall` exposes the local JSONL store at
`~/.claude/projects/<encoded-cwd>/<uuid>.jsonl` to a running agent (via
MCP) and to humans (via CLI). It ships two complementary surfaces over
the same Python service layer:

- **MCP server** (`session-recall-mcp`) — 14 tools for an LLM agent to
  recall what happened earlier in the session, especially after the
  context window has been compacted into a lossy summary.
- **CLI** (`session-recall`) — the same operations one-shot from the
  terminal: `tail`, `head`, `range`, `grep`, `info`, `list`, plus the
  v0.2 recovery surface.

## Why it exists

Claude Code's context-compaction step replaces older turns with a
short summary. The summary is lossy: it routinely smooths away exact
file edits, dispatched background agents, the literal user prompts
that drove them, and errors. After compaction the agent often repeats
work, picks the wrong thread, or hallucinates that something was done
when it wasn't.

The fix is to read the **raw** JSONL on disk — every message,
tool_use, and tool_result is right there — and re-derive a structured
recap. That's what this tool does.

## Installation

### As a Claude Code plugin (recommended — MCP server + hook + skill in one)

This repo is self-hosted as its own Claude Code plugin marketplace. Installing
it wires the MCP server, the `SessionStart(compact)` recovery hook, and the
`session-recall` skill together — nothing to configure by hand:

```
/plugin marketplace add msrashed2018/session-recall
/plugin install session-recall@session-recall
```

Uses `uvx --from session-recall ...` under the hood (see `.mcp.json` /
`hooks/hooks.json`) — no separate `pip`/`uv tool install` step; `uvx` fetches
and caches the package on first use.

### As a standalone CLI/MCP install

```bash
# CLI + MCP server
uv tool install --with fastmcp session-recall

# CLI only (no agent surface)
uv tool install session-recall
```

The two binaries land at `~/.local/bin/`:

```
session-recall          # CLI
session-recall-mcp      # FastMCP stdio server
```

Add the MCP server to Claude Code by appending to `~/.claude.json` (or run
`claude mcp add` if you prefer):

```json
{
  "mcpServers": {
    "session-recall": {
      "type": "stdio",
      "command": "session-recall-mcp",
      "args": [],
      "env": {}
    }
  }
}
```

With this path you also need the hook wired manually — see "Automatic
recovery via hook" below — and the skill isn't installed at all (copy
`skills/session-recall/SKILL.md` to `~/.claude/skills/` yourself if you want
it). The plugin install above does all three in one step.

## Headline workflow — post-compaction recovery (v0.2)

When a turn begins with *"This session is being continued from a
previous conversation that ran out of context"*, your first move
should be:

```python
mcp__session-recall__recall_after_compaction(cwd="/path/to/project")
```

You'll get a single structured payload (typically ≤ 30 KB) covering:

- **`prompts`** — the verbatim user prompts since compaction.
- **`files_changed`** — every file touched (Write/Edit/MultiEdit/
  NotebookEdit) deduplicated, with first/last touched turn.
- **`commands`** — every `Bash` invocation, with `bg_id` and
  `exit_code` parsed out of the matching tool_result.
- **`agents_dispatched`** — every `Task`/`Agent` call with its
  subagent type, description, and isolation mode.
- **`errors`** — error tool_results, interrupts, and `API Error: 5xx`
  in assistant text.
- **`compaction`** — line/byte position of the marker that anchored
  the slice, plus the marker's full summary text.

When a section overflows the per-section `max_*` cap, the response
flags it and you can drill in via the dedicated tools below.

## Automatic recovery via hook (v0.3.0+) — no agent action required

> Installed via the plugin above? This is already wired for you (see
> `hooks/hooks.json`) — skip to [Other recovery tools](#other-recovery-tools).
> This section is for the standalone CLI/MCP install path.

The workflow above still depends on an agent remembering to call
`recall_after_compaction` (or reading CLAUDE.md instructions telling it to).
`session-recall session-start-hook` removes that dependency: wired to
`SessionStart` with `matcher: "compact"`, it runs the moment compaction
happens and injects a structured digest + the last 8 turns verbatim
straight into the new session's context, automatically, every time — no
agent cooperation needed, no pre-compaction warning to notice in time, and
no extra script to install. It's the installed `session-recall` binary
itself, one subcommand among the others in this README.

Add this to `~/.claude/settings.json` (or a project's `.claude/settings.json`)
alongside whatever other `SessionStart` hooks you already have — Claude Code
runs every hook group whose matcher matches, so this is additive, not a
replacement:

```jsonc
{
  "hooks": {
    "SessionStart": [
      // ... any hooks you already have ...
      {
        "matcher": "compact",
        "hooks": [
          { "type": "command", "command": "session-recall session-start-hook", "timeout": 30 }
        ]
      }
    ]
  }
}
```

That's the whole install. It fails open at every step — non-`compact`
sources, missing session_id/cwd, an internal error resolving the session —
by printing nothing and exiting 0, so a broken hook can never block session
start. This replaces an older, informally-used pattern of nagging the
pre-compaction agent via `UserPromptSubmit`/`PostToolUse` to hand-write a
free-text handoff file: that depended on an LLM noticing a warning and
complying in time and produced unpredictable-quality prose; this pulls
deterministic, structured data straight from the transcript every time,
using the exact same service functions as every other tool in this README.

Run `session-recall doctor --cwd <project>` any time to validate the whole
chain end-to-end against real data: binaries on PATH, the newest session for
that project, every recovery tool, the hook itself (invoked live, against
that real session — not a fixture), whether it's actually wired in
`settings.json`, and its log file. Prints PASS/WARN/FAIL per check.

## Other recovery tools

| Need | Tool |
|---|---|
| Just the user's prompts (the 80% case) | `prompts_timeline(since_compaction=True)` |
| What did the agent actually do? | `tool_call_ledger(since_compaction=True)` |
| Which files do I need to re-Read? | `files_changed(since_compaction=True)` |
| Where are the compaction events in this session? | `compaction_events()` |
| Find a specific symbol/path | `grep_session(pattern, ...)` |
| Just browse | `tail_session(count=N, with_tools=False)` |

Every "since_compaction" tool also accepts an explicit `start_turn`
and `end_turn` (1-based `Turn.index`, negatives count from the end).

## CLI quickstart

```bash
# What sessions exist for this project?
session-recall list

# Stats — turn count, time span, compaction events, top tools
session-recall info

# Recover after compaction
session-recall recall-after-compaction --format md

# Compact ledger of every Bash + Task call since the compaction
session-recall tool-call-ledger --since-compaction --tool Bash --tool Task

# Files I've edited since the compaction
session-recall files-changed --since-compaction

# Just the prompts
session-recall prompts-timeline --since-compaction --text-trunc 200

# Slice — last 5 turns with full tool I/O
session-recall tail -n 5 --with-tools

# Search a session
session-recall grep "auth_service" --include-tools -C 2
```

The CLI takes `--session-id <uuid>` to target a specific session,
defaulting to the newest in the current `--cwd`. Cross-project
operations live in `list-all`, `search-all`, `export`, and
`export-recent`.

## Output format

Every command emits Markdown by default. Pass `--format json` to get
a stable, machine-readable envelope:

```jsonc
{
  "session_id": "...",
  "source": "/home/u/.claude/projects/.../<uuid>.jsonl",
  "mode": "tool_call_ledger",
  "start_turn": 14, "end_turn": 22, "count": 41,
  "entries": [
    { "turn": 14, "ts": "...", "tool": "Bash", "summary": "git status -s",
      "ok": true, "bg_id": null, "exit_code": null },
    // …
  ]
}
```

## Tests + dev

```bash
uv sync --extra dev --extra mcp
uv run pytest -ra
uv run ruff check src/ tests/
uv run mypy src/
```

## Project layout

```
src/session_recall/
├── cli.py            Click entry — one subcommand per service operation
├── mcp_server.py     FastMCP entry — one @mcp.tool() per service operation
├── service.py        Pure orchestration; CLI + MCP both call into here
├── digest.py         Per-tool summarisers + extractors (the heart of v0.2)
├── loader.py         Wire-format → Message stream + compaction-event scan
├── turns.py          Group messages → Turn objects (carries line numbers)
├── filters.py        Time + role + turn-index filters
├── search.py         Grep-with-context windows
├── stats.py          Session statistics (compaction count, etc.)
├── locator.py        ~/.claude/projects/<encoded-cwd>/ resolver
├── cross_session.py  list-all + search-all (across project dirs)
├── exporter.py       Write a session out to disk (md/html/json)
├── models.py         Domain types
└── render/           md / json / html renderers

.claude-plugin/
├── plugin.json        Claude Code plugin manifest
└── marketplace.json    Self-hosted marketplace — this repo lists itself (source: "./")
.mcp.json               MCP server entry (uvx --from session-recall session-recall-mcp)
hooks/hooks.json         SessionStart(compact) hook entry
skills/session-recall/   The skill teaching Claude how to use the tools above
```

See `CHANGELOG.md` for what's new in each release.
