conv-lookup · git:20260703.4f52714 · 2026-07-03 · sha256 a1c0e4b8da266822
conv-lookup git:20260703.4f52714A
Immutable. This exact content is served forever at /api/v1/blob/a1c0e4b8da266822.
---
name: conv-lookup
description: Find, review, read, inspect, summarize, or compare Overdeck conversations. Use when the user references a pan.localhost/conv/<id> URL, a conversation ID (e.g. "conv 371", "conversation 108"), a fuzzy reference ("that GPT conversation", "the last Sonnet session"), or asks to review/read/look at/check/summarize/compare conversations. Maps conversation IDs to Claude Code JSONL session files and parses session content. Read-only.
triggers:
- review conversation
- read conversation
- look at conversation
- look at that conversation
- check conversation
- inspect conversation
- summarize conversation
- compare conversations
- what was in conversation
- that conversation
- pan.localhost/conv
- conv/
- conv
- conversation
---
# Conversation Lookup
Use this skill whenever the user references a Overdeck conversation — by `pan.localhost/conv/<id>` URL, numeric id, conversation name, or a fuzzy reference like "that GPT conversation". Handles single-conversation review, recent-conversation listing, search, and side-by-side comparison.
## When to use
- User asks about a specific conversation ID (e.g., "check conv/108", "what was happening in conversation 42?")
- User pastes a `https://pan.localhost/conv/<id>` URL and asks you to review, read, or look at it
- User wants to compare two conversations (e.g., voice/style diff across models)
- User wants to resume or summarize a past conversation
- User asks for recent conversation history
- Need to find the JSONL session file for a conversation to analyze its content
> **Do not** try `WebFetch` on `pan.localhost/conv/<id>` — the dashboard is an SPA and WebFetch will return empty page chrome. Always go through the script / `pan conv` CLI.
## "Which conversation am I in?"
If you are an agent inside a conversation and need to know *your own*
conversation (e.g. to hand it off), **do not** run `pan conv scan` / `list` /
`show` and guess. Run:
```bash
pan conv current # alias: pan conv whoami
```
This resolves the current conversation deterministically from the session you
are running in (PAN-1520) — no guessing. To hand off or fork your own
conversation, just omit `<conv>`: `pan handoff` / `pan fork` self-detect the
same way.
## How it works
Conversation and session state lives in the Overdeck SQLite database, but **this skill never reads that DB directly** — the DB location (`~/.overdeck/overdeck.db`) and its schema (UUID conversation ids, the per-harness session id in `conversation_files.locator`, etc.) are not a stable contract and have already shifted twice (PAN-2019 rebrand; `claude_session_id` column → `locator`). Instead, everything routes through the canonical `pan conv` CLI read door, which is schema-stable:
```bash
pan conv jsonl <id> # alias: pan conv transcript <id>
pan conv jsonl --json <id>
pan conv show --json <id> # conversation metadata (PAN-2018: conversation-first)
pan conv list --format json # discovered sessions
```
`pan conv jsonl` is the canonical resolver. It reads the conversation's recorded session id (the `locator` in `conversation_files`) + `cwd`, resolves through the shared Overdeck transcript-path helper, preserves the one-level `~/.claude/projects/*/<session-id>.jsonl` fallback, and reports one of:
- `ok` — path exists on disk
- `expired` — Claude session id is known, but the JSONL is not present on disk
- `unknown` — no session locator is recorded for this conversation
`conv-find.py --jsonl <id>` delegates to `pan conv jsonl --json <id>`; do not reimplement path encoding, derivation, or glob fallback in the skill script.
**The `session_file` column is deprecated (PAN-451) and NULL for all conversations created since 2026-05.** Never conclude "no session file recorded" from a NULL `session_file` — resolve through `pan conv jsonl` instead.
Plain `pan conv jsonl <id>` prints the absolute path to stdout and exits 0 only when status is `ok`; it exits 1 for `expired` and `unknown`. `pan conv jsonl --json <id>` always prints a JSON object containing `status`, `path`, `conversationId`, `claudeSessionId`, and `cwd`; read the `status` field rather than the process exit code in JSON mode.
## Running commands
The script is at the root of this skill directory. Always run it from any working directory.
### Find a specific conversation
```bash
python3 scripts/conv-find.py <id>
```
Example output:
```text
Conversation #108
Name: 20260412-4175
Status: ended
Model: claude-opus-4-6
Effort: medium
CWD: ~/Projects
Issue: N/A
Title: Lexerra game rules query out of scope
Cost: $22.90
Created: 2026-04-12T01:44:30.908Z
Ended: 2026-04-12T17:00:06.619Z
Session file: ~/.claude/projects/<project-hash>/<session-id>.jsonl
Session messages: 130
By role: assistant=62, user=68
Tool uses: 41
First prompt: I don't have any information about a game called "Lexerra"...
Last prompt: That means the new code is running but still producing nonsense words...
Last assistant: I traced the remaining nonsense generation to...
```
The Name/Status/Model/Title/Cost fields come from `pan conv show --json`. On
main branches predating PAN-2018, `show` returns session-only data and these
fields show `N/A` (the script falls back to `pan conv jsonl` for id / cwd /
transcript); they populate automatically once PAN-2018 lands.
### Get only the JSONL path
Prefer the canonical resolver directly:
```bash
pan conv jsonl 108
pan conv transcript 108 # alias
```
The skill helper delegates to the same command:
```bash
python3 scripts/conv-find.py --jsonl 108
```
### Print a normalized summary of recent notable messages
```bash
python3 scripts/conv-find.py --summary 108
```
This includes recent messages with:
- line number in the JSONL
- role
- tool names used in that message
- normalized text snippet
### Output machine-readable JSON
```bash
python3 scripts/conv-find.py --json 108
python3 scripts/conv-find.py --recent 20 --json
python3 scripts/conv-find.py --search gpt-5.4 --json
```
For a single conversation, `--json` includes:
- conversation metadata (resolved through `pan conv show --json`; falls back to the `pan conv jsonl` resolver on older main)
- a `session_summary` object with normalized session info parsed from the transcript
### List recent sessions
```bash
python3 scripts/conv-find.py --recent 20 # default 20
```
### Search by model / workspace / tools / files
Search is a client-side substring filter over `pan conv list --format json` (there is no CLI search door yet). It matches across primary model, workspace path, issue id, summary, models used, tools used, and files touched:
```bash
python3 scripts/conv-find.py --search lexerra
python3 scripts/conv-find.py --search gpt-5.4
```
## Session parsing behavior
The script now tolerates the JSONL message shape variations seen in real Claude Code sessions.
### Supported shapes
`message.content` may be:
- a plain string
- a list of strings
- a list of typed blocks
Typed blocks may include:
- `text`
- `thinking`
- `tool_use`
- `tool_result`
The parser normalizes these into:
- text fragments
- tool names
- role/timestamp/line metadata
## Parsing session content manually
If you still need custom parsing, do not assume `message.content` is always a list of dict blocks.
```python
import json, pathlib
path = pathlib.Path(session_file)
for line in path.read_text().splitlines():
if not line.strip():
continue
try:
obj = json.loads(line)
except json.JSONDecodeError:
continue
msg = obj.get("message")
if not isinstance(msg, dict):
continue
content = msg.get("content")
# content may be a string, list[str], or list[dict]
```
## Do not query the DB directly
There is no stable contract for the on-disk DB path or the `conversations`
schema, and both have already changed repeatedly (rebrand: `~/.panopticon` →
`~/.overdeck`; schema: integer → UUID ids, `claude_session_id` moved into
`conversation_files`, then renamed to `locator` with a `harness` column
alongside it). Direct SQL against the DB is what broke this skill in
the first place (PAN-2019).
Use the CLI doors instead:
```bash
pan conv jsonl --json <id> # transcript path + claudeSessionId + cwd
pan conv show --json <id> # conversation metadata (PAN-2018)
pan conv list --format json # discovered sessions
pan conv current --json # the conversation you are running in
```
If you genuinely need a raw DB inspection for debugging (not for resolving a
conversation), prefer the dashboard's read API (`GET /api/conversations/<id>`)
or the `pan conv` doors over hand-written SQL — the DB is a disposable cache
rebuilt from durable sources.
## Comparing two conversations
When the user wants a voice/approach/regression diff between two conversations:
1. Resolve both via `python3 scripts/conv-find.py --json <id>` to get `resolved_session_file`, `session_file_status`, and `model`.
2. Extract readable text from each resolved session file (use `--summary`, or jq for full text).
3. Present side-by-side labelled by model, so style differences are obvious.
Typical use cases: "how did GPT-5.4 handle this vs Sonnet?", "compare conv 365 and 366", "why does the GPT version feel clunkier?".
## See Also
- `unarchive-conversation` — restore an archived Overdeck conversation to active state (write operation; use this if the conversation you're reviewing is archived and you want it live in Mission Control)
- `pan show <id>` — inspect agent state for *issue* work (different scope — agents working on issues, not user conversations)