Repository navigation
Copies between accounts: clearer rows, sync on resume, fork from a turn, and review fixes - #20
Merged
Merged
Conversation
The plan prints a table whose ACTION column reads "create" or "fast-forward", which looks like a result. The only hint that nothing happened was a dimmed last line, and it was easy to miss: a copy ran without --apply, and resuming the session in the target account then failed with "No conversation found". The last line is no longer dimmed and starts by saying nothing was copied, moved or forked.
A session copied between accounts keeps its id, and the live-process map was keyed by id alone, so a process running the copy in one account marked every account's copy as running. The map is now keyed by account and id. The commands that must not touch a session running anywhere (copy, move, hide, clean) keep their own checks across accounts. The list also had no sign of the copy relationship that ccli show prints. A copied or moved session's account now reads "talcum ← default", from the newest copy or move recorded in the transfer ledger; forks are left out because they get a new id. JSON rows carry it as copied_from. The running and deleted marks now stand one space apart from the id, so a double-click in the terminal selects the id alone. Tested: go test ./..., and on the real index: only the account whose process runs 1087b979 shows it running, and its row reads "talcum ← default".
…an account `ccli fork <id> --turn N -a <account>` keeps the conversation through turn N of `ccli log` and leaves the rest out, in a new session beside the original. The cut is the byte offset of the next turn's prompt, taken from the index and checked against the file: the byte before it must end a line, and the line there must be a user message, where every turn starts. Agent transcripts started after the turn are left out, by the turn the index ties them to, or by start time when it could not place them. Only the conversation goes back; the plan and the result both say that files on disk stay as they are and the fork does not know the later changes. Without --turn a fork keeps everything, as before. `-a` names the account the fork goes into and is required; `--to` still works. `ccli resume <id> -a <account>` now brings that account's copy up to date from a newer one without --sync, which was the step people forgot. It still only appends to a copy the newer one extends exactly, still refuses diverged copies, and when a process runs the session it names the account to exit first. `--no-sync` restores the old check; `--sync` is accepted and is the default. The tutorial gains the pitfalls of switching accounts: a copy planned but not applied, switching while Claude Code runs, the account-less resume line Claude Code prints on exit, and a fresh copy showing $0. Tested: go test ./...; a real Claude Code resumed a fork cut at turn 1 of a two-turn session and recalled only turn 1; dry runs on the real index and the demo home.
checkParents started its walk one level down, so the account's own projects/ and file-history/ folders were taken on trust. A target whose projects folder is a symlink (another disk, a mount) was written through, which DESIGN.md says cannot happen. The walk now starts at the first folder below the account.
…replace a target that changed Only temporary files were synced. A rename into the target and a new folder were not synced to their directory, and `move` then renamed the source into the archive, so after a power cut the copy's rename could be lost while the source's removal was kept, leaving the transcript in neither account. Every rename, link and new folder is now synced to its directory, and the archive move syncs both folders it touches. A fast-forward copy wrote the whole transcript to a temporary file and renamed it over the target. A Claude Code process that resumed the session in the target meanwhile lost every line it appended. The copy now checks, just before the rename, that the target is still the size and age it was, and leaves it alone otherwise.
…through the last turn keeps The review of --turn found four ways the cut could go quietly wrong. The check on the cut accepted any user line, so a stale index could cut at a tool result and leave a dangling tool call. The parser's turn rule is now one function, transcript.StartsTurn, which the indexer and the fork check both use; the fork passes it in, so transfer still imports only account. Fork repeats the check just before it writes, against the file as it is then. Asking for the last turn read "no next turn" as "keep everything", so lines written after the index ran, a new turn included, came along and the plan said nothing. A fork through the last turn now ends where the index stopped reading, and the plan says how much it leaves out. The agents to leave out were trusted as given; a path that did not match the walk would have been copied anyway. Every one must now be found in the session's folders, at plan time and again before writing. `--turn 0` was taken as "no cut" although `ccli log --all` can show a turn 0. It is now refused with what turn 0 is. `resume --sync --no-sync` is refused instead of letting one win.
- fork's plan looked up its one session by loading every session of the account, and missed it when the session was hidden; it reads the one session now. - The quota window's usage left out web-search tokens and the share of its cost that came from process totals (unlogged), which the session, account and overview totals include. - In `sessions -v`, the account cell was dimmed inside a line that is dimmed as a whole, and its reset ended the dim early. - The copy/move plan's last line had an empty past tense for any verb but copy and move. - sessionModels' doc comment had ended up above copiedFrom. - DESIGN.md listed `fork --to` without -a or --turn, and called --json, --no-index and --color global although they follow the command.
prepare returns *query.DB and commands call a dozen methods the interface did not list, so the interface promised a boundary that did not exist. The TUI already declares the narrower Source it reads through, which is the pattern a future web server would follow too. DESIGN.md now describes it that way.
Restore hard-links an archived transcript into place, which fails when a file has appeared there. Where hard links do not work (another device, a file system without them) it fell back to a rename, which replaces such a file. The fallback now copies into a file it creates only if none exists, syncs it, and removes the archived copy afterwards.
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.
Summary
Work on sessions that live in more than one Claude Code account, plus the fixes from a code review of it.
Lists and plans
talcum ← defaultinccli sessions(JSON:copied_from).Dry run, nothing was copiedand is no longer dimmed.Resume and fork
ccli resume <id> -a <account>brings that account's copy up to date by default.--no-syncrestores the old check;--syncis still accepted. When a process runs the session, the error names the account to exit first.ccli fork <id> -a <account> --turn Nkeeps the conversation through turn N ofccli log, in a new session. The cut must land on a line that starts a turn by the parser's own rule (transcript.StartsTurn); a fork through the last turn ends where the index stopped reading; the agent transcripts to leave out must all be in the session's folders;Forkre-checks all of it before writing.--turn 0is refused. The plan and the result say that files on disk are not rolled back.-ais required;--tostill works.Write-path fixes from the review
checkParentsnow checks the account's ownprojects/andfile-history/folders for symlinks.movenever removes a source whose copy could be lost in a power cut.clean --undono longer falls back to a rename that could replace a transcript written since the run.Smaller
query.Service, which nothing used, is removed; DESIGN.md describes the real boundary and per-command flags.Deferred items are tracked in #19. The
resume --bestidea is #18.Test plan
go vet ./...,gofmt -l .,go test ./..., andgo test -raceon transfer, index, store and query.projects/target (fails on the old code); a target changed during a copy; the exclusive copy for undo.sessions,fork --turn,fork --turn 0,resume -awhile the session runs.