On this page

Training boundary

Skryba owns the person's text and the rewrite loop. Ster owns the weights and the gradient. Skryba calls Ster rather than reimplementing it: it writes the training file, spawns the installed ster binary, and reports what came back.

Which product owns what

Skryba holds the store, decides what a passage is, builds the training file, chooses candidates, scores them against detectors, and gates them on quality. It maps no checkpoint in its own process, links no tensor library, and carries no tokenizer — that work belongs to Ster, which maps the checkpoint, runs the forward and backward passes, and writes the LoRA adapter. Reimplementing a trainer inside Skryba would duplicate Ster and give a text tool a GPU dependency it has no other use for; calling Ster costs one process.

Skryba resolves ster the way Skryba Desktop resolves skryba: every PATH entry first, then ~/.cargo/bin, ~/.local/bin, ~/.stado/bin, /opt/homebrew/bin and /usr/local/bin. When it is missing, Skryba says so in one sentence and names the install command rather than failing obscurely.

Ster's own words reach the operator unchanged. A training run streams both of Ster's streams to Skryba's stderr, so its progress and its refusals print as Ster writes them while Skryba's stdout stays the one JSON report; a captured run carries Ster's message through verbatim. Skryba never rewords a refusal it did not produce.

From the store to an adapter, in one command

skryba writing-style add ~/writing ~/notes --min-words <N> --max-words <N>
skryba writing-style train \
  --model <checkpoint> \
  --output my-prose.safetensors \
  --rank <N> --alpha <A> --epochs <N> --learning-rate <F> --accumulation <N> \
  --max-sequence <TOKENS> --batch-size <N> --seed <N> --lead-words <N>

train exports the held text, runs ster tune sft over it, and reports where the adapter landed together with the exact ster command it ran, so the run can be repeated by hand. --method dpo trains the preference objective from the pairs the person resolved themselves and runs ster tune dpo instead. --model, --revision, --device, --precision, --rank, --alpha, --epochs, --learning-rate, --accumulation, --max-sequence, --batch-size, --seed and, for DPO, --beta pass straight through to Ster rather than being hidden; every number is required, because Ster assumes none and so does Skryba.

The export is kept, not discarded: it is written beside the adapter as <adapter-stem>-sft.json or -dpo.json unless --export names a path. writing-style export still exists for anyone who wants the file alone.

The two shapes, and which command reads each

--format sft — and --method sft — writes what ster tune sft deserializes:

{
  "name": "my-prose",
  "examples": [
    { "prompt": "…", "completion": "…" }
  ]
}

The completion is the person's own prose. The prompt is one fixed line of framing, Continue this passage in the same voice:, followed by the passage's own opening sentences — --lead-words words (required for sft), cut at the first sentence end at or after that count. Ster masks the prompt out of the loss and trains only on the completion, so nothing is learned from the lead as a target; it is the distribution the adapter answers.

Two other prompts were available and are worse. A synthesized instruction would need a model call — a Brama request and a credential — to capture your own writing, and it would collapse into a handful of templated sentences repeated across the corpus, which is exactly what Skryba's six hard-coded strategies already are: the same words for every user on earth. The AI-written version of the same passage is a rewrite prompt rather than a writing prompt, it exists only where a rewrite was run, and where it does exist it is a preference — which is the other format, below.

--format dpo writes what ster tune dpo deserializes:

{
  "trait_name": "my-prose",
  "pairs": [
    { "positive": "…", "negative": "…" }
  ]
}

positive is what the person kept, negative what the model produced. Ster scores a pair whole and carries no prompt field, so both sides are complete texts of the same passage. --name sets name in the SFT set and trait_name in the pair set.

A pair set is not only a preference input. ster train, ster optimize, ster evaluate, ster tune dpo and ster tune reward all deserialize the same PairSet, so one --format dpo file feeds the steering half of Ster as well as the preference half, unchanged.

Rewriting through the model that was trained

An adapter nobody generates with is a file. rewrite takes a generator:

skryba --minimum-quality <Q> rewrite \
  --generator local \
  --local-model <checkpoint> \
  --adapter my-prose.safetensors \
  --candidates <N> --max-words-per-chunk <N> --temperature <T> --seed <N> \
  < passage.txt

--generator brama is the other route — one chat completion per candidate, no weights anywhere near the machine. --generator local runs ster generate with the personal adapter attached, so the rewrite is written by the model that learned the person's prose. The rest of the loop is unchanged: the same six strategies, the same detector ensemble, the same quality gate, the same least-detectable selection.

One candidate is one ster generate process, and each process maps the checkpoint again. That cost is real, and it is why the local route is chosen rather than assumed; a small --candidates keeps a local group affordable.

What each side still refuses

  • Skryba refuses to invent examples: a training run uses only rows the person put in the store, and a passage too short to split into a lead and a completion is counted in skipped rather than padded.
  • Skryba refuses to claim a success Ster did not report: if ster tune returns zero but no adapter exists at --output, train fails.
  • Ster refuses to truncate: an example longer than --max-sequence tokens is skipped and named on stderr, because a cut completion would teach the model to stop early.
  • Ster refuses a mismatched adapter: an adapter trained for another checkpoint is rejected rather than applied to the wrong residual stream.

Maintained as part of the website-owned Skryba documentation corpus.