Skip to content

The patter CLI

The patter CLI runs the same operations the editor does, so what you author and what you automate never drift apart. It’s the natural fit for gating a pull request, running a build, or scripting a localisation hand-off.

Terminal window
npm install -g @patterkit/cli
patter validate ./my-project.patter

Every command writes through your version control (checking a file out first, adding new files), so a locked or read-only file fails the write rather than being overwritten. Exit codes are consistent. Exit 0 means success, 1 means the operation found problems or failed, and 2 means a usage error. fmt is an alias for format, and stats for report.

patter <command> --help (or -h, or patter help <command>) prints that command’s usage. Flags take their value as the next word or inline (--seed=-5); anything starting with - is a flag, so a mistyped one is refused rather than read as a path. Every usage error is printed under usage:, followed by the command’s whole form.

Terminal window
patter --version # also -v, or `patter version`

Worth knowing if you use the standalone binary: it has no package.json beside it and npm never installed it, so the tool itself is the only thing that can tell you which build you have.

Scaffold a new project: <dir>.patter with a starter scene and VCS config. --name X · --vcs git|perforce|plastic|svn · --bundle commit|ignore. (init . in place stays a plain folder.)

Check structure, expressions, interpolation, encoding, the localisation files, a stale bundle, and unresolved merges. Exit 1 if anything is wrong: the command to gate a PR on. A choice that can run dry is a warning, as in Patterpad, and never fails the run. A bundle counts as stale when it no longer matches the source or is not strict JSON, wherever the project writes it. Where the game shares its scopes, it also checks the other tools’ names and types against their files, and reports the folder itself ([game-scopes]): a file that won’t parse or a scope two files claim is an error, while another tool’s name, patter.scopes.json being out of date, or the project’s copy of a game scope differing from game.scopes.json is a warning, printed as one, which never fails the run.

Rewrite Patter source (.patterflow, .patterloc, .patterx, .patterproj) to canonical form. A folder means every shard in that project; any other file is left alone, so the bundle and the scopes files stay the strict JSON a game reads, and patter format $(git ls-files) is safe. --check reports what would change and writes nothing, exiting 1 if anything differs: a CI formatting gate.

Compile to a .patterc bundle (a single JSON file). Defaults to the project’s configured output, else patter-dist/<name>.patterc beside the project folder, where Patterpad’s Build Bundle writes too; -o - writes to stdout. --ids builds an IDs-only bundle (ships no strings); --source-debug is IDs-only but embeds the source language for debug playback. A project validate finds errors in (a jump to nowhere, a condition that doesn’t parse) is refused, with the problems listed; --allow-invalid builds it anyway, for looking at, never for shipping. Where the game shares its scopes, it also writes game-scopes/patter.scopes.json, and only when its content would change, and in an Audio Folders project the patteraudio.json manifest beside the audio (neither with -o -).

patter export-script [path] [-o file.pdf|.docx]

Section titled “patter export-script [path] [-o file.pdf|.docx]”

Export a readable screenplay of the script + flow: dialogue, narration, choices (with their conditions / flags), and jumps, in reading order, with a speaker qualifier in the cue (TAM (O.S.)). Format follows the extension; default beside the bundle, as <name>.pdf. PDF uses built-in fonts (Latin / Western-European); use .docx for full Unicode. The document’s layout is described on Building & shipping.

Export a single self-contained, playable .html: the runtime, the whole story, and a reader UI inlined, so it plays offline in any browser with no server, timed by a reading estimate and the writer’s pauses, with a Speed control. Hand one file to a stakeholder. Defaults to beside the bundle, as <name>.html; -o - writes to stdout. Refused, like export, for a project validate finds errors in. Reads in the project’s source language, as Building & shipping describes.

Run the story through Patterplay non-interactively and print a transcript, for scripted checks and CI, not for exploring (to actually play through a story, use Patterpad’s Play window). Choices come from --choices a,b,c (option ids taken in order; otherwise the first eligible is picked). --scene id · --block id · --seed N. A line with a speaker qualifier prints it after the name, TAM (O.S.): …. Exits 1 if the playthrough didn’t reach the end, or if a condition or effect failed on the way (the engine plays on past it, and the transcript marks it with !): a completion gate for CI. A line that names another engine’s scope (@story.act) plays where the game shares its scopes, standing that engine in from its file’s defaults; without the folder it is refused, since Patter is playing alone.

