Library API

Hand edits and the in-browser editor

A hand edit never touches the generated file: it is a sibling under <outDir>/edits/ that the manifest points at with source (or sourceByStyle), so plan keeps the generation ok while packStyle, mountStyle, and exportTileset place the edit. startHandEdit and saveHandEdit are what pixelkiln edit and the gallery's editor call:

import {
  detachHandEdit,
  readHandEditCompanion,
  saveHandEdit,
  startHandEdit,
} from "pixelkiln"

const spec = specs.find((s) => s.styleId === "base" && s.assetId === "anvil")!
const started = await startHandEdit(loaded, lock, spec)   // copies, declares, idempotent
started.members                                           // one file, or one per member of a set
await saveHandEdit(loaded, lock, spec, {
  png: bytesFromYourEditor,                                // or frames: [{ role, png }] for a set
  project: pxoBytes,                                       // optional layered file kept beside it
  editor: "your-editor@1.0", protocol: 3,
})
await readHandEditCompanion(started.editPath)             // { version: 2, outputs: [{ role, basedOn, sha256 }], … }
await detachHandEdit(loaded, spec)                        // manifest only; the files stay

saveHandEdit validates every PNG, checks its size against the generated art, refuses a set whose members changed, replaces the files atomically, and writes the companion; startHandEdit and saveHandEdit take expectedSha256 so a stale caller is refused with ManifestDriftError when the manifest must change. handEditPath, handEditMembers, and sourceOutputPath give the file layout without writing anything.

The in-browser editor is a pinned Pixelorama build the package does not carry: EDITOR_PIN names its release and file hashes, editorStatus() says whether it is installed under editorDir(), and installEditor({ onProgress }) fetches and verifies only what is missing. createGalleryEditorHandlers() is the editor option serveGallery takes to report, install, and serve it; the page speaks the bridge protocol documented in tools/pixelorama-bridge/README.md.