feat(sdk): Store Claude SDK sessions in .warden/sessions/#193
Open
feat(sdk): Store Claude SDK sessions in .warden/sessions/#193
Conversation
Add session storage functionality to capture SDK conversations for debugging, analysis, and replay purposes. Changes: - Add SessionCollector class to capture SDK messages during query execution - Store sessions organized by timestamp and session ID - Add utilities for listing, reading, and pruning old sessions - Integrate session capture into the SDK runner with opt-in configuration - Add .warden/sessions/ to gitignore - Add comprehensive tests for session storage Closes #188 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> https://claude.ai/code/session_012gZ8yStobN3XJ4gaL2YxMH
Rework session storage to move the JSONL files Claude Code writes internally (~/.claude/projects/<hash>/<uuid>.jsonl) to .warden/sessions/ after each query, rather than creating a parallel capture from the stream. - session.ts: replace SessionCollector with moveSession() + getClaudeProjectDir() - config/schema.ts: add [sessions] config block (enabled, directory) - analyze.ts: call moveSession() post-query using result uuid - executor.ts, main.ts: pass config.sessions into runnerOptions Configure via warden.toml: [sessions] enabled = true Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com> https://claude.ai/code/session_012gZ8yStobN3XJ4gaL2YxMH
- Replace renameSync with copyFileSync+unlinkSync to handle EXDEV errors when home directory and repo are on different filesystems (Docker/CI) - Default session storage to enabled - Gitignore .warden/ (not just .warden/logs/) on init Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add retention-based session cleanup (7-day default, auto mode) - Rename cleanupLogs to cleanupArtifacts for shared log/session use - Default session storage to enabled - Gitignore .warden/ on init (covers logs and sessions) - Use copy+delete for cross-device moves (EXDEV) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Only pass enabled/directory to SDK (strip cleanup/retention fields) - Defensive statSync in listSessions sort for race conditions - Add .warden/ to repo gitignore - Improve readability of init gitignore check Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When [sessions] is omitted from warden.toml, config.sessions is
undefined. Previously this meant sessions were silently disabled.
Now all entry points default to { enabled: true } so sessions work
out of the box without any config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of relying on resultMessage.uuid (unavailable on abort/error), snapshot Claude's project dir before each executeQuery and diff in a finally block to capture any new session files. This ensures sessions are stored even when runs are cancelled or fail. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove moveSession (replaced by snapshot-based moveNewSessions) - Remove findExpiredSessions and pruneOldSessions (cleanup uses cleanupArtifacts from log-cleanup.ts) - Fix session cleanup to use resolveSessionsDir for correct absolute path handling - Add existsSync guard in moveNewSessions for concurrent hunk races - Remove tests for deleted functions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Handle stat failures individually for each file so the comparator remains consistent with the sort contract (compare(a,b) = -compare(b,a)). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace specific .warden/logs/ and .warden/sessions/ entries with a single .warden/ catch-all and move it to the correct section. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move session capture from per-hunk to per-skill level so all SDK processes have fully exited and flushed before copying files - Add session handling to CLI task runner (tasks.ts) which was missing it - Skip empty (0-byte) session files as defense against race conditions - Name session files as <skill>-<shortId>-<datetime>.jsonl - Name log files as <shortId>-<datetime>.jsonl (id-first, consistent) - Show log file path after summary at normal verbosity - Add reporter.dim() for subtle output visible without --debug - Replace blind catches with logged warnings via Sentry logger - Fix ?? to || for empty string shortUuid fallback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| error: err instanceof Error ? err.message : String(err), | ||
| skill: displayName, | ||
| }); | ||
| } |
There was a problem hiding this comment.
Concurrent skills race on session file snapshot
Low Severity
When multiple skills run concurrently via runComposedSkillTasks (which launches all tasks in parallel), each runSkillTask snapshots the same shared Claude project directory before work begins. Because all snapshots capture the same initial state, the first skill to complete its moveNewSessions call moves ALL new session files (including those from other concurrent skills) under its own prefix. Remaining skills find nothing to move, causing session misattribution.
The log path was displayed after the summary even when the write failed, showing both a warning and a path to a non-existent file. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
Dead code — only referenced in tests, never called in production, and there are no external consumers of this package. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Capture SDK session transcripts by moving session files from Claude SDK's
internal storage into
.warden/sessions/after each run. Keeps all Wardenartifacts under
.warden/and lets downstream tooling inspect or replaysession data.
Session storage is enabled by default. Files are moved (copy+delete) rather
than renamed to handle cross-filesystem boundaries in Docker/CI. Expired
sessions are auto-pruned using the same retention pattern as logs.
warden initnow gitignores.warden/(covering both logs and sessions).Fixes #188