Narrative coverage: play the story many times with random choices and tally how often each beat is reached, flagging never-reached content (‼, or ? when it may just need an input) and content reached in fewer than 5% of runs (~). The table lists each beat’s reached (the share of runs that played it) and played (times it played in all runs), least reached first; --order script lists them in the script’s order instead, scene by scene. --runs N · --max-steps M · --seed S · --scene id · --block id. --json for pipelines; --fail-on-gap exits 1 if any beat is never reached (a CI gate). --propose prints auto-proposed @world coverage drivers instead of running. The same check has a window in Patterpad (Review ▸ Coverage Test…); see Coverage testing for how to read it.

Find the line (or node) a query names and print where it lives + what it says. The query can be an opaque id (e.g. from a locale string, an audio filename, or a runtime log), a Game ID address, or a scene/block name. Each hit prints id [kind] Game-ID Scene > Block «text» (file), so an an id resolves straight to the line it refers to.

Find every node that references a property: in a condition, an effect, or interpolated text. Handy when coverage flags a dead branch and you want to know where else its gating property is used. The query is a property ref (@gold, world.threat); add a value to narrow the matches, quoting it as one argument ("faction rebels"). --json emits the hits for scripting.

A production report: status, burndown, recording coverage. --xlsx file also writes a spreadsheet; --json emits JSON to stdout (for pipelines). In an Audio Folders project, recording status is derived from the takes on disk, the same numbers Patterpad shows.

Export strings for translation. --format json|xlsx|po (required) · --locale xx (omit for a blank template / POT). -o - writes JSON or PO to stdout. Each string carries its translator context, including the speaker’s grammatical gender.

Import a translated file back; the format is read from the extension, and --locale xx overrides the file’s locale. A file naming a scene the project doesn’t have, or a language it doesn’t declare, is refused and nothing is written.

A voice-recording script. Requires a Voiced project (voiced: true), or it exits with an error. --all includes every voiced line (otherwise only those ready to record). In an Audio Folders project, each line’s status column is derived from the takes on disk.

patter export-editable [path] -o file.docx

Section titled “patter export-editable [path] -o file.docx”

An editable script to send to an editor outside Patter, plus its handoff record in handoffs/. --scene name (repeatable; a name or an id) limits it to those scenes; --recipient "Sam" names who it’s for; --status, --cast, and --all-notes add writing status, a cast page, and every classed note; --by names who’s exporting.

Bring a returned editable script back as suggestions and comments, and print what it held. --dry-run writes nothing; --direct accepts the clean changes on the way in; --as name credits changes made without Track Changes; --strict-quotes counts quote style as an edit. Under lock-based version control it writes everything or nothing. A refused file exits 1.

List the open suggestions, each marked clean or out of date. --handoff H-7Q2K keeps one handoff’s; --accept-clean accepts every clean one; --json prints the list for a pipeline.

Share the project’s scopes with the game’s other editing tools, as Patterpad’s File > Share Scopes with Other Tools does: makes the game’s game-scopes/ folder (in --at, else at the version-control root above the project) with patter.scopes.json and a game.scopes.json holding the project’s World properties, which the project keeps as its synced copy. A folder another tool already made is joined, not replaced: its game.scopes.json keeps every scope it holds and gains only the ones it lacks. When looking up from the project wouldn’t find the folder, the project names it in gameScopes.

patter pack [path] -o file / patter unpack <file> -o dir

Section titled “patter pack [path] -o file / patter unpack <file> -o dir”

Pack a project into a portable .patterpack, or explode one back into source shards. unpack --merge --base sent.patterpack folds a returned pack’s edits into the project (a 3-way merge using --base as the common ancestor). Where the project has a game-scopes/ folder, pack carries a snapshot of it and unpack writes that into game-scopes/ inside the new project; unpack --merge never writes the snapshot back, but when the returned pack changed World properties it writes that change to your game.scopes.json and prints a game scopes: line.

A pack may come from outside the team, so unpack writes only what a pack of Patter’s carries: the source shards, the game’s scopes files, and open handoff records. Any other file in it is named in a warning and left unwritten, and a pack holding a dot-file or dot-folder (.git/config, say) is refused outright. unpack also refuses a folder that already holds a different project. unpack --merge writes only the shards the merge changed, and never brings back a scene you deleted after sending the pack.

A 3-way structural merge of Patter source by node id. -o out (otherwise stdout) · --type flow|loc|authoring|project (otherwise auto-detected) · --json. Conflicts write a provisional result plus a .patterconflict sidecar and exit 1. As git’s merge driver it runs as patter merge %O %A %B -o %A --path %P: -o is git’s temporary file, and --path names the real one, so the sidecar lands beside the shard where validate finds it. Input that is not Patter source exits 2, so the version control can fall back to its own merge.

A version-control merge-driver wrapper: Patter source goes through the structured merge, and anything else is handed to your normal tool via --fallback cmd. One driver serves the whole repository.

Open source under the MIT licence, made by .