Releases: it-bens/cc-port
Release list
v0.7.0 - Codex Support Alongside Claude Code
Summary
Add OpenAI Codex support alongside Claude Code. Every command now takes a repeatable --tool flag to pick which tools a run touches, moves are crash-safe across both tools, and non-fatal findings surface as warnings instead of silent skips.
Changes
Features
- Add OpenAI Codex as a second supported tool.
move,export,import,push,pull, andstatsall operate on Codex projects, and with--toolomitted a command runs against every tool it detects. Pass--tool codexor--tool claude(repeatable) to limit a run. (#55) - Make moves crash-safe. A move stages its writes and publishes them by atomic rename; an in-process failure rolls back and restores file modification times, and a move killed mid-apply re-runs to convergence. (#55)
- Surface non-fatal findings as warnings.
move,import, andpullnow report a malformed history line, an active writer, or a rules file that references the project instead of silently skipping the entry or refusing the whole run. (#55)
Fixes
- Stop Claude import from answering the destination machine's security prompts. Import used to copy the
.claude.jsontrust-dialog and external-include approval keys verbatim, pre-accepting the folder-trust checkpoint that gates the archive'sallowedToolsandmcpServers. Those keys are now destination-owned, so Claude Code asks its own questions the first time an imported project opens. (#62) - Raise the Go floor to 1.26.5 so release binaries pick up the stdlib fixes for the crypto/tls and os vulnerabilities. (#54)
- Render
push,pull, andmove --applyoutput after the progress ledger tears down. Plan summaries and result tables were interleaving with the ledger's live region and staircasing across the terminal. Apply runs also print a real command header instead of the[dry-run]prefix. (#64) - Reconstruct per-session witnesses on Claude import. An imported project used to land unwitnessed, so its identity check was skipped with a "no witness" warning.
importnow writes a~/.claude/sessions/<id>.jsonwitness for each staged session, attributed to the destination and recorded with pid 0 so it never blocks a later move. (#63) - Make Codex rollout imports converge. When an import stages a rollout, cc-port re-arms Codex's one-shot session backfill so the next Codex start rebuilds the missing
threadsrows. The old warning told users to rerun after opening the project, which never worked. (#61) - List Codex projects known only through a rollout file in all-projects stats.
statsbuilt its project set from thread cwd values andconfig.tomlkeys alone, so a project whose cwd appeared only in a rollout was missing entirely. (#58) - Close the pull dry-run and push warning parity gaps. Pull's dry-run now refuses every archive
--applywould refuse by running the same preflight gates, and push now prints the export warnings it was silently dropping. (#59)
Documentation
- Refresh the export/import, push/pull, and move demo clips to show both Claude Code and Codex. (#65)
Dependencies
Breaking Changes
The --claude-dir flag is gone. Use --claude-home or --codex-home to override a tool's state location, and --tool <name> (repeatable) to limit a run to specific tools.
metadata.xml changed shape. The old root-level <export><categories> block and top-level <placeholders> are replaced by one <tool name="..."> block per exported tool, each carrying its own categories and placeholders. Archives produced by v0.6.0 and earlier don't import.
Upgrade Notes
- Replace any
--claude-dir <path>invocation with--claude-home <path>. - Re-export any archives you still need to import. Archives from v0.6.0 and earlier no longer load under the new
metadata.xmlschema.
v0.6.0 - Project Stats Command
Summary
Adds cc-port stats, a read-only command that reports per-surface path-reference counts and disk footprint for one project or all projects. Also replaces error-string matching with exported sentinels across lock, move, and manifest.
Changes
Features
- Add
cc-port stats <project-path>to show per-surface path-reference counts, per-category disk usage, and history/session-file counts for a project. Runcc-port statswith no argument to rank all projects by disk footprint. Pass--jsonto either mode for machine-readable output. (#51)
Refactors
- Replace
err.Error()substring checks inlock,move, andmanifestwith exported sentinels and typed errors (LiveSessionsError,ErrEncodedDirAmbiguous,ErrManifestFileTooLarge, and others), so callers can branch on error identity rather than message wording. (#50)
CI
Dependencies
- Update
charmbracelet/x/exp/teatest/v2to a newer pre-release commit. (#48)
Upgrade Notes
No breaking changes.
v0.5.1 - Fix Live Ledger Terminal Input
Summary
Fixes garbled escape sequences appearing at the shell prompt after any command that uses the live progress ledger. The ledger now owns the controlling terminal's input reader, which lets Ctrl+C cancel a running command rather than being dropped.
Changes
Fixes
- Fix garbled text at the shell prompt after ledger-mode commands by letting bubbletea own the terminal's input reader, so startup capability queries drain before the ledger exits. (#46)
- Route Ctrl+C to context cancellation via a new
Interruptibleinterface on the ledger renderer. Non-TTY runs and external signals keep the existingsignal.NotifyContextpath, so cancellation behavior is uniform at the context level. (#46)
Upgrade Notes
No breaking changes.
v0.5.0 - Live Progress & Portable Paths
Summary
Add live progress rendering to all long-running commands and extend the move/export/import pipeline to handle the encoded project storage directory. Two bug fixes close an inaccurate dry-run count in move and a temp-file leak in import.
Changes
Features
-
Add live progress rendering to
move --apply,export,import,push, andpull. A newinternal/progresspackage provides four renderers: a bubbletea TTY ledger with spinners and per-phase timers, an ANSI-free stream mode for CI (rate-limited to onePhaseAdvanceline per phase per 500 ms), newline-delimited JSON under--json, and a null sink under--quietthat keeps warnings. New persistent flags--quiet,--verbose,--debug, and--jsonare available on every subcommand. (#42) -
Anonymize and rewrite the encoded project storage directory (
~/.claude/projects/<encoded>) across export, import, and move. Export replaces it with{{PROJECT_DIR}}. Import resolves it to the recipient machine's encoded path. Move rewrites it alongside the real project path so references in transcript and memory files stay consistent. (#40)
Fixes
-
Report memory-file replacements in the
movedry-run preview. The--applypass has always rewritten memory files, but the preview counted only transcript replacements. A newMemory: N replacementsline now appears in the output. (#44) -
Reclaim staging temp files orphaned by a failed import write. When a staging write failed after the temp file was created, the temp stayed on disk because the staging record was only built on success. The record is now built as soon as the temp path is known, so
cleanupTempsremoves it on any error path. (#43)
Dependencies
- Update charm.land/lipgloss/v2 to v2.0.4, charm.land/bubbles/v2 to v2.1.0, charm.land/bubbletea/v2 to v2.0.7, and several AWS SDK Go v2 modules across 4 Renovate PRs. (#36, #38, #39, #41)
CI
- Add a Homebrew environment to the release job for Homebrew Cask distribution.
- Update actions/checkout to v6.0.3. (#37)
Upgrade Notes
No breaking changes.
v0.4.0 - Move Timestamp Preservation & Demo Videos
Summary
move --apply now preserves modification times on relocated session files, keeping Claude Code's /resume picker in order after a move. This release also adds animated GIF demos for all three main commands to the README.
Changes
Features
- Preserve modification times on session files during
move --apply, so Claude Code's/resumepicker maintains its order after a relocation. Transcripts and memory files carry their source mtime throughCopyDir. Todos, usage data, plugins data, and tasks restore their pre-rewrite mtime viaos.Chtimes. Merged globals likehistory.jsonlget a fresh write-time since they're edited rather than copied verbatim. (#35)
Documentation
- Add animated GIF demos for
move,export/import, andpush/pullto the README, embedded at each command's section. The recordings are reproducible from VHS tape sources indocs/videos/. A single-node Garage S3 compose stack indev/s3/handles the remote for thepush/pulltape, andmake videosrebuilds all three GIFs and MP4s. (#31) - Update release verification instructions to use the
.sigstore.jsonbundle format. The--bundleflag replaces the earlier--signature/--certificatepair.
Dependencies
- Bump
github.com/aws/aws-sdk-go-v2/credentialstov1.19.17and patch-bump GitHub Actions (golangci-lint-action,goreleaser-action). (#33, #34)
Upgrade Notes
No breaking changes.
v0.3.0 - Logo Build Variant and Signed Releases
Summary
Ships cc-port-with-logo as a second binary compiled with -tags=logo, rendering the gantry-crane logo on --help, --version, and the interactive category prompt. The default cc-port build is unchanged. Release artifacts are now signed with cosign keyless OIDC, and CI validates the goreleaser config and runs a full snapshot build on every push.
Changes
Features
- Add
cc-port-with-logo, a second Homebrew-installable binary that renders the gantry-crane logo on--help,--version,version, and the interactive category prompt. The defaultcc-portbuild shows no logo.logo.Bannerbecomes the sole exported entry point ininternal/logo; all previously exported logo functions are unexported. (#28)
Build / Release
- Fix goreleaser config to use
archives[*].idsinstead of the removedarchives[*].buildskey, bind each Homebrew cask to the correct archive, and add cosign keyless OIDC signing that attaches achecksums.txt.sigstore.jsonbundle to each release. (#29) - Switch cosign signing from separate certificate and signature files to the bundle format (
--bundle), producing a single.sigstore.jsonartifact. Pin cosign to v3.0.6. (#30)
CI
- Replace the
buildjob withgoreleaser-check, which validates.goreleaser.ymlschema on every push, and addrelease-snapshot, which runs the full goreleaser pipeline in snapshot mode (build, archive, checksum, keyless sign) without publishing. (#30)
Chore
- Add a Claude Code brainstorming hook context that injects cc-port's design-rules overlay, so feature proposals are checked against the correct internal primitives before implementation.
Dependencies
- Update
aws-sdk-go-v2/service/s3(v1.92.1 to v1.101.0),gjson(v1.18.0 to v1.19.0), andgolangci-lint(to v2.12.2). (#27, #26)
Upgrade Notes
No breaking changes.
v0.2.0 - Remote Sync and Encrypted Archives
Summary
Adds cc-port push and cc-port pull for syncing archives to file:// and s3:// remotes with optional passphrase encryption. Placeholder discovery switches to an anchor-based algorithm that resolves {{HOME}} implicitly, which removes the --resolution flag from import and pull.
Changes
Features
- Add
cc-port pushandcc-port pullfor syncing project archives tofile://ands3://remotes via gocloud.dev blob. Push detects prior uploads from a different machine and refuses without--force; pull renders a dry-run plan before applying. (#7) - Add passphrase encryption to
export,import, andimport manifestvia--passphrase-envand--passphrase-file. Archives are encrypted with age scrypt; the import side detects and decrypts without extra configuration. (#6) - Add
--credentials-fileand--no-prompttopushandpullfor injecting AWS credentials from a.env-style file or environment variables before falling back to an interactive TTY prompt. Files with permissions looser than 0600 are rejected. (#23) - Preserve source file modification times on verbatim archive entries through the export/import round-trip. The
/resumesession picker in Claude Code now sorts imported sessions in their original chronological order rather than by import time. (#25) - Switch placeholder discovery to an anchor-based algorithm that accepts only paths under
{{PROJECT_PATH}}or{{HOME}}.{{HOME}}now resolves implicitly on import alongside{{PROJECT_PATH}}, so neither anchor requires user interaction. (#19)
Fixes
- Fix
pushandpullwith S3-compatible remotes that pass a bare-hostendpointparameter. The opener now prependshttps://(orhttp://whendisable_https=true) so the AWS SDK receives a valid URL. (#24) - Stop rejecting archives whose content contains
{{UPPER_SNAKE}}-shaped text not listed in the manifest. Session logs, skills, and documentation can hold such patterns; the preflight pass now only checks that declared placeholder keys have a resolution. (#21) - Upgrade
google.golang.org/grpcto v1.80.0, addressing GO-2026-4762 (authorization bypass via malformed:pathheader), and update the OpenTelemetry suite to v1.43.0. (#18)
Dependencies
Breaking Changes
--resolution is removed from cc-port import and cc-port pull. Scripts that passed custom placeholder values via --resolution KEY=VALUE must switch to --from-manifest <file.xml>.
Archives exported before this release that contain {{UNRESOLVED_N}} placeholder keys can't be imported without a manifest file providing resolve entries for those keys.
Three symbols are removed from cc-port internals: GroupPathPrefixes and PlaceholderSuggestion.Auto from internal/export, and Placeholder.Resolvable from internal/manifest.
Upgrade Notes
Remove --resolution flags from any import or pull invocations and supply a manifest with --from-manifest instead. Archives that don't contain {{UNRESOLVED_N}} keys need no changes.
v0.1.0 - Move, Export, Import
Summary
First public release of cc-port, the CLI that rewrites Claude Code project state when a project directory is moved, exported, or imported. Path rewriting stays inside word boundaries. Mutating commands take an exclusive flock and abort if a Claude Code session for the project is alive. Writes are atomic with rollback on failure.
Changes
Features
The CLI ships with five subcommands.
cc-port move <old> <new>rewrites every reference to the old path under~/.claude/to the new path. Default is dry-run.--applycopies, verifies, and deletes the old encoded directory.--refs-onlyupdates references in place, and--rewrite-transcriptsextends rewriting into session transcript bodies.cc-port export <project>produces a portable archive of one project. Categories include sessions, memory, history, file-history, config, todos, usage-data, plugins-data, and tasks. Use--all, individual category flags, or omit them all for an interactive picker.cc-port export manifest <project>emits the manifest XML alone for review or hand-editing. Refuses to overwrite an existing output path.cc-port import <archive> <target>applies an archive to a target path. Placeholder values come from--resolution KEY=VALUEflags or from a manifest via--from-manifest. Mixing the two sources is rejected.cc-port import manifest <archive>reads the metadata from an archive and writes a manifest XML with empty resolve attributes for hand-editing.
Beyond the subcommand surface, every mutating operation acquires an exclusive flock on ~/.claude/.cc-port.lock and aborts if any session JSON records a live PID. LocateProject cross-checks session files before rewriting, so two distinct paths that encode to the same directory (my project and my-project both map to my-project) surface as a conflict rather than splicing one project's data into another. Project paths resolve through symlinks before encoding, imports write sensitive files at 0o600, and --resolution accepts placeholder values from the command line for non-interactive runs. Interactive prompts run a TTY preflight. Piped invocations surface a clear error instead of hanging on stdin. Help output, version output, and the interactive picker render the project logo when stdout is a TTY.
Fixes
- Prefix-sharing paths no longer corrupt each other during rewrite. A project at
/work/foois left alone when porting/work/foobar. - Embedded paths inside
~/.claude.jsonproject blocks, session transcripts, session-memory files, and text file-history snapshots are all rewritten on move. - Encoded-directory collisions abort a move before any data is touched.
- A sentence-ending period no longer suppresses path rewrites in prose.
- Free-text history entries that reference the project path are included in the rewrite scope.
~/.claude.jsonkeeps its existing formatting through targetedsjsonedits rather than a full re-marshal.- Malformed
history.jsonllines surface with the offending line number. - Imports validate placeholders before any write and roll back on failure, so a broken archive can no longer leave partial state on disk.
Closeerrors from streaming pipelines and rollback paths are aggregated viaerrors.Joininstead of being dropped.- Importer staging lands on the resolved filesystem parent so a target on a different mount does not trigger
EXDEV.
Build / Release
- Homebrew cask published to the
it-bens/taptap. macOS users canbrew install it-bens/tap/cc-port. goreleaserproduces tarballs, checksums, and the cask artifact.- A top-level
Makefileexposesbuild,test,lint, andvulntargets.
CI
ci.ymlruns test, lint,govulncheck, and a build matrix on push.release.ymldrives thegoreleaserflow on tag push.
Documentation
- README covers install, every subcommand, the experimental warning, and known limitations.
docs/architecture.mdand the per-moduleREADME.mdandAGENTS.mdfiles document the cross-cutting policies, session-keyed registry, lock contract, import cap guards, and path-rewrite boundary rules.
Upgrade Notes
No breaking changes. This is the first public release.