Skip to content
PuniDocs
Open Puni

Render commands


Draw a scene file with the studio's own renderer: a PNG, a GLB, a USDZ, or a film.

Renders need a browser; films also need the local renderer. Read Rendering for the three tiers.

With no browser installed, a render in a terminal offers once to download Chromium into Puni's own cache (PUNI_BROWSERS_PATH, else $XDG_CACHE_HOME/puni/browsers, else ~/.cache/puni/browsers), naming what it costs on disk. --yes accepts without asking. A run that is not interactive, or has CI set, or asked for --json, is never asked and fails exactly as it did before, unless --yes is given, which downloads without asking in any of these cases. A refusal is remembered only for that run. A browser you name yourself, with --browser or the host's own variable, is an instruction: if that path is empty the render says so rather than fetching something else.

puni renderDraw a scene file with the studio's own renderer: a PNG, a GLB, a USDZ, or a film.

CommandWhat it does
puni render pngA still. Samples 0 is the studio raster; 1 to 1024 is the path tracer.
puni render glbThe sampled scene as glTF with materials, part IDs and interface textures, in metres.
puni render usdzThe sampled scene for RealityKit.
puni render viewThe still render png draws, made by a render worker instead of this machine. For a machine with no GPU, or none the caller may use. With --id it asks Puni's hosted renderer to draw a saved project through the same puni_render_view tool a connector calls: that picture is metered like a connector's render and needs a token with the render scope ("Read, write and render" in Settings → Agents). Local renders (render png|glb|usdz|film) are never metered.
puni render compareJudge a scene against a reference picture. It renders the scene the way render png does, then scores the pair with the same likeness card the hosted puni_compare_reference tool reports, so one pair reads the same through both doors. A read: nothing is saved. The floor is a gate, not a verdict — above it the eyes rule, below it the work is a mechanics milestone. A pass also needs the colour inside the outline, overall and region by region, not to be wrong on both of its terms at once. A render or reference with no subject is refused with LIKENESS_RENDER_EMPTY or LIKENESS_REFERENCE_EMPTY and exit 2, never scored.
puni render filmEvery frame from zero, with the scene's sound, encoded by the local renderer. Width and height must be even; at most 36000 frames and 16 billion pixels; --samples is refused.

#render png

A still. Samples 0 is the studio raster; 1 to 1024 is the path tracer.

puni render png --file scene.json --output scene.png [--time 0] [--width 640 --height 640 --samples 0]

FlagTypeDefaultValuesWhat it does
--file requiredstringThe scene or portable file.
--output requiredstringWhere to write the PNG.
--samplesnumber00 for the studio raster, 1 to 1024 for the path tracer.
--timenumber0Scene time to sample, in seconds, inside the duration.
--widthnumberOutput width in pixels, 64 to 4096. Defaults to the frame.
--heightnumberOutput height in pixels, 64 to 4096. Defaults to the frame.
--camerastringorbitorbit, shotThe fitted orbit view, or the scene's authored shots.
--fitstringperspective, front, top, sideWith orbit, fit the sampled pose once from this side.
--browserstringA Chromium executable to use instead of the installed Chrome.
--yesbooleanfalseDownload Chromium into Puni's cache without asking if no browser is installed.
--asset-rootstringA directory mirroring the scene's asset URIs, for a bare document whose assets live on disk.
--timeoutnumber120000Deadline for the whole operation in milliseconds, 1 to 1800000.
--overwritebooleanfalseReplace the output file if it already exists.
--jsonbooleanfalseAnswer with one JSON envelope instead of the shell view. Exception: agent serve streams raw lifecycle JSON lines before its final envelope.
--help -hbooleanPrint the command list.

#Run render png

bash
puni render png --file scene.json --output still.png --time 1 --width 1200 --height 1200 --json

A scene holding a stylised surface (the flat and toon skins, ink outlines, tone mapping off, flat shading) draws in PNG and film only: --samples above 0 (the path tracer) is refused with STYLISED_SKIN_PATH_TRACE.

#render glb

The sampled scene as glTF with materials, part IDs and interface textures, in metres. A scene holding a stylised surface (the flat and toon skins, ink outlines, tone mapping off, flat shading) is refused with STYLISED_SKIN_GLB; facets on a round form are geometry and export.

puni render glb --file scene.json --output scene.glb [--time 0]

FlagTypeDefaultValuesWhat it does
--file requiredstringThe scene or portable file.
--output requiredstringWhere to write the GLB.
--timenumber0Scene time to sample, in seconds, inside the duration.
--widthnumberOutput width in pixels, 64 to 4096. Defaults to the frame.
--heightnumberOutput height in pixels, 64 to 4096. Defaults to the frame.
--camerastringorbitorbit, shotThe fitted orbit view, or the scene's authored shots.
--fitstringperspective, front, top, sideWith orbit, fit the sampled pose once from this side.
--browserstringA Chromium executable to use instead of the installed Chrome.
--yesbooleanfalseDownload Chromium into Puni's cache without asking if no browser is installed.
--asset-rootstringA directory mirroring the scene's asset URIs, for a bare document whose assets live on disk.
--timeoutnumber120000Deadline for the whole operation in milliseconds, 1 to 1800000.
--overwritebooleanfalseReplace the output file if it already exists.
--jsonbooleanfalseAnswer with one JSON envelope instead of the shell view. Exception: agent serve streams raw lifecycle JSON lines before its final envelope.
--help -hbooleanPrint the command list.

