Skip to content

keryx theme migrate

Description

Brings your theme catalog up to date, in three independent moves:

  1. out of the legacy ~/.keryx/config.yaml into ~/.keryx/themes.yaml (spec 0042 §3.6);
  2. your user library, out of the per-type shape into one flat list (spec 0047);
  3. the project's .keryx.yaml, the same flattening, when you run it inside a project.

The flattening covers fields as well as shape: a catalog can be structurally flat and still be writing prompt instead of style, or carrying an aspect the target now supplies.

Any of them may already be done. It reports only what it actually changes, and names the file each change lands in.

Usage

keryx theme migrate [--dry-run] [--default <keyword>]

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

Nothing moves until you ask

This is a command rather than something that happens on first run. Silently rewriting files you own, at a moment you did not choose, is the kind of surprise that erodes trust in every later write. keryx doctor tells you there is something to do and leaves the timing to you.

Look before you leap

$ keryx theme migrate --dry-run --default editorial
flattened to 13 theme(s), one list
default: editorial

merged (the same keyword under more than one type):
  blueprint    article + reel
  clay         article + reel
  editorial    article + reel

worth renaming — meaningless in a flat list:
  default

these styles still describe framing or aspect, which the target now
supplies. Left exactly as written — trim them by hand when you like:
  tattoo       16:9, banner, negative space, centred, no text
  emberlight   vertical, no text

nothing was written — re-run without --dry-run to apply

Three things worth reading there:

  • Merged — the same keyword filed under two types becomes one theme carrying both sides' fields. The article side's cover prompt and the reel side's music and voice both survive; nothing is discarded.
  • Worth renaming — a keyword like default made sense inside a portrait: block and means nothing in a flat list, especially sitting beside themes.default, which now means something else entirely.
  • Framing — the phrases are listed, not just the theme names, because nearly every style mentions something. tattoo 16:9, banner tells you what to delete; emberlight vertical is nearly clean already.

Nothing in your prose is edited. A tool that rewrites words you wrote is a tool you stop trusting with words.

What normalising a theme does

All of it is lossless:

Before After Why
prompt: … with no style style: … prompt is just the pre-0047 name. Renaming a key is not editing prose.
prompt identical to style prompt dropped A duplicate carries no information.
card.style identical to style card.style dropped Same. The aesthetic resolves from style.
aspect: "16:9" dropped 16:9 is the cover profile, so the key says nothing (D6).
aspect: "21:9" formats: {cover: {aspect: "21:9"}} A frame that differs is composition, and is preserved.

What it will not do is choose between a prompt and a style holding different text. That is two pieces of prose you wrote, and only one can survive:

these carry BOTH a `prompt` and a `style`, holding different text.
Only one can survive and the choice is yours — both were left in place;
delete the one you do not want with `keryx theme edit`:
  blueprint
  clay
  editorial

Both are left exactly as they are — style is what resolves — until you decide. Same line as the framing report below, for the same reason.

--default when your defaults disagree

Themes now have a single default rather than one per type. If your existing per-type defaults differ, migration stops rather than choosing for you:

$ keryx theme migrate
ERRO your per-type defaults differ (article=editorial, portrait=default,
     reel=editorial) and there is now a single default — re-run with
     `--default <keyword>` to choose which one applies to every target

The default decides what every un-themed generation produces, so picking one on your behalf would change output you never asked to change.

What it does and does not touch

  • Only themes move. Your config.yaml keeps its other job — ports, update policy, git behaviour — untouched.
  • A theme already in the library is left alone. One promoted from a project after the legacy copy was written is the newer version, and overwriting it with a stale duplicate would undo deliberate work.
  • The destination is written first, and the source cleared only once that succeeded — so a failure leaves a recoverable duplicate rather than nothing.
  • A project never gains a default it did not have. --default answers a conflict between your library's per-type defaults; writing it into a committed .keryx.yaml would force that theme on everyone working in the repo, and on CI.

You do have to run it

An unmigrated catalog no longer resolves. Every command that reads themes refuses a themes.<type>.<keyword> block by name, and points here:

$ keryx cover --scene "a lighthouse"
`themes.article` holds a block of themes, which is the pre-0047 layout — run `keryx theme migrate` to flatten it

That is a deliberate hard break rather than a deprecation. Reading both shapes is what let the typed and flat models run at once for a release, and four separate bugs came out of that one accommodation. Ignoring the old block instead would silently drop themes that exist in no other file — so keryx stops, and names the fix.

The legacy file move is different: ~/.keryx/config.yaml is still read as a lower-precedence layer, so themes living there resolve fine. That half is tidying; the flattening is not optional.

See also