Guides

Recovery and account safety

Restore, generation history, cache, adopt, salvage, claims, and confirmed purge.

PixelKiln separates local file recovery, account reconciliation, unclaimed-work review, and irreversible deletion. A failed download never needs to become a new paid generation, and salvage never deletes by implication.

Restore missing output

pixelkiln restore
pixelkiln restore --style neon --only anvil

restore repairs a missing lock output from validated content-cache bytes or a durable provider reference. It does not submit generation and refuses to replace a file whose current bytes differ from the recorded hash; --force overrides that for a file changed after download, and the gallery's Restore button on an orphaned record does the same after asking.

A regeneration is not the end of the generation it replaces: the lock entry keeps it in history (up to PIXELKILN_HISTORY or the manifest's history, 5 by default), its bytes stay in the content cache, and its provider object was never deleted. pixelkiln history lists them and pixelkiln restore --only <asset> --generation <n|hash> brings one back at no cost, moving the current generation onto the list in its place.

Generation and download failures are separate lock states. A CDN failure after successful generation becomes download-failed; the next fetch or restore retries at zero generation cost.

Use the lock state rather than guessing which stage to rerun:

StateSafe next command
incomplete submission checkpointpixelkiln submit
complete pending or processing submissionpixelkiln poll
reviewpixelkiln pick
selected or download-failedpixelkiln fetch
downloaded output is missingpixelkiln restore

plan, doctor, and completed stages print these remaining actions. If a manifest change causes a deliberate regeneration, PixelKiln carries the old output hash until the replacement is fetched. An unchanged PixelKiln-owned file can then be replaced automatically. A hand-edited or untracked destination is still refused; after inspecting it, pixelkiln fetch --force explicitly lets the new result take ownership. This also recovers interrupted jobs created by older PixelKiln versions that could not retain the prior output hash.

ComfyUI frame sets submit one prompt per frame. PixelKiln saves the compound job after every accepted prompt, before asking ComfyUI to queue the next one. If submission stops halfway through, plan reports the saved checkpoint and pixelkiln submit continues at the first missing frame. poll will not advance an incomplete set into review. A changed prompt, workflow, input image, seed schedule, or other spec identity starts a fresh set instead of appending to old prompt ids.

Provider adapters should keep expiring signed result URLs transient and store a provider-neutral reference that can refresh them. Once ingestion succeeds, PixelKiln removes credential-bearing URLs, inline data URLs, and local file URLs from the lock entry. A failed download temporarily retains its source so a local retry remains possible; do not commit that in-flight lockfile.

Local caches

Two ignored caches accelerate recovery:

  • .pixelkiln/cache/<sha256>.png or <sha256>.gif: content-addressed, structurally validated generated media bytes;
  • pixelkiln.cache.json: provider object id → remote image hash.
pixelkiln cache
pixelkiln cache --check
pixelkiln cache --prune

Cache checks verify filenames/hashes and fully decode PNG chunks, checksums, palettes, scanlines, and decompressed size. Pruning removes corrupt/partial and unreferenced content plus malformed object-hash entries. Caches are disposable and should not be committed.

Adopt existing art

pixelkiln init --from assets/sprites --generator map
pixelkiln adopt --write-prompts

adopt hashes local files and provider objects, then maps exact matches into the lockfile. --write-prompts recovers the real upstream prompts. Retouched files remain untracked: provenance is unknown, but the art is not overwritten or automatically scheduled for paid regeneration.

The account object-hash cache avoids repeated full downloads. It is pruned for deleted remote ids only after adopt has seen the provider's complete object list.

Salvage unclaimed work

An account can contain paid objects that no current project lockfile claims. Inventory them before generating replacements:

pixelkiln salvage --claims ../other-project/pixelkiln.lock.json --dry-run
pixelkiln salvage --claims ../other-project/pixelkiln.lock.json

On shared accounts, supply every other project lockfile with repeatable --claims. Missing claim files are errors. PixelKiln loads sibling manifests where available to recognize another project's style patterns; incomplete claims could otherwise make shipped art look unowned.

Multi-style manifests group matching objects into one review session per style. Unmatched objects are listed separately. --style deliberately overrides grouping when a human wants to force one destination.

Review verdicts:

VerdictEffect
importDownload, add a manifest asset and lock entry, and recover its prompt.
keepAdd pixelkiln:keep upstream; no local change.
discardAdd pixelkiln:discard; does not delete.

--dry-run --all lists the full inventory. --dry-run --json writes the JSON array to stdout and human diagnostics to stderr for piping into jq.

Imported ids are derived from prompts and land under _salvaged/; review and rename them before treating them as stable application ids.

Characters

Characters are account records of their own, outside the object listing, and salvage reviews them too. A base and the states made from it share a group upstream, so each unclaimed group is one card: the base's south rotation, with a line counting its directions, states, and loops. A group is unclaimed when none of its characters is in any supplied lockfile. A group with some members claimed (a project uses the base, say, but not a state) is left out and reported, since discarding the rest would delete states of a character in use; declare those states and run pixelkiln adopt instead.

Groups go to the manifest's character styles, never to other styles: the only character style when there is one, otherwise the style whose prompt prefix or suffix the base's prompt carries. --style <character style> takes every unclaimed group. A manifest with no character style reports the groups and triages none of them. Account objects likewise never route to a character style, where an import would become a character base with nothing upstream.

VerdictEffect on a character group
importAdd a base asset, one asset per state, and one loop asset per animation direction to the manifest, each with a remoteId, then adopt them: every rotation and frame is downloaded and gets a lock entry.
keepAdd pixelkiln:keep to the base and every state.
discardAdd pixelkiln:discard to the base and every state; does not delete.

An imported base is named from the character's name, its states <base>_<state name>, and its loops <parent>.<animation>.<direction>. A loop PixelLab recorded without an animation group id cannot be adopted by remoteId and is left out, with a line saying so. A base whose size differs from the style's gets its own size; a 4-direction character imported into an 8-direction style keeps its four rotations.

Shared workspace catalog

For a single project, its own lockfile is the whole claim set. On a shared account with several sibling projects, repeating --claims on every salvage run is easy to get wrong. A forgotten lockfile makes another project's paid art look unclaimed. workspace fixes that by registering every sibling once, outside any one manifest:

pixelkiln workspace add ../other-game/pixelkiln.manifest.json
pixelkiln workspace add ../another-game/pixelkiln.manifest.json --name another
pixelkiln workspace status
pixelkiln workspace claims

workspace status reports each project's effective providers, spend-by-unit, and plan state offline. workspace claims validates the catalog and emits the exact union of provider-qualified objectId/reviewObjectId/jobId claims across every registered lock. Qualifying the IDs prevents two providers that reuse the same remote identifier from colliding. This is the same union rule --claims uses, so the two paths cannot drift.

A registered lockfile that is missing or unreadable is a hard error for claims, never a silent skip: an incomplete claim set is precisely what makes another project's shipped art look orphaned. workspace add still lets you register a brand-new project before its first gen. It warns rather than refusing because the project has no lock yet, but claims and salvage --workspace both refuse until every registered project has one.

Salvage accepts the catalog directly instead of a repeated --claims list:

pixelkiln salvage --workspace pixelkiln.workspace.json --dry-run
pixelkiln salvage --workspace pixelkiln.workspace.json

--claims still works and unions with a workspace's claim set. This helps a one-off lockfile that isn't part of the catalog. Choose one workflow per account: --claims for an occasional cross-project check, workspace once sibling projects are a standing arrangement worth registering once.

The catalog stores paths and project identity, never a credential. Each project still loads its own provider key from its own .env. workspace remove only edits the catalog file; it never touches art, a lock, or the provider account.

In a mixed-provider manifest, account-wide operations require an explicit backend: for example, salvage --provider retrodiffusion or adopt --provider pixellab. The selected operation only sees styles and lock entries for that provider. Restore does not need the flag because each lock entry already records where its work came from.

Confirmed purge

Deletion is a separate command:

pixelkiln purge --dry-run
pixelkiln purge
pixelkiln purge --yes

Only objects and characters already tagged pixelkiln:discard are eligible. The command lists targets, asks interactively, and refuses non-interactive deletion without --yes. A shared account should be fully adopted/salvaged before purge. A deleted character takes its animations with it; each state is its own record upstream, tagged and deleted on its own.

Accept intentional spec prose changes

pixelkiln accept --style base --only anvil

accept re-baselines an intact output against the current spec hash when prose changed but the existing pixels are intentionally retained. It does not modify art and skips missing or hash-mismatched files.

Derived output recovery

Pack, mount, and export bundles have a separate ownership and crash-recovery system based on .pixelkiln.json companions and transaction journals. See derived artifacts.

What to commit

Commit manifests, lockfiles, generated art, derived output used by the application, and its .pixelkiln.json companions. Do not commit credentials, .pixelkiln/, pixelkiln.cache.json, or short-lived transaction/stage/backup files. In the PixelKiln repository, npm run test:security rejects tracked JSON that contains a credential-bearing URL.