Under the hood

How a chat with Claude on a Mac turned into 1,044 illustrated scenes, Genesis, Exodus, Joshua, Judges, Ruth, 1 and 2 Samuel, 1 and 2 Kings, 1 and 2 Chronicles, Ezra, Nehemiah, Esther, the four Gospels and the Acts of the Apostles, plus a short film of Paul's letter to Philemon, rendered on a box on my desk. Everything here is in the GitHub repo, including the raw numbers.

The run, by the numbers

Nineteen books so far. Pick any two to compare side by side. It opens on the easiest book and the hardest, measured by how many attempts it took to get each published image.

Attempts per published image, every book

    Show the full table for all nineteen books
    GenesisExodusJoshuaJudgesRuth1 Samuel2 Samuel1 Kings2 Kings1 Chronicles2 ChroniclesEzraNehemiahEstherMatthewMarkLukeJohnActs
    Test conditionsBox doing nothing else; run overnight with no one watchingImage agents one job at a time; two scenes redone at the endImage agents one job at a time; one more pass on 10:16 at the endImage agents one job at a time; two scenes redone at the endImage agents one job at a time; box otherwise quietOne session with 2 Samuel; three rounds of fixes after Brian's reviewOne session with 1 SamuelBox doing nothing elseBox doing nothing elseImage agents one job at a time; other coding agents on the box for the first half hourOne session with 1 ChroniclesImage agents one job at a time; box otherwise quietImage agents one job at a time; box otherwise quietImage agents one job at a time; box otherwise quietBox doing nothing else, checked clean before the runThree AI coding agents running on the box at the same timeBox doing nothing else, fresh rebootBox doing nothing elseBox doing nothing else
    Chapters5040242143124222529361013102816242128
    Scenes897747528413737364346192017111751038898
    New cast portraits11 (Adam to Joseph)7 (Moses at two ages, Aaron at two, Miriam, Pharaoh, young Joshua)5 (Joshua at two ages, Rahab, Caleb, Eleazar)5 (Deborah, Gideon, Jephthah, Samson, Delilah)3 (Ruth, Naomi, Boaz)9 (David at four ages, Samuel, Saul, Jonathan, the ark, Goliath)2 (Joab, Absalom)7 (Solomon at two ages, Jeroboam, Ahab, Jezebel, Elijah, Elisha)4 (Elisha old, Jehu, Hezekiah, Josiah)1 (Asaph)3 (Rehoboam, Asa, Jehoshaphat)3 (Ezra, Zerubbabel, Jeshua)1 (Nehemiah)4 (Esther, Mordecai, Haman, Ahasuerus)1 (Joseph)2 (Peter, Mary Magdalene)1 (Mary, mother of Jesus)2 (Jesus, John the Baptist)6 (Paul, John, Stephen, Barnabas, Silas, Philip)
    Attempts (generations + edits)153 (129 + 24)266 (188 + 78)162 (106 + 56)205 (134 + 71)31 (21 + 10)140 (87 + 53)98 (56 + 42)96 (63 + 33)80 (49 + 31)151 (98 + 53)166 (106 + 60)68 (38 + 30)65 (37 + 28)71 (42 + 29)217 (163 + 54)189 (160 + 29)254 (194 + 60)168 (121 + 47)234 (162 + 72)
    Attempts per published image1.533.453.453.943.882.802.512.182.223.513.613.583.254.181.942.452.441.872.25
    Kept on the first try57 of 898 of 777 of 476 of 520 of 88 of 417 of 376 of 378 of 362 of 431 of 462 of 193 of 200 of 1738 of 11110 of 7520 of 103about half13 of 98
    GPU time53 min100 min68 min80 min12 min68 min51 min41 min34 min62 min67 min30 min28 min30 min91 min99 min108 min68 min115 min
    GPU busy during the session69%65%54%52%60%54% (shared session)76%79%56% (shared session)62%59%62%58%57%57%44%63%
    Median klein + reference job16.7 s17.2 s17.6 s16.5 s15.9 s16.8 s16.9 s16.8 s16.2 s16.7 s16.6 s16.0 s17.1 s16.0 s16.7 s21.7 s16.8 s15.7 s16.8 s
    Median edit56.5 s43.2 s43.1 s42.8 s42.3 s55.7 s55.1 s40.5 s39.2 s42.5 s42.7 s41.9 s42.0 s42.2 s57.0 s91.9 s57.0 s52.5 s57.0 s

    Why the numbers differ

    One cast for the Gospels

    Matthew, Mark, Luke and Acts reused John's portraits, so the New Testament shares one cast. Each Old Testament book brought its own.

    Mark: a busy box

    Mark ran while a separate workflow had three AI coding agents working on the same machine. Its median edit took 92 seconds instead of 57.

    Luke and Matthew: quiet again

    On a quiet, freshly rebooted box, Luke's per-job times came back almost to John's, the clearest sign the agents slowed Mark. Matthew matched Luke almost to the tenth of a second.

    Zooming in costs attempts

    From Mark on, every image was checked region by region, which catches small things a full-frame look misses. That is most of why later books took more tries than John.

    Acts: crowds and furniture

    Same per-job times as Luke and Matthew, but more attempts: more crowds, Roman rooms full of modern furniture, and six new faces to keep straight.

    Genesis: the easiest

    Run overnight with no one watching, and the fewest attempts of any book. Much of it is sky, sea and animals, and every prompt started from the lessons of the books before it.

    Samuel: aging and reviews

    David had to age across four portraits, the ark needed its own reference and a rule that nobody touches it, and three rounds of Brian's review caught what the first pass let through.

    Chronicles: the hardest so far

    About three and a half attempts per image. The genealogies needed a picture for every chapter of names, the model could not count seven sons or two oxen, and the temple musicians came out with valved trumpets, lyres played with bows, and snare drums on stands.

    Exodus: the sapphire and the door

    The sapphire pavement of 24:10 came out as a wireframe grid, a plastic slab and a row of solar panels. The Passover door took fourteen tries: the model kept adding horror-film drips, a mushroom cloud, an electric light, a potted plant and a tornado.

    Judges: chariots and jawbones

    Four tries at Sisera's chariots drew boats, carriages and covered wagons, so the picture has horses in the rain instead. Samson's jawbone came out as a giant fanged arc, a tusk and a pickaxe before a bone the length of a forearm.

    Joshua: battles

    The first book allowed to show fighting, with some blood. Edits that removed a modern town from behind a battle often took the army or the flames with it, and in eight generations the model never put a captain's foot on a king's neck. An edit did it in the end.

    Kings: chariots and castles

    1 Kings fought glass jars, ceiling lights and a model that cannot draw a chariot. In 2 Kings every distant city came out as a medieval castle or a modern town.

    Per-job data

    Genesis CSV / summary, 1 and 2 Samuel CSV / summary, 1 Kings CSV / summary, 2 Kings CSV / summary, 1 and 2 Chronicles CSV / summary, Ezra CSV / summary, Nehemiah CSV / summary, Esther CSV / summary, Exodus CSV / summary, Joshua CSV / summary, Judges CSV / summary, Ruth CSV / summary, Matthew CSV / summary, Mark CSV / summary, Luke CSV / summary, Acts CSV / summary.

    Housekeeping on the box

    Before Luke, the Halo was rebooted to clear dozens of orphaned Chromium processes. Those didn't reappear during the Luke run, but a python3 process belonging to ComfyUI stayed resident after ComfyUI was closed properly, holding about 2.4 GB of memory. A full restart is needed to get the machine back to a clean state before the next run. Before Matthew the box was checked again and came back clean: only ComfyUI running, no language model loaded, 0.5 GiB of GPU memory in use.

    John in detail

    168

    generations and edits for 90 published images (1.87 each)

    68 min

    of GPU time for the whole book, about 45 s per published image

    27 ×

    each model was reloaded, from switching between generating and editing

    44%

    of the active session the GPU was busy. The rest was prompting and review.

    0.18 kWh

    for the book, about 3 cents of electricity at $0.15/kWh

    $7 to $32

    for the same 240 calls on cloud image APIs (estimate)

    Every job came from ComfyUI's own history: comfy_history.csv. The scripts that produced these numbers are in scripts/, and every image with its prompt is on the Making of page.

    Philemon: a short film

    Philemon is one chapter, so it became a three-minute film instead of a picture book. The narration is the clock: every shot is timed to its verses, and the player moves the camera itself. Most shots are video clips made with LTX-2.5 from a still keyframe; the rest are stills with depth parallax, built from a depth map made on the Mac. A lyre score made with ACE-Step 1.5 runs under the voice and dips under the narration. Watch it here.

    Shots37: 26 video, 9 depth parallax, 1 pan, 1 still
    Length3 min 12 s (narration 3 min 7 s, then a silent epilogue)
    New cast portraits13: Paul about ten years older than in Acts, Onesimus, Timothy, a guard, Philemon, Apphia, Archippus, Tychicus, Epaphras, Mark, Aristarchus, Demas, Luke
    Still attempts (generations + edits)225 (134 + 91) for the keyframes, portraits, character sheets and location plates
    Video renders52 logged, 12 of them first-and-last-frame
    GPU time164 min for stills, about 504 min for video, 16 min for music
    Median klein + reference job52.8 s (keyframes at 3.7 MP, against about 1 MP in the books)
    Median edit40.3 s
    One video clip, draft quality (960 wide)5 s: about 3.5 min. 7 s: about 7.5 min. 11 s: about 20 min
    First-and-last-frame clip5 s: about 10 min. 7 s: about 21 min. 10 s: about 48 min
    Published film28 MB: video at 960x544, stills 2048 wide, depth maps, one music track

    Video time grows faster than clip length, so long clips were the expensive part. ComfyUI lost its job history in two restarts during the video work, so the video numbers come from the render logs. Per-job data: CSV / summary.

    The pieces

    Claude calls a tool like halo_generate_image. The MCP server fills in a ComfyUI workflow, queues it, polls until the image is done, saves the PNG on the Mac and hands a preview back into the chat. ComfyUI only listens on the Halo's localhost. The Mac reaches it through an SSH connection that launchd opens on demand, so nothing is exposed on the network. Setup steps are in setup/.

    The MCP tools

    halo_generate_image

    Text to image. Pick a model or take the default. Pass a reference_image to put the same face in a new scene, or a trained lora.

    halo_edit_image

    Plain-language edits with Qwen-Image-Edit. With no path it edits the last image, so fixes chain naturally.

    halo_list_models

    What's installed, each model's tuned defaults, and what it can do.

    halo_train_lora

    Uploads a folder of photos and trains a LoRA with ComfyUI's built-in trainer, with status and cancel tools alongside.

    Code: mcp-server/ · workflows/ · scripts/ · viewer/ · setup/

    The box

    APUAMD Ryzen AI Max+ 395 ("Strix Halo"): 16 Zen 5 cores / 32 threads, up to 5.19 GHz, 64 MB L3
    GPURadeon 8060S, RDNA 3.5 (gfx1151), 40 CUs, up to 2.9 GHz
    NPUXDNA 2 (not used here)
    Memory128 GB LPDDR5X shared: 512 MB VRAM carve-out, 94 GiB GPU-addressable via GTT
    PowerAMD spec 55 W default, 45 to 120 W configurable. Measured: 30.6 W idle, about 156 W sustained under load
    OSAMD Ryzen AI Developer Platform 1, kernel 6.18
    ROCm7.14
    PyTorch2.12.0+rocm7.14.1 (HIP 7.14.60850)
    ComfyUI0.21.1 in a rootless Podman container, socket-activated
    Disk2 TB Micron 4600 NVMe

    The models

    Used forModelPrecisionSizeSteps
    Scenes and portraitsFLUX.2 [klein] 4B (distilled) + Qwen3 4B text encoder + FLUX.2 VAEBF1616.1 GB4
    Keeping faces consistentSame, with a ReferenceLatent built from a cast portraitBF164
    Fixes and touch-upsQwen-Image-Edit 2511 + Qwen2.5-VL 7B + Lightning 4-step LoRAFP8 (compute in BF16)31.0 GB4
    Video (Philemon)LTX-2.5 22B distilled + Gemma 4 12B text encoder + video VAE + 2x latent upscalerINT8 (VAEs in BF16)39 GB8 + 3
    Depth for parallax (Philemon)Depth Anything V2 Large, on the MacFP321.3 GB1
    Music (Philemon)ACE-Step 1.5 turbo (all in one)BF1610.0 GB8

    The book's model set is 47.2 GB on disk. A 20B-parameter edit model on an integrated GPU works because the GPU borrows system memory: peak usage was 27 GB for klein and 38 GB for the edit stack.

    Benchmark

    Fixed seeds, 1 Hz power and temperature sampling on the box. Energy is APU socket energy, not wall plug. benchmark.csv · raw samples

    JobTimeAvg powerEnergy / imagePeak GPU memory
    FLUX.2 klein, 1344×768, warm8.6 s119 W0.28 Wh27 GB
    FLUX.2 klein, first run after unloading12.7 s98 W0.35 Wh27 GB
    klein + reference image, warm15.7 s130 W0.57 Wh27 GB
    Qwen-Image-Edit, warm31.9 s133 W1.18 Wh38 GB
    Qwen-Image-Edit, right after a klein job54.3 s116 W1.75 Wh38 GB
    Qwen-Image 2512, 1328×1328, warm22.3 s135 W0.84 Wh64 GB

    Under load the package holds a ceiling of about 156 W. The GPU edge sensor hit 100 °C on back-to-back Qwen runs, but the shader clock only dropped 0.8%, so it's power-limited rather than throttling.