session mirror: --follow, --all, compact (+ cwd-encoding fix)#10
Merged
Conversation
session mirror --follow/-f re-flushes every --interval seconds (default 5) until Ctrl-C, so a crash loses at most one interval of trace instead of the whole run. Refactors the mirror body into a reusable _mirror_once() so single- shot and follow behave identically; reuses the incremental cursor + --min-bytes gate (empty cycles cost no upload). Ctrl-C stops cleanly and stamps ended_at. Batches one PUT per interval rather than streaming per event, keeping per-operation request cost flat. Tests: follow loop (patched sleep raises KeyboardInterrupt after N cycles, asserts two disjoint parts + ended_at) and non-positive --interval rejection. Docs: README session-mirroring section + docs/session-mirror.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
_encode_cwd only replaced "/" with "-", but Claude Code slugifies the cwd by collapsing every run of non-alphanumeric chars (including "_" and ".") to "-". So sessions for any folder like test_session_flow or my.proj were silently undiscoverable — `session mirror` reported "No claude-code session found" and forced users to pass --session-id by hand. Now uses re.sub to match. Regression test pins the _ and . cases and confirms plain hyphenated names (data-universe) are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
--follow writes one part per flush, so long sessions accumulate many small objects. `session compact <id>` concatenates them in seq order, byte-for-byte, into a single new part and deletes the originals. Replay (session show) is identical before/after. Safe ordering: merged part uploaded + meta rewritten BEFORE any original is deleted, so a crash mid-compact leaves a harmless duplicate, never a gap. --keep-tail N leaves the newest N parts alone (e.g. while --follow still appends). Tests: byte-identical replay after merge, --keep-tail, single-part no-op. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One terminal mirrors a whole project: --all re-discovers all sessions under --cwd each cycle and flushes each (own cursor), picking up sessions that start after the loop begins. Implies --follow, rejects --session-id. Ctrl-C marks all followed sessions ended. Tests: multi-session + mid-run pickup, --session-id rejection. Docs updated for --all and compact (README quick-ref + docs/session-mirror.md). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI runs ruff format --check with a newer ruff (0.15.20) than local; it expands the --all/--session-id test invocation across lines and collapses two wrapped lines in compact(). Pure formatting, no logic change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Arrmlet
added a commit
that referenced
this pull request
Jun 27, 2026
session mirror --follow / --all / compact + claude-code cwd-encoding fix (PR #10). Also syncs __init__.__version__ (was stale at 0.2.1). Co-Authored-By: Claude Opus 4.8 (1M context) <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.
Live and multi-session mirroring for
tracecraft session, plus a real bugfix surfaced along the way. Four focused commits.What's new
session mirror --follow(-f)[--interval SECONDS]— near-real-time mirroring. Re-flushes every interval (default 5s) until Ctrl-C, so a crash loses at most one interval of trace. Reuses the incremental cursor +--min-bytesgate, so idle cycles upload nothing. Ctrl-C stops cleanly and stampsended_at. One PUT per interval (batches, doesn't stream per event) to keep request cost flat.session mirror --all— one terminal mirrors a whole project: follows every session under--cwd, including sessions that start after the loop begins, each with its own cursor. Implies--follow, rejects--session-id. Scoped to one cwd + harness.session compact <id>[--keep-tail N]— merges a session's many part files into one, byte-for-byte;session showoutput is identical before/after. Safe ordering: merged part is uploaded andmeta.jsonrewritten before any original is deleted, so an interrupted compact leaves a harmless duplicate, never a gap.fix(claude-code): cwd slugify for
_and.—_encode_cwdonly replaced/, but Claude Code collapses every run of non-alphanumeric chars (incl._and.) to-. So sessions for any folder liketest_session_flowwere silently undiscoverable and forced users to pass--session-idby hand. Now matches Claude Code's real encoding, with a regression test.Testing
--ignore=tests/test_replay_collect.py, a pre-existing untracked/broken module). New tests cover: follow loop clean-stop,--allmulti-session + mid-run pickup, compact byte-identical replay /--keep-tail/ single-part no-op, and the underscore/dot encoding regression.Docs
README quick-ref +
docs/session-mirror.mdupdated for--follow,--all, andcompact.Not in this PR (deliberate)
--allis per-cwd/per-harness; cross-folder / cross-harness auto-mirroring is the hooks' job.🤖 Generated with Claude Code