diff --git a/skills/agent-session-resume/references/antigravity.md b/skills/agent-session-resume/references/antigravity.md index 013bc89..f2098c3 100644 --- a/skills/agent-session-resume/references/antigravity.md +++ b/skills/agent-session-resume/references/antigravity.md @@ -99,6 +99,30 @@ Prefer the strongest source for the question being resumed: If artifacts disagree, prefer the latest artifact that includes concrete verification evidence, then validate against current repository files and git state. +## Safe Reading + +Check size before opening any candidate artifact body: + +```bash +wc -lc "$HOME/.gemini/antigravity/brain//task.md" +``` + +Read `*.metadata.json` peeks before bodies, and rank candidates by strongest signal before reading: explicit user-supplied path first, then exact repo/workspace match from metadata or workspace storage, then summary/title match, with recency only as a tie-breaker. + +For markdown artifacts (`task.md`, `implementation_plan.md`, walkthroughs), map structure first and read only evidence-bearing slices: + +```bash +rg -n "^#|^-|TODO|\[x\]|\[ \]|error|failed|verified" path/to/task.md +sed -n '20,80p' path/to/implementation_plan.md +``` + +If a JSONL transcript or handoff from another agent surfaces in the workspace, project it with the packaged scripts from the skill's `scripts/` directory (next to `SKILL.md`) instead of reading raw lines: + +```bash +python3 "$skill_dir/scripts/session-events.py" path/to/transcript.jsonl --limit 200 +python3 "$skill_dir/scripts/session-digest.py" path/to/transcript.jsonl +``` + ## Reading Read artifacts in chronological order when possible. For local Antigravity data, inspect metadata first, then the smallest task/plan artifacts that explain: diff --git a/skills/agent-session-resume/references/claude-code.md b/skills/agent-session-resume/references/claude-code.md index d1a7dcf..3c4e4e9 100644 --- a/skills/agent-session-resume/references/claude-code.md +++ b/skills/agent-session-resume/references/claude-code.md @@ -2,6 +2,8 @@ Use this adapter when the prior session came from Claude Code or when the user points to a `.claude/` directory. +Packaged helper scripts live in the skill's `scripts/` directory, next to `SKILL.md`. Resolve them relative to the skill base directory and set `skill_dir` accordingly before using the commands below. + ## Discovery Start in the current workspace: @@ -27,9 +29,11 @@ find "$HOME/.claude/projects" -maxdepth 2 -type f -name '*.jsonl' 2>/dev/null find "$HOME/.claude" -maxdepth 1 -type f -name 'history.jsonl' 2>/dev/null ``` -Claude Code stores full transcripts and prompt history in different places: +Claude Code stores full transcripts, per-session sidecars, and prompt history in different places: - `~/.claude/projects//.jsonl`: full conversation transcript with messages, tool calls, and tool results. +- `~/.claude/projects///subagents/agent-*.jsonl`: subagent transcripts. When the main transcript delegates work to agents, include these in the evidence set; the main transcript may show only the dispatch and a summary. +- `~/.claude/projects///tool-results/*.txt`: large tool outputs spilled to disk. Read these targeted files instead of giant inline transcript lines. - `~/.claude/history.jsonl`: prompt history used for up-arrow recall, containing prompts with timestamps and project paths. Use `history.jsonl` as a locator and context supplement, not as a transcript replacement. It can reveal the project path, the user's exact prompts, and nearby session intent even when the matching transcript is hard to identify. When a relevant history entry is used, include the project path or prompt-history clue in the context summary. @@ -38,10 +42,19 @@ Treat Claude Code project transcripts as append logs that may still be active. A Do not treat a `history.jsonl` miss as evidence that no transcript exists. If prompt history does not contain the current cwd or session topic, inspect the cwd-derived `~/.claude/projects/` directory before broadening discovery. -Common useful formats include JSONL transcripts, Markdown exports, text exports, and metadata files. If a session name is provided, search contents and metadata before sorting by time: +Common useful formats include JSONL transcripts, Markdown exports, text exports, and metadata files. + +Raw-grep trap: do not grep `~/.claude/projects/` transcript bodies for a topic, skill name, or tool name as a discovery step. Every transcript embeds the available-skills list, plugin descriptions, and other boilerplate inside `system-reminder` blocks, so a topic-shaped `rg` produces mass false positives. Concrete failure shape: `rg -l "agent-session-resume" ~/.claude/projects/` matches roughly 20 unrelated sessions whose only "mention" of the skill is the skills list injected into every conversation. Project user messages first, then search the projected view: + +```bash +python3 "$skill_dir/scripts/session-events.py" "$candidate" | rg "text/user" | rg -i "" +``` + +For shortlisting candidates by cwd, topic, or time window without opening bodies, use the packaged lister. Time-bounded asks map to `--since` / `--until`, which accept relative windows (`7d`, `12h`) or ISO dates: ```bash -rg -i "" .claude ~/.claude ~/.claude/history.jsonl 2>/dev/null +python3 "$skill_dir/scripts/session-candidates.py" --platform claude-code --cwd "$(pwd)" --topic "" +python3 "$skill_dir/scripts/session-candidates.py" --platform claude-code --cwd "$(pwd)" --since 7d --until 1d ``` To filter prompt history by the current workspace path: @@ -73,10 +86,9 @@ Do not let prefix siblings outrank an exact cwd match. For example, `~/.claude/p If no title is provided, sort candidate files by modified time only after applying the stronger path and metadata signals. -When comparing candidate times, normalize to UTC or epoch seconds before deciding which record is newer: +When comparing candidate times, normalize to UTC or epoch seconds before deciding which record is newer. `session-candidates.py` prints every row's `updated_at` normalized to ISO-8601 UTC with seconds precision (e.g. `2026-06-10T00:15:30Z`) on both platforms, so its rows sort chronologically as plain strings, and `session-events.py` prints normalized event timestamps; cross-check against file and repo time: ```bash -jq -r '.timestamp // empty' "$session" | head stat -f '%m %N' "$session" 2>/dev/null git log -1 --format='%ct %h %s' ``` @@ -105,30 +117,19 @@ Use event types to skim before deep reading: Repeated `ai-title` events should be treated as one title signal per `(sessionId, aiTitle)` pair. Do not count duplicate title rows as progress, task evidence, or user/assistant turns. -For a message-only skim, extract visible user and assistant text plus bounded tool summaries: +For a message-only skim, extract visible user and assistant text plus bounded tool summaries with the packaged projector. It emits one previewed event per line with transcript line references and skips opaque thinking/signature payloads, which add noise and do not normally change task status: ```bash -jq -r ' - def text: - if (.message.content | type) == "string" then .message.content - elif (.message.content | type) == "array" then - [.message.content[] - | if .type == "text" then .text - elif .type == "tool_use" then "[tool_use " + .name + "] " + (.input | tostring) - elif .type == "tool_result" then "[tool_result] " + ((.content // "") | tostring | .[0:500]) - else empty - end - ] | join("\n") - else "" - end; - select(.type == "user" or .type == "assistant" or .type == "system") - | "\n=== \(.timestamp // "") [\(.type)] ===\n\(text)" -' "$session" +python3 "$skill_dir/scripts/session-events.py" "$session" --limit 200 ``` -Default skims should include assistant `text` blocks and tool-use summaries. Skip opaque thinking/signature payloads unless debugging transcript format behavior; they add noise and do not normally change task status. +For a compact reusable summary with evidence cues, build a digest. It writes a persistent `.digest.json` sidecar cache and processes only the appended tail on later runs: -Claude Code may persist oversized tool results outside the JSONL transcript. If a tool result contains a placeholder such as `` or says the full output was saved to `tool-results/.txt`, treat that sidecar as part of the session record. +```bash +python3 "$skill_dir/scripts/session-digest.py" "$session" +``` + +Claude Code persists oversized tool results outside the JSONL transcript, under the per-session sidecar directory `~/.claude/projects///tool-results/*.txt`. If a tool result contains a placeholder such as `` or says the full output was saved to `tool-results/.txt`, treat that sidecar as part of the session record. Likewise check `~/.claude/projects///subagents/agent-*.jsonl` whenever the main transcript dispatches subagents; project them with `session-events.py` like any other transcript. Inspect sidecars safely: @@ -151,30 +152,11 @@ For large transcript or tool-output files, use an evidence inventory before deep If the transcript may still be active or was modified during resume, recheck the tail before reporting. Use a bounded projected tail instead of dumping raw JSONL, so the final scan keeps visible messages, tool-use summaries, and tool-result previews while skipping opaque `thinking` or `signature` payloads: ```bash -tail -n 80 "$session" | jq -r ' - def projected_content: - if (.message.content | type) == "string" then - {kind: "text", body: .message.content} - elif (.message.content | type) == "array" then - .message.content[] - | if .type == "text" then - {kind: "text", body: .text} - elif .type == "tool_use" then - {kind: "tool_use", body: ((.name // "tool") + " " + ((.input // {}) | tostring))} - elif .type == "tool_result" then - {kind: "tool_result", body: ((.content // "") | tostring | .[0:500])} - else empty - end - else empty - end; - - select(.type == "user" or .type == "assistant" or .type == "system") - | . as $event - | projected_content - | "\($event.timestamp // "")\t\($event.type)\t\(.kind)\t\(.body)" -' +python3 "$skill_dir/scripts/session-events.py" "$session" | tail -n 40 ``` +Re-running `session-digest.py` is also cheap here: its `.digest.json` sidecar cache means only the appended tail is processed. + The exact stopping point should come from the final meaningful events, not from the first TODO list. Capture: - the last user prompt or instruction diff --git a/skills/agent-session-resume/references/codex.md b/skills/agent-session-resume/references/codex.md index dc8d914..960dc4c 100644 --- a/skills/agent-session-resume/references/codex.md +++ b/skills/agent-session-resume/references/codex.md @@ -2,6 +2,8 @@ Use this adapter when resuming a Codex session, continuing from a Codex desktop or CLI handoff, or when a Codex conversation summary is present. +Packaged helper scripts live in the skill's `scripts/` directory, next to `SKILL.md`. Resolve them relative to the skill base directory and set `skill_dir` accordingly before using the commands below. + ## Discovery Codex may provide prior context directly in the active conversation, through a compaction summary, or through files in the workspace. Treat injected conversation context as a session record, then validate it against the repository before editing. @@ -19,10 +21,16 @@ Codex normally stores conversation transcripts in the user-level Codex home, not tail -n 40 "${CODEX_HOME:-$HOME/.codex}/session_index.jsonl" 2>/dev/null ``` -Use `session_index.jsonl` to shortlist candidate session IDs by thread name, session name, and update time. If a title or topic is known, filter the index before opening transcripts: +Use `session_index.jsonl` to shortlist candidate session IDs by thread name, session name, and update time. Use the packaged candidate lister, which ranks candidates without dumping transcript bodies and accepts `--cwd`, `--topic`, `--since`, and `--until` filters: + +```bash +python3 "$skill_dir/scripts/session-candidates.py" --platform codex --cwd "$(pwd)" --topic "" +``` + +Warning: `session_index.jsonl` does not cover every transcript. Codex Desktop sub-threads (transcripts with a `parent_thread_id`) never get index entries, so any index-only listing silently omits them. The packaged lister compensates with an mtime fallback sweep over `sessions/YYYY/MM/DD` that surfaces unindexed in-window transcripts as `source=mtime` rows (untitled, so `--topic` cannot match them). On windowed asks where completeness matters, also broaden directly on disk: ```bash -jq -r 'select((.thread_name // "") | test(""; "i")) | [.updated_at, .id, .thread_name] | @tsv' "${CODEX_HOME:-$HOME/.codex}/session_index.jsonl" +find "${CODEX_HOME:-$HOME/.codex}/sessions" -name '*.jsonl' -newermt '' 2>/dev/null ``` After choosing a candidate ID, resolve it to the transcript file: @@ -53,13 +61,7 @@ session="" jq -r 'select(.type == "session_meta") | .payload.cwd // empty' "$session" | head -n 1 ``` -When checking several candidate transcripts, print a compact `cwdfile` inventory before ranking: - -```bash -for session in path/to/candidates/*.jsonl; do - jq -r --arg file "$session" 'select(.type == "session_meta") | [(.payload.cwd // ""), $file] | @tsv' "$session" | head -n 1 -done -``` +When checking several candidate transcripts, use `session-candidates.py` (above) to print a compact ranked inventory instead of looping `jq` over every file. ## Candidate Ranking @@ -84,10 +86,9 @@ Example: Use `git status --short --branch` early to understand what already changed. If the active folder is not a git repository, locate the relevant repo from the transcript or user-provided path. -When comparing candidate times, normalize to UTC or epoch seconds before deciding which record is newer: +When comparing candidate times, normalize to UTC or epoch seconds before deciding which record is newer. `session-candidates.py` prints every row's `updated_at` normalized to ISO-8601 UTC with seconds precision (e.g. `2026-06-10T00:15:30Z`) on both platforms; cross-check against file and repo time: ```bash -jq -r '.updated_at // .timestamp // empty' "${CODEX_HOME:-$HOME/.codex}/session_index.jsonl" | head stat -f '%m %N' "$session_file" 2>/dev/null git log -1 --format='%ct %h %s' ``` @@ -104,10 +105,10 @@ Before reading a candidate transcript, check its size and line count: wc -lc "$session_file" ``` -Project metadata with `jq` instead of dumping raw JSONL: +Project metadata and the bounded event stream with the packaged projector instead of dumping raw JSONL. Its first projected event is the `session_meta` routing record (id, cwd, originator, CLI version), followed by previewed user/agent messages, tool calls, and truncated tool output: ```bash -jq -c 'select(.type == "session_meta") | {id: .payload.id, timestamp: .payload.timestamp, cwd: .payload.cwd, originator: .payload.originator, cli_version: .payload.cli_version}' "$session_file" | head -n 1 +python3 "$skill_dir/scripts/session-events.py" "$session_file" --limit 200 ``` Use event types to decide what to inspect next: @@ -131,18 +132,13 @@ sed -n '120,220p' "$session_file" Do not use broad raw JSONL regex scans as the first evidence pass for Codex transcripts. Matches inside `session_meta`, embedded developer/system instructions, tool schemas, or serialized prompts can look like user-visible TODOs or errors even when they are only context. Project the event stream first, then apply targeted `rg` to that projected view or to a narrowed line range: ```bash -jq -r ' - select(.type == "event_msg" or .type == "response_item") - | if .type == "event_msg" and (.payload.type == "user_message" or .payload.type == "agent_message") then - [.timestamp, .payload.type, (.payload.message // .payload.text // "")] - elif .type == "response_item" and .payload.type == "function_call" then - [.timestamp, "tool_call", ((.payload.name // "tool") + " " + ((.payload.arguments // "") | tostring))] - elif .type == "response_item" and .payload.type == "function_call_output" then - [.timestamp, "tool_output", ((.payload.output // .payload.content // "") | tostring | .[0:1000])] - else empty - end - | @tsv -' "$session_file" | rg -n "error|failed|TODO|" +python3 "$skill_dir/scripts/session-events.py" "$session_file" | rg -n "error|failed|TODO|" +``` + +For a compact reusable summary with evidence cues, build a digest. It writes a persistent `.digest.json` sidecar cache and processes only the appended tail on later runs, so rechecks of an active transcript stay cheap: + +```bash +python3 "$skill_dir/scripts/session-digest.py" "$session_file" ``` Use raw `rg` only after the projection reveals a specific event, file path, command, or line range worth inspecting. @@ -155,17 +151,13 @@ Read the current conversation summary, local handoff files, and changed files re - facts verified from files - inferences from current repository state -For large Codex JSONL transcripts, start with a message-only skim to orient yourself before deeper review: +For large Codex JSONL transcripts, start with a bounded skim to orient yourself before deeper review: ```bash -jq -r ' - select(.type == "event_msg" or .type == "response_item") - | select(.payload.type == "user_message" or .payload.type == "agent_message") - | "\n=== \(.timestamp) [\(.payload.type)] ===\n\(.payload.message // .payload.text // "")" -' "$session_file" +python3 "$skill_dir/scripts/session-events.py" "$session_file" | rg "user_message|agent_message" ``` -This intentionally keeps only user and agent messages with timestamps, skipping session metadata, tool calls, tool output, and other large event payloads. Use it as an orientation step, not as a replacement for evidence review: still inspect relevant tool outputs, changed files, git state, tests, and artifacts before continuing work. +This keeps only previewed user and agent messages with timestamps and transcript line references, skipping session metadata and large event payloads. Use it as an orientation step, not as a replacement for evidence review: still inspect relevant tool outputs, changed files, git state, tests, and artifacts before continuing work. ## Resume Notes diff --git a/skills/agent-session-resume/references/cursor.md b/skills/agent-session-resume/references/cursor.md index 110ff75..94b994b 100644 --- a/skills/agent-session-resume/references/cursor.md +++ b/skills/agent-session-resume/references/cursor.md @@ -82,6 +82,32 @@ Read the export in order. Capture: Cursor export docs say exports include messages/responses, code blocks, file references/context, and chronological conversation flow. Still verify claims against current files and `git status` before editing. +## Safe Reading + +Cursor exports and project-scoped artifacts can be large. Check size before reading any candidate body: + +```bash +wc -lc path/to/export.md +``` + +Peek structure and evidence cues before reading bodies, then read only the slices that carry evidence: + +```bash +rg -n "^#|^##|TODO|error|failed|stop here" path/to/export.md +sed -n '40,120p' path/to/export.md +``` + +Rank candidates by strongest signal before opening anything: explicit user-supplied path first, then exact cwd/workspace match, then title match, with recency only as a tie-breaker (see Candidate Ranking below). Do not read whole files to decide between candidates. + +If a JSONL transcript surfaces (for example under `~/.cursor/projects//agent-transcripts/`, or a handoff produced by another agent), project it with the packaged scripts from the skill's `scripts/` directory (next to `SKILL.md`) instead of dumping raw lines: + +```bash +python3 "$skill_dir/scripts/session-events.py" path/to/transcript.jsonl --limit 200 +python3 "$skill_dir/scripts/session-digest.py" path/to/transcript.jsonl +``` + +For `terminals/` and other artifact folders, slice bounded ranges with `rg -n` plus `sed -n` rather than reading entire outputs. + ## Local Storage Safety Cursor chat history may be stored locally in SQLite, while Background Agent chats are not part of normal history and may be remote. Local storage formats can be large and unstable. diff --git a/skills/agent-session-resume/references/opencode.md b/skills/agent-session-resume/references/opencode.md index 70e8618..ab53c0b 100644 --- a/skills/agent-session-resume/references/opencode.md +++ b/skills/agent-session-resume/references/opencode.md @@ -45,6 +45,23 @@ find . -maxdepth 5 -type f \( \ \) 2>/dev/null ``` +## Safe Reading + +Check size before opening any candidate export, storage file, or fetched session dump: + +```bash +wc -lc path/to/export-or-session-file +``` + +Project or peek metadata before bodies: prefer `opencode session list` style listings, session titles, and timestamps over opening message bodies. Rank candidates by strongest signal before reading anything: explicit user-supplied path, share link, or session ID first, then exact cwd/project match, then title or summary match, with recency only as a tie-breaker. + +For markdown or text exports, map structure with `rg -n "^#|TODO|error|failed"` and read bounded `sed -n ',p'` slices instead of whole files. If a JSONL transcript surfaces (an export, or a handoff produced by another agent), project it with the packaged scripts from the skill's `scripts/` directory (next to `SKILL.md`): + +```bash +python3 "$skill_dir/scripts/session-events.py" path/to/transcript.jsonl --limit 200 +python3 "$skill_dir/scripts/session-digest.py" path/to/transcript.jsonl +``` + ## Reading Read the full session export or fetched session messages when available. If only a generated title or summary is available, treat it as incomplete and verify against files, tests, and git state.