Skip to content

keryx media migrate

Description

Convert a workspace from the original path-keyed layout (spec 0039) to the content-addressed one (spec 0040) — blobs at blobs/<sha256>, with each file seeded at v1 in the version ledger.

A pre-0040 media.lock pins each file by path and store-side version_id. This command re-keys that content to its content-addressed blob and rewrites the manifest to {v, sha256, size}, seeding media.log with a v1 entry noting the migration. After it, media versions / media rollback work on the workspace, and the media is portable to any backend.

Safe by construction: content comes from the working copy only when its hash matches the manifest, otherwise it is re-fetched from the legacy key and hash-verified — never migrated blind. An entry whose content can't be resolved is reported, not fatal, so one missing object doesn't abort the run.

Non-destructive: legacy objects are left in place (keryx never deletes), so the change is reversible by reverting the manifest. Reclaim them later with a bucket lifecycle rule or media gc.

Idempotent: a second run reports everything already current.

Usage

keryx media migrate -w <slug> [--dry-run]
-w, --workspace The reel workspace slug (required).
--dry-run Report what would change and write nothing (neither store nor manifest). Run this first.

Run keryx media migrate --help for the authoritative, always-current flag set.

Output

media migrate (dry run): sandboxed-isnt-safe — 14 to migrate, 0 already current
Nothing written. Re-run without --dry-run to migrate.

media migrate: sandboxed-isnt-safe — 14 to migrate, 0 already current
media.lock re-pinned to content-addressed blobs and seeded at v1; commit to record it.
Legacy objects are left in place — reclaim them with a bucket lifecycle rule.

Unresolvable entries are listed with a ! marker. With --output json, the envelope carries {migrated, migrated_bytes, already_current, unresolved, dry_run}.

See also