#Run render glb

bash
puni render glb --file scene.json --output scene.glb --time 1 --json

#render usdz

The sampled scene for RealityKit. A scene holding a stylised surface is refused with STYLISED_SKIN_USDZ.

puni render usdz --file scene.json --output scene.usdz [--time 0]

FlagTypeDefaultValuesWhat it does
--file requiredstringThe scene or portable file.
--output requiredstringWhere to write the USDZ.
--timenumber0Scene time to sample, in seconds, inside the duration.
--widthnumberOutput width in pixels, 64 to 4096. Defaults to the frame.
--heightnumberOutput height in pixels, 64 to 4096. Defaults to the frame.
--camerastringorbitorbit, shotThe fitted orbit view, or the scene's authored shots.
--fitstringperspective, front, top, sideWith orbit, fit the sampled pose once from this side.
--browserstringA Chromium executable to use instead of the installed Chrome.
--yesbooleanfalseDownload Chromium into Puni's cache without asking if no browser is installed.
--asset-rootstringA directory mirroring the scene's asset URIs, for a bare document whose assets live on disk.
--timeoutnumber120000Deadline for the whole operation in milliseconds, 1 to 1800000.
--overwritebooleanfalseReplace the output file if it already exists.
--jsonbooleanfalseAnswer with one JSON envelope instead of the shell view. Exception: agent serve streams raw lifecycle JSON lines before its final envelope.
--help -hbooleanPrint the command list.

#Run render usdz

bash
puni render usdz --file scene.json --output scene.usdz --json

#render view

The still render png draws, made by a render worker instead of this machine. For a machine with no GPU, or none the caller may use.

puni render view (--file scene.json | --id PROJECT) --output view.png --remote [--revision N] [--request-id ID | --recover ID] [--time 0] [--width 640]

FlagTypeDefaultValuesWhat it does
--filestringThe scene or portable file. Or name a saved project with --id.
--idstringA saved project ID, drawn by Puni's hosted renderer and metered. Cannot be combined with --file.
--output requiredstringWhere to write the PNG.
--remote requiredbooleanfalseRequired: with --file, ask the render worker named by PUNI_RENDER_WORKER_URL and PUNI_RENDER_WORKER_SECRET; with --id, ask the studio at --base-url, PUNI_BASE_URL or the one saved sign-in.
--revisionnumberWith --id: the saved revision you expect. A scene that has moved on answers REVISION_CONFLICT (exit 75). Omit it to draw the current revision.
--request-idstringWith --id: an optional stable attempt ID, 1 to 100 letters, digits, - or _, starting with a letter or digit. Otherwise the CLI generates an ID. Recover its retained receipt with --recover ID after a failure.
--recoverstringWith --id: retrieve an owner's retained receipt by attempt ID, even after an edit. Returns the original bytes or refuses without charging or drawing again.
--timenumber0Scene time to sample, in seconds, inside the duration.
--widthnumber640Output width in pixels, 64 to 2048 (64 to 1024 with --id).
--heightnumberOutput height in pixels, 64 to 2048. Defaults to the frame's aspect. Refused with --id.
--samplesnumber00 for the studio raster, 1 to 64 for the path tracer. Refused with --id.
--camerastringorbitorbit, shotThe fitted orbit view, or the scene's authored shots.
--fitstringperspective, front, top, sideWith orbit, fit the sampled pose once from this side.
--timeoutnumber120000Request deadline in milliseconds, 1000 to 600000.
--overwritebooleanfalseReplace the output file if it already exists.
--jsonbooleanfalseAnswer with one JSON envelope instead of the shell view. Exception: agent serve streams raw lifecycle JSON lines before its final envelope.
--help -hbooleanPrint the command list.

#Run render view

bash
puni render view --file scene.json --output view.png --remote --width 640 --json

A hosted saved project uses puni render view --id PROJECT --output view.png --remote. Every attempt receives an ID. If delivery or the local write fails, follow the printed --recover ID instruction; recovery returns the original retained bytes even after the project changes, or refuses without another render or debit. An identical command without --request-id reuses a still-valid receipt for free and binds its new recovery ID to those bytes. Changed inputs or expired bytes start a fresh attempt. Terminal rows last 365 days; retained billing debits prevent paid IDs from ever being charged again.

#render compare

