On this page
Writing style workflow
The original writing-style form adds authored files, exports examples and trains an adapter through local Ster. Those commands need no model-provider credential. The separate Your voice panel registers automatic sources, offers writing and rewrite assignments, and shows prospective model comparisons. Generating new assignments or evaluating an adapter uses the selected Brama decision route or a declared direct chat service. A passage count or detector probability is not a personal-voice score.
Form
A segmented picker selects the subcommand: Add writing, Sources,
Remove a source, Train adapter, Export for Ster, Status. keep
is deliberately absent from it: a preference is recorded from a finished
rewrite by the button under that result, not by filling another form.
No number starts filled in: each is a field you type, and the app names the first empty one the subcommand needs before it runs anything.
| Subcommand | Control | UI value | CLI argument |
|---|---|---|---|
| Add writing | sources editor, one path per line | non-empty | positional SOURCES |
| Add writing | fewest words per passage | typed, required | --min-words |
| Add writing | most words per passage | typed, required | --max-words |
| Sources | none | — | — |
| Remove a source | the file or directory as it was named when adding | non-empty | positional SOURCE |
| Remove a source | "Remove its passages; this cannot be undone" toggle | off | --yes when on |
| Train adapter | objective | SFT examples or DPO pairs, default SFT | --method sft|dpo |
| Train adapter | checkpoint | empty | --model |
| Train adapter | adapter destination | empty | --output |
| Train adapter | revision (optional) | empty, omitted when blank | --revision |
| Train adapter | device | cpu, metal, or cuda, default cpu | --device |
| Train adapter | precision | f32, f16, or bf16, default f32 | --precision |
| Train adapter | LoRA rank | typed, required | --rank |
| Train adapter | LoRA alpha | typed, required | --alpha |
| Train adapter | epochs | typed, required | --epochs |
| Train adapter | learning rate | typed, required | --learning-rate, as typed |
| Train adapter | accumulation (rows per optimizer step) | typed, required | --accumulation |
| Train adapter | token limit per row | typed, required | --max-sequence |
| Train adapter | rows per pass | typed, required | --batch-size |
| Train adapter | seed | typed, required | --seed |
| Train adapter | beta (pull toward the base model) | typed; required for DPO, hidden for SFT | --beta |
| Train adapter | lead words used as the prompt | typed; required for SFT, hidden for DPO | --lead-words |
| Train adapter | rows used (empty = all) | typed; omitted when empty | --limit |
| Export for Ster | shape | SFT examples or DPO pairs, default SFT | --format sft|dpo |
| Export for Ster | destination file | empty | --output |
| Export for Ster | name | writing-style |
--name |
| Export for Ster | lead words used as the prompt | typed; required for SFT, hidden for DPO | --lead-words |
| Export for Ster | rows used (empty = all) | typed; omitted when empty | --limit |
| Status | none | — | — |
The objective, the name, the lead words and the rows used are one piece of
state shared by Train adapter and Export for Ster; the name is changed
in the export form. The train form shows no --export control, so the file
Ster reads always lands beside the adapter.
Blank lines and surrounding whitespace are dropped from the sources editor, so one path per line is the whole rule. Run is blocked with the app's own sentences:
Name at least one file or directory of your own writing.Name the file or directory whose passages to remove.Name the checkpoint to train on.Say where the adapter should be written.Give the export a destination file.State the <setting>.for the first empty number the subcommand needs, for exampleState the fewest words per passage.,State the LoRA rank.orState the lead words.
Status and Sources have nothing to validate and always run. Remove a source with the toggle off runs too: the CLI then names the passages and words it would remove and removes nothing, and that refusal is what the window shows, so the counts are read before the toggle is turned on.
Exact invocation shape
skryba writing-style add --min-words N --max-words N PATH [PATH...]
skryba writing-style train --method sft --model CHECKPOINT --device cpu --precision f32 --output PATH --rank N --alpha A --epochs N --learning-rate F --accumulation N --max-sequence N --batch-size N --seed N --name writing-style [--beta B] [--lead-words N] [--revision REV] [--limit N]
skryba writing-style export --format sft --output PATH --name writing-style [--lead-words N] [--limit N]
skryba writing-style status
skryba writing-style sources
skryba writing-style remove PATH [--yes]
Every number is sent exactly as typed. --lead-words is sent for SFT, and
--revision and --limit only when they carry a value, which is why they
trail the fixed block rather than sitting beside --model.
These forms carry paths in argv and send nothing on stdin. Detector options are not added: this workflow has no detector.
Successful result
Stdout must decode as the one report shape every writing-style subcommand shares:
action
store
passages
passage_words
preferences
added
skipped
removed passages a Remove a source run took back; zero otherwise
sources Sources only: every source with its passages and words
output absent unless the command wrote a file
written absent unless the command wrote a file
adapter train only: the safetensors Ster wrote
ster_command train only: the exact `ster` command the CLI ran
The Writing-style store panel shows the store path, passages and their word total, preference pairs, what this run added, skipped or removed, every source with its counts after a Sources run, and — after an export — the destination and the record count. The app computes none of those numbers.
A train run renders in the same panel with two additions and one relabelling.
output and written are the export Ster read, so the count row reads
Ster read Adapter Ster wrote:, with a Copy
adapter path button; then the ster command the run reported, verbatim, so
it can be repeated in a terminal. Both fields are optional in the decoder: a
CLI without train still decodes, and every other subcommand omits them.
There is nothing to watch while it runs. The app pipes stdout and stderr and
drains them to the end, and the CLI sends Ster's progress to its own stderr,
so the preflight and per-step loss arrive only when the process exits, behind
Skryba is running / This may take several minutes. A training run is minutes
to hours, and the window shows nothing until it finishes.
Keep mine, on a finished rewrite
A completed Rewrite result carries a Keep mine editor seeded with the CLI's own rewritten text. Change it into your own words and the pair — the model's text against yours — is recorded by a second, separate invocation:
skryba writing-style keep
with {"kept": …, "machine": …, "strategy": …} on stdin. The two texts travel
as one JSON object rather than in argv, which is the same rule Score and
Rewrite follow: the command line the app displays stays a command, not a copy
of somebody's prose.
The status line under the button is the CLI's own word, verbatim on failure and one sentence on success:
Recorded. The writing-style store holds <n> preference pairs.Already recorded. The writing-style store holds <n> preference pairs.
A rewrite nobody changed is refused by the CLI —
the kept text is identical to the machine text; that is a rewrite nobody changed, not a preference — and that refusal is what the line shows.
Recording a preference never replaces the rewrite result it was read from.
Failure
A nonzero exit shows CLI stderr verbatim, so every refusal on the
CLI writing-style page
appears here unaltered — a missing directory, a store that holds nothing to
export, a --lead-words no passage survives, a missing ster binary, or
Ster's own message plus the ster command that carried it. A zero exit with
malformed JSON throws the platform decoding error; a train run against a CLI
old enough to print Ster's own report object on stdout is one such case, and
it fails with The data couldn’t be read because it isn’t in the correct format. — the adapter is written even then, at the destination the form
named. Install a CLI that keeps Ster's output on stderr. Use
runbook to separate form, spawn, CLI, and decoding failures.
Maintained as part of the website-owned Skryba documentation corpus.