Session Discovery
Utility skill that finds Claude Code conversation sessions stored on the local machine. Runs a bun script and returns a JSON manifest.
How to invoke
Run the discovery script from the harness root:
bash1bun "$(cat ~/.config/weft/root)/scripts/session-discovery.ts" [flags]
Flags
| Flag | Default | Description |
|---|---|---|
--since YYYY-MM-DD | today | Start of date window |
--until YYYY-MM-DD | today | End of date window |
--project <substring> | (all) | Filter by project path substring |
Examples
bash1SCRIPT="$(cat ~/.config/weft/root)/scripts/session-discovery.ts" 2 3# Today's sessions 4bun "$SCRIPT" 5 6# Sessions since last review 7bun "$SCRIPT" --since 2026-02-25 8 9# Only sessions in the roger project 10bun "$SCRIPT" --project roger 11 12# Two-day window, specific project 13bun "$SCRIPT" --since 2026-02-27 --until 2026-02-28 --project weft-dev
Output format
JSON to stdout. Diagnostics to stderr.
json1{ 2 "meta": { 3 "claudeDir": "/Users/name/.claude", 4 "since": "2026-02-28", 5 "until": "2026-02-28", 6 "filesScanned": 258, 7 "sessionsMatched": 6, 8 "errors": [] 9 }, 10 "sessions": [ 11 { 12 "sessionId": "uuid", 13 "project": "/Users/name/code/project", 14 "projectEncoded": "-Users-name-code-project", 15 "filePath": "/Users/name/.claude/projects/.../uuid.jsonl", 16 "start": "2026-02-28T00:21:36.816Z", 17 "end": "2026-02-28T01:56:48.087Z", 18 "messageCount": 178, 19 "userMessageCount": 59, 20 "firstPrompt": "first 120 chars of first real user message...", 21 "gitBranch": "feature-branch", 22 "schemaVersion": "2.1.59" 23 } 24 ] 25}
How consuming skills should use the manifest
1. Run the script, parse the output
bash1bun "$(cat ~/.config/weft/root)/scripts/session-discovery.ts" --since <last-review-date> 2>/dev/null
Parse the JSON from stdout. The meta object tells you how many
sessions were found and whether errors occurred.
2. Decide what to read
The manifest gives you file paths and message counts. Use this to decide whether to analyze inline or delegate to sub-agents (per the context management gate in session-review).
- Small window (1-2 sessions, < 200 total messages): read the JSONL files directly
- Large window (3+ sessions, or > 500 messages): dispatch sub-agents with specific file paths from the manifest
3. Read session content
Each filePath is a JSONL file. Each line is a JSON object. The
relevant message types:
type | Contains |
|---|---|
user | User messages. message.content is a string or array of {type, text} blocks. |
assistant | Agent responses. message.content is an array of text and tool_use blocks. |
queue-operation | Session lifecycle (enqueue/dequeue). Has timestamp but no content. |
progress | Streaming progress. Skip for analysis. |
file-history-snapshot | File state snapshots. Skip for analysis. |
Filter to user and assistant types for conversation analysis.
4. Filter noise from user messages
User message content often starts with IDE-injected metadata. Skip blocks matching these patterns:
<ide_opened_file>...<system-reminder>...<command-message>...<command-name>...<local-command...
Resilience notes
CLAUDE_CONFIG_DIR: The script checks this environment variable
first. If set, it uses that path instead of ~/.claude/. Most users
won't have this set.
Path encoding: The / → - encoding for project directories is
undocumented and could change. The script doesn't depend on decoding
being perfect — it just needs to find JSONL files under projects/.
The decoded project field is best-effort for display.
Schema changes: The JSONL format is internal to Claude Code and
undocumented. The script reads timestamp and type fields. If these
change, the script will return empty results (not crash). The
schemaVersion field in each session lets consumers detect version
mismatches.
30-day retention: Claude Code may delete sessions older than 30 days. The script can only find what's on disk.
Cross-midnight sessions: The script uses interval overlap logic, not simple date matching. A session starting at 23:00 on day N and ending at 01:00 on day N+1 will match queries for either day.