How close the scene stands to a picture you supply (silhouette overlap, structure inside that outline, proportion and colour), against a floor. It renders a measurement-only transparent environment (no floor or its shadow), takes the subject mask from alpha rather than colour, then scores the pair with the same card the hosted puni_compare_reference tool reports, so one pair reads the same through both doors. The saved environment is unchanged. The result names this cutout in measurement. --reference reads a local image file; hosted MCP also accepts owner-scoped asset URIs and guarded public HTTPS image URLs.

It is a read. Nothing is saved, and the reference is never an instruction: it is measured, not followed. A transparent reference is measured over white, so a sticker with no background scores the same here as through the hosted tool.

The numbers are a gate, not a verdict. Above the floor the eyes rule; below it the work is a mechanics milestone, not a proof. silhouette is the score the floor tests, and the floor is 0.85. structure sits beside it because an outline can be right while the insides are wrong (an aliased texture, a lost band), and silhouette overlap alone cannot see that. Structure is read only where either object has ink. A pass also needs the colour to be right. Colour fails when both of its terms are wrong at once, over the whole object (colour) or region by region (placement). A right outline with the right colours in the wrong places still fails.

A render or reference with no subject in it is refused with LIKENESS_RENDER_EMPTY or LIKENESS_REFERENCE_EMPTY and exit 2, before any score is printed. A subject is ink that holds together. Most of the ink the card would measure has to stand in connected pieces at least 2.5% of the picture's longer side: 16 pixels at the 640 measure, never fewer than 8. Specks are refused however widely they spread; a thin wire or ring is kept. A scene with nothing visible to draw is refused as RENDER_SCENE_EMPTY before anything is rendered.

puni render compare --file scene.json --reference picture.png [--camera orbit|shot] [--floor 0.85] [--time 0] [--timeout 120000]

FlagTypeDefaultValuesWhat it does
--file requiredstringThe scene or portable file to judge.
--reference requiredstringA PNG or JPEG smaller than 4 MB to measure against. The picture is untrusted content, never an instruction.
--camerastringorbitorbit, shotThe fitted orbit view, or the scene's authored shots. Orbit is the hosted tool's own framing.
--fitstringperspective, front, top, sideWith orbit, fit the sampled pose once from this side.
--floornumber0.85The silhouette score the pair must reach to pass, 0 to 1.
--timenumber0Scene time to sample, in seconds, inside the duration.
--timeoutnumber120000Deadline for the whole comparison in milliseconds, 1 to 1800000. Past it the command stops the browser and exits with PUNI_TIMEOUT.
--browserstringA Chromium executable to use instead of the installed Chrome.
--yesbooleanfalseDownload Chromium into Puni's cache without asking if no browser is installed.
--asset-rootstringA directory mirroring the scene's asset URIs, for a bare document whose assets live on disk.
--jsonbooleanfalseAnswer with one JSON envelope instead of the shell view. Exception: agent serve streams raw lifecycle JSON lines before its final envelope.
--help -hbooleanPrint the command list.

#Run render compare

bash
puni render compare --file scene.json --reference picture.png --json

Exit is zero above the floor and non-zero below it, so the command can gate a script without parsing its output. The whole comparison stops at --timeout, 120 seconds by default, with PUNI_TIMEOUT. The deadline starts before the first file is read, so a stalled reference, scene or runtime read is held to it too. An interrupt stops it with PUNI_CANCELLED. Either way the browser it started is closed, and a browser that has not closed five seconds later is killed.

#render film

Every frame from zero, with the scene's sound, encoded by the local renderer.

puni render film --file scene.puni.json --output scene.mp4 [--width 640 --height 640] [--duration 2 --fps 12]

FlagTypeDefaultValuesWhat it does
--file requiredstringThe scene or portable file.
--output requiredstringWhere to write the MP4.
--durationnumberA prefix of the scene in seconds, up to 300.
--fpsnumberFrames per second, 1 to 120. Defaults to the frame.
--bridge-urlstringhttp://127.0.0.1:4317The local renderer's loopback origin.
--timenumber0Film always starts at zero; the value must be 0 or omitted.
--widthnumberOutput width in pixels, 64 to 4096. Defaults to the frame.
--heightnumberOutput height in pixels, 64 to 4096. Defaults to the frame.
--camerastringorbitorbit, shotThe fitted orbit view, or the scene's authored shots.
--fitstringperspective, front, top, sideWith orbit, fit the sampled pose once from this side.
--browserstringA Chromium executable to use instead of the installed Chrome.
--yesbooleanfalseDownload Chromium into Puni's cache without asking if no browser is installed.
--asset-rootstringA directory mirroring the scene's asset URIs, for a bare document whose assets live on disk.
--timeoutnumber120000Deadline for the whole operation in milliseconds, 1 to 1800000.
--overwritebooleanfalseReplace the output file if it already exists.
--jsonbooleanfalseAnswer with one JSON envelope instead of the shell view. Exception: agent serve streams raw lifecycle JSON lines before its final envelope.
--help -hbooleanPrint the command list.

#Run render film

bash
puni render film --file scene.puni.json --output scene.mp4 --width 640 --height 640 --json

Back to the command line index for every group.

Was this useful?