Set up ComfyUI

Export an API-format workflow

For the tested SDXL environment graph, start from the bundled versioned recipe instead of copying node IDs by hand:

pixelkiln recipe install comfyui/pixel-art-xl-environment@1.0.0
pixelkiln recipe verify \
  pixelkiln-recipes/comfyui/pixel-art-xl-environment/1.0.0 \
  --model-root /path/to/ComfyUI/models

Installation prints the manifest style entry. The recipe pins the workflow and model hashes, records their licenses and source links, and labels the output as composition source. It does not download models or turn the result into finished pixel art. See Versioned recipes for its update and verification contract.

Build and test the workflow in ComfyUI first. Enable developer mode in ComfyUI settings, then use Save (API Format). Commit the exported JSON beside the manifest or in a project workflow directory. PixelKiln reads the file during planning and hashes its parsed JSON, so a node or model change marks dependent assets stale even if the filename stays the same.

The output node must expose an images array in ComfyUI history. A standard SaveImage node does this. Record these node IDs and input names from the exported JSON:

  • the positive text encoder's prompt input;
  • the latent image width, height, and batch-size inputs;
  • the sampler seed input, when the PixelKiln style declares a seed;
  • the source LoadImage input for a revision;
  • the mask LoadImage input for inpainting;
  • the sampler denoise/strength input when the asset declares strength;
  • any project-named inputs that should vary by asset, such as a pose image, ControlNet strength, reference image, or LoRA weight;
  • the final SaveImage node.

Node IDs are workflow-specific. Do not copy IDs from an example without checking the exported file.

Bind per-asset workflow inputs

Use one project-defined binding name in the style and the same key under each asset's providerInputs. This keeps a pose, composition guide, reference image, or strength with the asset instead of cloning nearly identical workflow files:

{
  "styles": {
    "character": {
      "generator": "map",
      "outDir": "assets/generated/characters",
      "providerOptions": {
        "comfyui": {
          "workflowFile": "workflows/pose-api.json",
          "outputNodeId": "9",
          "bindings": {
            "prompt": { "nodeId": "6", "input": "text" },
            "width": { "nodeId": "5", "input": "width" },
            "height": { "nodeId": "5", "input": "height" },
            "pose": { "nodeId": "19", "input": "image" },
            "poseStrength": { "nodeId": "20", "input": "strength" }
          }
        }
      }
    }
  },
  "assets": {
    "showcase-performer": {
      "prompt": "a stage performer mid-spin",
      "width": 832,
      "height": 1216,
      "providerInputs": {
        "pose": "controls/pole-spin.png",
        "poseStrength": 0.75
      }
    }
  }
}

PixelKiln recognizes a custom binding as an image input when it targets the image input of a core LoadImage or LoadImageMask node. Its value must be a manifest-relative PNG or JPEG. Planning reads and hashes the file without contacting ComfyUI. Submission checks the bytes again, uploads them under a content-addressed pixelkiln/ name, and refuses the job if the file changed in between. The lock records the hash and format, never the workstation path.

Other custom bindings accept strings, finite numbers, or booleans. Their type must match the primitive placeholder already stored at the target input in the committed workflow. PixelKiln rejects missing targets, duplicate targets, reserved built-in names, missing files, and unsupported image formats during offline resolution. ComfyUI performs the final graph and custom-node validation when /prompt is submitted. Keep providerInputs names stable: values are part of the asset spec hash, so changing one correctly makes that asset stale.