UtterPlan's command-line compiler accepts literal text, stdin, and files:
usage: utterplan compile [-h] [--file FILE] [--language LANGUAGE]
[--input-format {auto,text,plain,ssmd}]
[--text-preparation {auto,ssmd,spokenform,identity}]
[--spacy {auto,off,sm,md,lg,trf}] [-o OUTPUT]
[--trace TRACE] [--force] [--stdout]
[--renderability {strict,repair}]
[text ...]
--lang is an alias for --language; the older --format spelling is accepted
as an alias for --input-format. --language is a fallback language: it is
required for plain input, optional for SSMD with a header language, and never
forces a language over SSMD document semantics.
Compilation has no --unit or --pause-mode option. Schema v7 always stores paragraph-local flow units and canonical boundary_before / boundary_after opportunities (clause, sentence, paragraph, parenthetical, voice_change) separately from authored SSMD pause intents. One saved plan can support downstream sentence, paragraph, or renderer-token-budget chunking, and native, automatic, or manual pause realization. A FlowSegment is not necessarily a TTS call; its linguistic token views are not engine/model token counts.
render-plan accepts only the current schema-v7 .utterplan.toml file and a
RenderProfile TOML file. It does not re-prepare text, infer semantic boundaries,
call a renderer, or calculate backend model-token counts:
utterplan render-plan chapter.utterplan.toml \\
--profile voice.renderprofile.toml \\
--output chapter.renderplan.tomlReplanning requires both the exact previous RenderPlan and its matching preflight report. Only failed speech occurrences are refined; successful partitions remain:
utterplan render-plan chapter.utterplan.toml \\
--profile voice.renderprofile.toml \\
--previous chapter.renderplan.toml \\
--preflight chapter.preflight.toml \\
--output chapter.next.renderplan.toml \\
--explain--previous and --preflight must be supplied together. Existing output files
require --force. --explain formats the generated plan and replan decisions; it
does not invoke planning a second time. --json emits a versioned JSON wrapper to
stdout while the RenderPlan artifact remains TOML at --output.
Role coverage is validated before grouping or replanning. The selected profile must contain every explicit speech role and, when any speech omits a role reference, its default_role. Missing roles are reported together as renderplan.role.missing; extra profile roles are allowed. The check is renderer-independent and does not add role data to the RenderPlan schema.
Use source-only role inspection without loading a RenderProfile:
utterplan inspect chapter.utterplan.toml --rolesThe human render-plan summary reports required roles and coverage: complete. With --json, the versioned CLI wrapper includes a role_coverage object (default_role, required, available, missing, and uses_default_role) alongside, but outside, the RenderPlan payload.
The rules are deterministic:
--file FILEreads exactly that UTF-8 file and cannot be combined with positional text.- With no positional text or
--file, stdin is read. An empty terminal or empty stdin is an error. --input-format textand--input-format plaininterpret positional tokens as literal text.- Otherwise, one positional token naming an existing regular file is read.
- All remaining positional tokens are joined with single spaces as literal text.
With auto, .ssmd and .ssmd.md files are interpreted as SSMD. Markdown files
with an SSMD version header are also detected as SSMD; ordinary Markdown remains
plain text; literal text and stdin default to plain. Use --input-format ssmd
explicitly for SSMD from stdin or unversioned canonical fragments. All SSMD inputs
are parsed as strict dialect 0.9.
The SSMD header's language wins over --language. When the header declares a
language, no CLI language is needed. If it does not, provide --language as the
fallback; plain input always requires that option:
utterplan compile chapter.ssmd.md
utterplan compile legacy.ssmd.md --language de-DE
utterplan compile plain.txt --input-format plain --language de-DEUtterPlan accepts SSMD 0.9 syntax only. It does not auto-migrate older source or provide a legacy parser. Convert an old SSMD file before compilation:
ssmd migrate old.ssmd --to 0.9 --output migrated.ssmd
utterplan compile migrated.ssmd --lang en-usutterplan migrate handles serialized-plan migrations only; v6-to-v7 promotion returns migration.recompile_required instead of writing an incomplete current plan. It cannot migrate SSMD source.
Without --output, compile writes the pretty TOML plan to stdout. With
--output, the TOML file is written and an existing file is refused unless
--force is supplied. Add --stdout with an output path to write the file and
also emit the same TOML plan to stdout.
--trace PATH writes optional compiler provenance to a separate TOML sidecar. The trace is not embedded in, or hashed as part of, the executable plan. The plan itself stores exact raw source when available; keep and distribute the sidecar when preparation maps, diagnostics, renderability evidence, or source-coordinate mappings must be retained.
Human status messages are written to stderr, never mixed into TOML stdout:
utterplan compile chapter.ssmd.md -o chapter.utterplan.toml
# status is written to stderr
utterplan compile chapter.ssmd.md -o chapter.utterplan.toml --stdoutArgparse usage errors use exit code 2. Input, planning, file, and plan validation errors use exit code 1 and are reported without a traceback.
compile-many reads source files in the requested order, compiles each independently, and atomically saves each successful plan before reading the next. Ordinary input, planning, and write failures are reported per item and do not roll back earlier plans; processing continues unless --fail-fast is set.
utterplan compile-many chapters/*.ssmd --output-dir build/plans \
--language en-us --report build/compile-report.tomlSource names determine output names: chapter.ssmd, chapter.ssmd.md, and chapter.md each map to chapter.utterplan.toml. Duplicate output names and a report path that collides with a plan output are rejected before any writes. Existing plans are protected unless --force is supplied. By default the command writes an atomically refreshed compile-report.toml in the output directory; the report is operational TOML, not a plan accepted by FlowPlan.load().
Compile reports use format version 2. Each successful item records its resolved preparation_mode, diagnostic/severity counts, a complete structured diagnostics list, renderability_repair_count, and a degraded_linguistics boolean. For compatibility, repair_count and repairs remain; they include segmentation diagnostics (including informational ones) as well as renderability repairs, so they are not the terminal warning/repair summary. Diagnostic source ranges use original-input Python-character coordinates where available. Failed or skipped items have no preparation result. Reports remain operational metadata and do not affect plan output or incremental write behavior.
Shared planning options include --language, --input-format auto|plain|ssmd, --text-preparation, --spacy, and --renderability. --diagnostics warnings|all|none controls terminal detail (default warnings): warnings mode suppresses informational diagnostics, all includes them, and none suppresses non-failure diagnostics. Failures are always reported, and the operational report always retains complete diagnostics. Progress, selected diagnostic details, actionable errors, and final counts are written to stderr. Exit status is 0 if every input succeeds, 1 if any input fails, and 2 for usage errors such as output collisions. --fail-fast skips later requests after the first failure but preserves all completed outputs and updates the report.
The bundle command is the only workspace entry point. It requires the canonical <name>.ssmd-bundle/ directory and dispatches from manifest.json; chapter directories and document files are not accepted as alternate roots. Supported manifest kinds are book (ssmdconvert.book, schema 1) and document (ssmdconvert.document, schema 1).
utterplan bundle compile BUNDLE [--chapters SELECTOR]
[--output-dir PATH] [--language LANGUAGE]
[--text-preparation {auto,ssmd,spokenform,identity}]
[--renderability {strict,repair}] [--spacy {auto,off,sm,md,lg,trf}]
[--force] [--fail-fast] [--report PATH]
[--diagnostics {warnings,all,none}]
utterplan bundle render BUNDLE --profile PROFILE [--chapters SELECTOR]
[--utterplan-dir PATH] [--output-root PATH] [--variant LABEL]
[--force] [--fail-fast] [--report PATH]
utterplan bundle replan BUNDLE --variant VARIANT [--chapters SELECTOR]
[--renderplan-root PATH] [--voicerender-root PATH] [--report PATH]
[--dry-run] [--fail-fast] [--explain] [--json]
BUNDLE must be a .ssmd-bundle/ root. --chapters defaults to all. Book selection uses manifest source_number values and accepts one number, an inclusive range, or comma-separated combinations such as 1,3-5,9; selected items retain manifest order. Document bundles support only --chapters all. Source paths are validated against the bundle root, and symlinks or path escapes are rejected.
Compilation writes one schema-v7 FlowPlan per selected item and an operational compile-report.toml under <bundle>/utterplan/ by default. Rendering reads those saved plans and requires an explicit RenderProfile; it writes profile-fingerprinted RenderPlans, a profile snapshot, and an operational report (book bundles also maintain a set index) under <bundle>/renderplan/. Replanning refines active plans from matching VoiceRender preflight feedback and updates only the selected active entries. These commands never mutate the manifest or source documents. render-plan remains the low-level one-file projection/replan command.
The diagnostics option controls compile terminal verbosity; failures are always reported and complete diagnostics remain in the operational report. --fail-fast skips later selected items after a failure. --force replaces selected plan artifacts but does not bypass unsafe paths, metadata collisions, or profile-identity checks. Exit status is 0 when all selected work succeeds, 1 when an item fails, and 2 for usage or shared-configuration errors. See the bundle guide for layouts, safety behavior, and Python examples.
Explain an existing compiled plan as a human-readable speech narrative:
utterplan explain chapter.utterplan.toml
utterplan explain chapter.utterplan.toml --detailsThe explanation presents executable flow: prepared segment text, paragraph-local unit order, effective languages, canonical boundary opportunities, authored pause intents, headings, markers, and typed directives. The v7 plan retains exact raw source when available and compact replacement views show local prepared surfaces with original spellings. Complete compiler source diagnostics and preparation maps remain absent unless a trace sidecar was saved. Add --details for local token offsets, flow hashes, plan identity, and trace preparation mappings. Pass --trace PATH to attach a matching sidecar; the TOML trace can also be read independently with inspect-trace.
preview projects chunk text and pause facts from a saved schema-v7 plan. It does not recompile the source, call linguistics providers, modify the plan, or cross into G2P/rendering:
utterplan preview chapter.utterplan.toml \
--segments 58-62 \
--chunk-by clause \
--pause-policy automatic--segments accepts zero-based global flow-segment indexes: N, N-M, comma-separated combinations, or all. It is a focus selector: grouping is performed for the full plan first, so selecting one segment returns its complete containing chunk. --chunk-by is segment, clause, sentence (default), or paragraph; clause grouping closes on clause, sentence, and paragraph opportunities. Chunk text is the exact concatenation of stored segment.text values, including spaces at chunk edges.
--pause-policy native (default) shows authored pause intent but does not materialize ordinary boundary opportunities. automatic exposes saved clause/sentence/paragraph opportunities without inventing durations. manual displays authored pause intent and the automatic opportunity separately. These policies affect preview projection only; the saved plan and its identity remain unchanged. Use --details to show constituent segments, local spans, directives, and boundary facts, or --json for the versioned machine-readable preview object.
inspect reads canonical plans. Persistable planning outcomes use the separate
utterplan.planning-attempt.v1 artifact and are opened with inspect-attempt:
utterplan inspect-attempt chapter.attempt.toml
utterplan inspect-attempt chapter.attempt.toml --issues
utterplan inspect-attempt chapter.attempt.toml --segment seg-000001 --unit unit-000001
utterplan inspect-attempt chapter.attempt.toml --jsonThe default view summarizes status, renderability, and candidate size. --issues
shows source context and conservative repair assessments; segment and unit selectors
accept an ID or zero-based index. --json emits the complete artifact as JSON for
inspection, but the persisted attempt itself remains TOML. A blocked candidate is an
inspect-only draft, not a canonical plan, and is rejected by FlowPlan.load().
--text-preparation auto|ssmd|spokenform|identitychooses written-to-spoken handling.--spacy off|auto|sm|md|lg|trfselects deterministic fallback, automatic spaCy use, or a required model tier.--renderability repair|strictdefaults to safe punctuation-only repair. Semantic blockers remain failures with source context and an actionable next step; strict mode reports safe repair opportunities without applying them.
The default spaCy policy is auto: inspect only already-installed compatible local models in sm, md, lg, trf preference order. If spaCy or every compatible model is unavailable, compilation continues with deterministic fallback; no model is downloaded.
The defaults are --text-preparation auto and --spacy auto. Preparation auto selects authoritative ssmd for SSMD input and TTSReady/Spokenform for plain text; explicit spokenform on SSMD is a warned legacy mode. SpaCy auto uses a compatible local model when available and otherwise falls back safely. Compilation does not select renderer chunking or pause realization: schema-v7 boundaries and authored pause intents are realized downstream.
Use --spacy off to force deterministic fallback. --spacy sm|md|lg|trf requires that local model tier and fails if it is unavailable. Token columns in v7 carry final prepared-text linguistic context, not model-token counts; the optional replacement fields describe local output spans, not source coordinates. Preserve the trace sidecar for full source maps and preparation diagnostics.
utterplan --version
utterplan validate chapter.utterplan.toml
utterplan validate chapter.ssmd.md
utterplan validate plain.txt --input-format plain --language en-us
utterplan inspect chapter.utterplan.toml --segment 0
utterplan inspect chapter.utterplan.toml --unit 0 --boundaries --tokens
utterplan compile chapter.ssmd.md -o chapter.utterplan.toml --trace chapter.trace.toml
utterplan explain chapter.utterplan.toml --trace chapter.trace.toml
utterplan inspect-trace chapter.trace.toml --preparation --boundaries
utterplan inspect-attempt chapter.attempt.toml --issues
utterplan preview chapter.utterplan.toml --segments 58-62 --chunk-by clause --pause-policy automaticinspect --unit selects a stored flow unit for inspection; it does not choose compilation grouping. Compilation always writes paragraph-local flow blocks, and downstream renderers choose their own chunk boundaries from the saved boundary opportunities.
inspect-trace --preparation reports source/prepared text lengths, maps, preparation changes, and repair/diagnostic evidence from the optional trace. inspect-trace --boundaries shows compiler-only boundary events and semantic candidates. These fields are intentionally absent from the executable plan TOML.
Use utterplan migrate to inspect sequential data-only migrations for legacy saved plans. Schema-v6 files cannot prove the complete v7 boundary inventory, so promotion intentionally fails with migration.recompile_required; recompiling the original source is the supported route to a current plan.
utterplan migrate old.utterplan.json --check
utterplan compile source.ssmd.md -o current.utterplan.tomlWhen a migration is available, -o writes TOML to that path, while stdout and status messages remain separated; an existing output requires --force. --check reports source and target schema without writing. A historical plan that reaches schema v6 is rejected with migration.recompile_required because boundary opportunities cannot be recovered from serialized data; the CLI never silently reparses or replans. Future schema versions are rejected rather than guessed or downgraded.
Schema migration is separate from SSMD source migration. Frozen JSON schemas v1–v4 and saved schema-v5 TOML use the registered sequential path through schema v6; v6-to-v7 conversion reports migration.recompile_required rather than fabricating boundaries. These migrations do not rerun parsing, text preparation, NLP, or planning; the v5-to-v6 step preserves compiled flow and leaves unavailable source provenance absent. The v4-to-v5 projection refuses ambiguous token coordinates or pause meanings rather than guessing. Use ssmd migrate FILE --to 0.9 for older SSMD source documents.
For a saved TOML plan, validate verifies the current semantic schema and plan
invariants; JSON plan paths are rejected outside migrate. For an SSMD or
plain-text source document, it runs the canonical one-document semantic compiler
without writing a plan; plain input requires --language, while SSMD can use its
header language or an explicit fallback.