cutan.characters.cli

User-facing character CLI subcommands.

Wired into the top-level an dispatcher via character_* dispatch-friendly functions in an.tools. Each function here takes plain strings/bools and returns a string for terminal display.

Subcommands (used as an character <verb> ...):

  • new — generate a fresh character from DiceBear or fallback art.

  • add-views — give an offline character its turnaround (an#197).

  • add-half-lid — a HALF eyelid drawing from the rig’s own lid art (cutan#65).

  • mouths — regenerate the 9-shape default mouth set.

  • validate — completeness check.

  • capabilities — what it affords, and per aspect which methods apply (an#248).

  • silhouette— rasterize silhouettes; for two characters, also IoU.

  • preview — open an HTML viewer cycling visemes + idle animation.

Module Attributes

SILHOUETTE_ARTIFACTS

Where silhouettes go, under the project the characters belong to (never a character's own folder: that folder is the published asset, an#272).

Functions

add_gaze(name[, out_dir, overwrite_eyes])

Give name the eye stack (an#99): sclera and pupil slots under each lid, a filled closed lid, and the gaze_travel clamp — so gaze_x / gaze_y and the ambient saccades move its pupils.

add_half_lid(name[, out_dir, fraction, ...])

Give name a HALF eyelid drawing (cutan#65), made from its own OPEN and CLOSED lid art: the closed lid cut to its top fraction, under the open eye's outline.

add_views(name[, out_dir])

Give name its turnaround (an#197): back, side and three-quarter head and torso art, a view swap set, and a pose per view — so play: turn and set <name> view <key> turn it.

capabilities(name[, out_dir, as_json, style])

What a character affords, and per aspect which methods apply and what the rest lack.

contract()

Print the art-package contract an illustrator must satisfy.

feet_origin(name[, out_dir, undo])

Make an existing character stand on its feet (an#285): its stage point (stage.at) becomes where its feet are, as for a character an character new makes now.

mouths(name[, out_dir, palette, variants])

Regenerate the default 9-shape mouth set for name, plus its viseme@<form> variants, and declare them in the descriptor.

new(name[, out_dir, seed, style, voice_ref, ...])

Create a new character at out_dir/name.

preview(name[, out_dir, open_browser])

Render a small HTML viewer that previews all visemes + idle animation.

record(name[, out_dir, output, duration, ...])

Record a character's preview HTML to mp4.

silhouette(name[, other, out_dir, output, size])

Render a black silhouette for name (and optionally compare to other).

validate(name[, out_dir])

Validate a character's directory structure and descriptor.

cutan.characters.cli.SILHOUETTE_ARTIFACTS: tuple[str, ...] = ('artifacts', 'silhouettes')

Where silhouettes go, under the project the characters belong to (never a character’s own folder: that folder is the published asset, an#272).

cutan.characters.cli.add_gaze(name, out_dir='', overwrite_eyes=False)[source]

Give name the eye stack (an#99): sclera and pupil slots under each lid, a filled closed lid, and the gaze_travel clamp — so gaze_x / gaze_y and the ambient saccades move its pupils. The expand step for a character made before Wave 6; idempotent on one that has it.

name: character id out_dir: parent directory; defaults to ./assets/characters overwrite_eyes: replace hand-drawn eye parts with the synthesized outline

and filled lid (refused otherwise — a promoted rig’s eyes are not the factory’s to redraw)

Return type:

str

cutan.characters.cli.add_half_lid(name, out_dir='', fraction=0.5, overwrite=False)[source]

Give name a HALF eyelid drawing (cutan#65), made from its own OPEN and CLOSED lid art: the closed lid cut to its top fraction, under the open eye’s outline. A partial lid (lid_open between -0.35 and -0.85: a squint, suspicion, annoyance) then narrows the eyes instead of showing them open.

name: character id out_dir: parent directory; defaults to ./assets/characters fraction: how much of the eye the half lid covers, from the top overwrite: replace a HALF lid someone drew (refused otherwise)

Return type:

str

cutan.characters.cli.add_views(name, out_dir='')[source]

Give name its turnaround (an#197): back, side and three-quarter head and torso art, a view swap set, and a pose per view — so play: turn and set <name> view <key> turn it. The expand step for an offline character made before views; idempotent. Refused for a DiceBear head or a hand-drawn rig, whose views are an illustrator’s to draw.

name: character id out_dir: parent directory; defaults to ./assets/characters

Return type:

str

cutan.characters.cli.capabilities(name, out_dir='', as_json=False, style='')[source]

What a character affords, and per aspect which methods apply and what the rest lack.

The affordances are derived from character.json and the art files present (ADR 0002 decision 2), with the declared overrides it used; per aspect (locomotion, speech, …) the method the default chain picks, the methods that apply, and for each other method the missing capabilities with the remedy that would add them. With style, each aspect also says what it resolves to under that style’s policy (cutan#9, an#273): a South Park character with legs bounces, a Reiniger silhouette mimes.

name: character id out_dir: parent directory; defaults to ./assets/characters as_json: print the answer as JSON (what the MCP surface returns) style: a style spec’s name (python -m cutan.styles lists them) or path

Return type:

str

cutan.characters.cli.contract()[source]

Print the art-package contract an illustrator must satisfy.

Derived from the schema and the validator, never hand-written, so it cannot drift from what an character validate actually enforces — a contract that disagrees with its checker is worse than none, because it gets a human paid for work that cannot land.

Return type:

str

cutan.characters.cli.feet_origin(name, out_dir='', undo=False)[source]

Make an existing character stand on its feet (an#285): its stage point (stage.at) becomes where its feet are, as for a character an character new makes now. Existing characters are never converted implicitly; this moves the character in scenes made before, and prints by how much.

name: character id out_dir: parent directory; defaults to ./assets/characters undo: go back to placing it by the middle of its bones

Return type:

str

cutan.characters.cli.mouths(name, out_dir='', palette='', variants='happy,sad')[source]

Regenerate the default 9-shape mouth set for name, plus its viseme@<form> variants, and declare them in the descriptor.

Useful when you want to reset a character’s mouth art to the offline fallback (e.g. after experimenting with hand-drawn mouths), or to give a pre-an#98 character the variant sets its expressions prefer.

name: character id out_dir: parent directory; defaults to ./assets/characters palette: optional JSON string to override colors, e.g. ‘{“lip”:”#a44”}’ variants: comma-separated mouth forms (see an character new); “” = none

Return type:

str

cutan.characters.cli.new(name, out_dir='', seed='', style='lorelei', voice_ref='', offline=False, acknowledge_attribution=False, overwrite=False, mouth_variants='happy,sad', palette='', build='regular', head_scale=1.0, hat='none', sash=False, views=True, hair_style='peak', hair_length='short', feet_origin=True)[source]

Create a new character at out_dir/name.

name: character id (used as the directory name and descriptor ‘name’) out_dir: parent directory; defaults to ./assets/characters seed: deterministic seed for DiceBear; defaults to name style: DiceBear style. The default is CC0 — no attribution duty. Some styles

are CC BY 4.0 and oblige whoever ships the video to credit the artist; those need –acknowledge-attribution. Run an credits <project> to see what a project owes.

voice_ref: voice id stored in the descriptor’s voice_ref field offline: skip DiceBear and use the deterministic geometric fallback acknowledge_attribution: accept the attribution duty of a CC BY style overwrite: replace an existing directory at the target mouth_variants: comma-separated mouth forms to draw as viseme@<form>

sets (an#98) — a form an expression preset prefers (happy, sad, angry, surprised, afraid, disgusted); “” for the neutral set only

palette: colours by StylePack role, “skin=#f1c9a5,clothing=#2e7d4f” (or a

JSON object); roles: skin, hair, clothing, leg, accessory

build: body proportions — regular, squat (round body, short legs), tall,

stick (small blocky body, stick limbs)

head_scale: the head and its whole face scaled together (1.0 = regular) hat: none, cap, beanie, bowler or bicorne (offline head only), in the

accessory colour, worn above the brows so expressions read (a hat that cannot clear them on a very small head is recorded, and an character capabilities says the brows cannot act)

hair_style: peak (the default), bald, bun or curly (offline head only),

in the hair colour

hair_length: short (the default), medium (to the jaw) or long (past the

chin) (offline head only); bald takes short

sash: a diagonal band across the torso, in the accessory colour views: draw the turnaround — back, side (a profile facing right) and

three_quarter beside the front, as a view swap set (offline head only), so play: turn can turn the character (an#197)

feet_origin: put the stage point at the feet (the rig’s root bone), so

stage.at is where the character stands and every build placed at one y stands on one floor line (an#285). On by default; –no-feet-origin places it by the middle of its bones, as characters made before were (convert one of those with an character feet-origin)

Return type:

str

cutan.characters.cli.preview(name, out_dir='', open_browser=False)[source]

Render a small HTML viewer that previews all visemes + idle animation.

The page includes the head SVG, cycles through mouth_a … mouth_x once a second, and shows a ±2 px sine-wave breath on the head. Useful for eyeballing a character’s mouth set before integrating into the main runtime.

name: character id out_dir: parent directory; defaults to ./assets/characters open_browser: also open the file in the default browser

Return type:

str

cutan.characters.cli.record(name, out_dir='', output='', duration=8.0, width=640, height=480)[source]

Record a character’s preview HTML to mp4.

Real video file showing the new SVG character art animating: cycles through all 9 visemes and applies the breath/head-tilt animation.

name: character id out_dir: parent directory; defaults to ./assets/characters output: output mp4 path; defaults to <character_dir>/preview.mp4 duration: recording length in seconds (default 8) width / height: video resolution (default 640x480)

Return type:

str

cutan.characters.cli.silhouette(name, other='', out_dir='', output='', size=512)[source]

Render a black silhouette for name (and optionally compare to other).

The silhouette is the figure as the stage draws it (build, head scale, hat: an#272), tinted black on white. When two names are given, prints both silhouettes’ paths and an IoU score (0..1; lower means more visually distinct). Nothing is written into a character’s folder, so a later an library publish never ships a silhouette.

name: character id other: optional second character to compare against out_dir: parent directory; defaults to ./assets/characters output: output PNG path (one name only); defaults to the project’s

artifacts/silhouettes/<name>.png

size: square output size in pixels (default 512)

Return type:

str

cutan.characters.cli.validate(name, out_dir='')[source]

Validate a character’s directory structure and descriptor.

name: character id out_dir: parent directory; defaults to ./assets/characters

Return type:

str