The StoryMatrix CLI answers which commands and options control story generation, configuration, voices, and runtime modes.
🚀 generate
storymatrix generate loads YAML and environment configuration, layers explicitly supplied CLI values over it, validates a GenerateStoryRequest, and runs the asynchronous use case.
| Option | Type | Default | Effect |
|---|---|---|---|
--prompt, -p | str | None | None | Story prompt; required by GenerateStoryRequest. The CLI’s missing-prompt guard is bypassed when --story-md is supplied, but a story-md-only invocation still fails Pydantic validation because the request DTO requires prompt. |
--config | Path | None | None | Existing YAML file merged into the request and configuration. |
--title, -t | str | None | None | Story title. |
--genre, -g | str | None | None | Story genre. |
--style, -s | str | None | None | Writing style. |
--language, --lang, -l | str | None | None | Story language. |
--structure | str | None | None | Story structure archetype; maps to structure_type. |
--character, -c | list[str] | None | None | Repeatable character values. |
--num-scenes, --scenes | int | None | None | Target scene count. |
--story-md | Path | None | None | Accepted by the parser and used only to bypass the missing-prompt guard; the DTO carries story_md for use-case consumption, but the CLI never reads the file, and a story-md-only invocation fails Pydantic validation because GenerateStoryRequest still requires prompt. |
--voice-id | str | None | None | Default TTS voice identifier. |
--output, -o | Path | None | None | Output path, passed through the request’s output alias. |
--fast-dev-run | bool | False | Requests mock services for a fast run. |
--min-similarity-score | float | None | None | Accepted by Typer, but GenerateStoryRequest has no matching field, so the value is ignored after request construction. Use global --min-similarity to write the environment override instead. |
--keep-temp-files/--no-keep-temp-files | bool | None | None | Preserve or remove temporary files. |
--resume/--no-resume | bool | None | None | Resume from the last successful checkpoint. |
--low-resource/--no-low-resource | bool | False | Writes APP__LOW_RESOURCE_MODE=true before configuration loading when enabled. |
--max-tts-concurrency | int | None | None | For a positive value, writes APP__MAX_TTS_CONCURRENCY before configuration loading. |
--sfx/--no-sfx | bool | True | Enable or disable sound effects. |
--background-music/--no-background-music | bool | False | Enable or disable background music. |
--ambient-sounds/--no-ambient-sounds | bool | True | Enable or disable ambient sounds. |
--max-tokens | int | None | None | Maximum LLM generation tokens. |
Explicit command options are collected from Typer’s context and layered over YAML values before GenerateStoryRequest validation. The command’s --low-resource and --max-tts-concurrency write environment variables before load_config(), but those writes are not authoritative when YAML supplies the same settings: load_config() deep-merges YAML over the defaults-plus-environment mapping.
🚧 Offline and low-resource flags (B15)
--offline writes APP__DEV_LOCAL_ONLY=true, and --low-resource writes APP__LOW_RESOURCE_MODE=true into os.environ before load_config() (src/storymatrix/cli/main.py). The behavior is split: container branches that read os.environ directly honor those writes, while branches that inspect the loaded config object can lose them. load_config() first gets defaults and environment values through StoryMatrixConfig(), then deep-merges YAML over that mapping; only SERVICES__LLM__OPEN_ROUTER__TIMEOUT is reapplied from the environment afterward (src/storymatrix/config/config.py).
The shipped storymatrix_config.yaml explicitly sets app.dev_local_only: false and app.low_resource_mode: false, so those YAML values override the two flag writes for config-reading gates. Therefore --offline does not guarantee offline behavior or local/mock providers, and --low-resource does not guarantee low-resource mode across all consumers. Track this trap at B15.
🗣️ voices list
storymatrix voices list loads voice records, applies optional key=value filters, and prints a human-readable list or JSON.
| Argument / option | Type | Default | Effect |
|---|---|---|---|
filters | list[str] | None | None | Positional filters in key=value form; provider is converted to the provider enum. Invalid entries are ignored with a warning. |
--json | bool | False | Print voice dataclasses as indented JSON instead of a Rich panel. |
🧹 voices clear-cache
storymatrix voices clear-cache clears the in-memory voice data cache.
| Option | Type | Default | Effect |
|---|---|---|---|
-p | str | None | None | Clear one provider’s cache; omit it to clear all voice caches. Unknown provider values are ignored after a warning. |
⚙️ config show
storymatrix config show prints the effective settings as YAML with secret values redacted, followed by a provider-strategy summary.
| Option | Type | Default | Effect |
|---|---|---|---|
--config | Path | None | None | Existing YAML file merged through load_config(); without it, StoryMatrixConfig() shows defaults and environment values. |
📝 config set-pref
storymatrix config set-pref KEY VALUE persists one user preference through UserPreferences.
| Argument | Type | Default | Effect |
|---|---|---|---|
key | str | required | Preference key such as tts.default_voice_id. |
value | str | required | Preference value to save. |
🔎 config get-pref
storymatrix config get-pref KEY prints one persisted user preference.
| Argument | Type | Default | Effect |
|---|---|---|---|
key | str | required | Preference key to retrieve. |
🌐 Global callback options
These options apply before a subcommand runs. The callback loads configuration for logging and stores selected values in the Click context.
| Option | Type | Default | Effect |
|---|---|---|---|
--version | bool | None | Eagerly prints the package version and exits. |
--log-level, -l | str | None | None | Sets logging level; otherwise the configured application log level applies. |
--offline/--online | bool | False | When enabled, writes APP__DEV_LOCAL_ONLY=true before configuration loading; direct environment consumers honor it, but config-reading gates can be overridden by YAML and therefore local/mock selection is not guaranteed. |
--low-resource/--no-low-resource | bool | False | When enabled, writes APP__LOW_RESOURCE_MODE=true before configuration loading; direct environment consumers honor it, but config-reading gates can be overridden by YAML. |
--max-tts-concurrency | int | None | None | For a positive value, writes APP__MAX_TTS_CONCURRENCY before configuration loading. |
--min-similarity | float | None | None | For a value from 0.0 through 1.0, writes SERVICES__LOCAL_ASSETS__MIN_SIMILARITY_SCORE before configuration loading. |
The generate command repeats --low-resource and --max-tts-concurrency for command-local use. The global callback accepts --online, but it only represents the false side of the offline boolean and does not write an environment value when selected.
🎭 Interactive builder
InteractiveStoryBuilder exists in cli/interactive.py, but cli/main.py does not expose an --interactive option or call build_story_request(). There is therefore no current CLI trigger for this flow; embedding code must instantiate the builder and call build_story_request().
When called, it prompts in this order:
- Story idea:
Story prompt, defaulting toA brave knight rescues a princess from a dragon; input must contain at least 10 non-whitespace characters. - Story style: displays nine choices—fantasy, scifi, horror, comedy, drama, mystery, adventure, children, and educational.
none(the default) returns no style. - Story structure: displays
three_act,hero_journey, andfive_act.auto(the default) returns no explicit structure. - Audio mixing: displays the configured mixing profiles and defaults to profile
1. - Advanced options: asks whether to specify a scene count (default
False); if enabled, accepts1–20scenes with default5, then asks whether to create a final audio montage (defaultTrue). - Preview and confirmation: shows prompt, selected style, structure, mixing profile, scene count, and montage choice, then asks
Create this story?(defaultTrue). A negative answer cancels withKeyboardInterrupt.
📦 Console scripts
The project exposes three console scripts from pyproject.toml:
| Script | Entry point | Purpose |
|---|---|---|
storymatrix | storymatrix.cli.main:app | Typer command-line application. |
storymatrix-api | storymatrix.interfaces.api.main:run | FastAPI service launched through Uvicorn. |
storymatrix-web | storymatrix.interfaces.web.main:run | NiceGUI web service. |
uv run storymatrix generate --prompt "A lighthouse keeper finds a voice in the fog"uv run storymatrix voices list --json
uv run storymatrix voices clear-cache -p piper
uv run storymatrix config show --config storymatrix_config.yamluv run storymatrix-api
uv run storymatrix-web📚 README coverage
README.md documents generate, --config, --scenes, --sfx, --background-music, --resume, and the two service scripts. It does not document the voices group, either config subcommand, global callback options, most generate options, or the interactive builder. Its four-profile summary also omits the additional dev, test, docs, and deploy profiles defined by the project configuration.