Skip to content

Generation cache (content-addressed, no re-spend)

Generation is slow and paid (ElevenLabs, Gemini), so keryx caches by content: a generated take set — a VO line's takes, a music bed, a card's illustrations — is keyed by a hash of its request: the text / scene / prompt plus every setting that affects the output. Re-running a generation with unchanged inputs is a cache hit — the takes are materialised from the cache with no provider call and no spend (R-GEN-8 / R-GLOBAL-9). This is what makes per-line re-roll and re-runs of reel make cheap rather than a full re-spend.

Where it lives

The cache sits under the workspace's git-ignored, prune-able .cache/ dir, namespaced by kind and keyed by request hash:

.cache/vo/<hash>/1 2 3        a VO line's take set for one request
.cache/music/<hash>/1 …       a music bed's takes
.cache/cards/03/<hash>/1 …    card 3's illustration takes

Because the key is the content (not a filename or a timestamp), the cache even hits after you revert a text edit — the old request's takes are still there. keryx reel prune clears .cache/ (and the candidate takes/); it never touches the selected artefacts.

What's in the key

Everything that changes the output, so a change can't be masked by a stale take:

  • VO — text, voice id, stability / similarity / style / speed / speaker-boost, and the model, pronounce, ipa, and pronunciation-dictionary locators (R-GEN-31b: change the model or a dictionary and the cache invalidates). The --allow-unknown-model control flag is not in the key.
  • Music — the theme's music prompt and the bed length.
  • Cards / cover / portrait — the composed prompt, aspect, model, and each reference image's content. The take count is not in the key.

Semantics

  • --takes N variety is preserved — the cache stores the set of N candidate reads, so a hit replays the same N (synthesis is non-deterministic; the cache doesn't collapse them to one).
  • A re-run reuses (replaces) the set, it does not accumulatevoice gen twice on unchanged input leaves the same take set, not a doubled pile. To get fresh/different reads, change something or pass --force.
  • --force bypasses the cache: regenerate and refresh the cached entry.

See also: Workspace (the .cache/ + takes/ layout) and Providers (the paid backends the cache spares).