Bootstrap the writing store, author a writer profile, run a deterministic anglicism lint, and get a full rubric critique from your own LLM in one pass.
pks writing init && pks writing lint post.mdGet a Danish blog post linted and scored in a few minutes: create the writing store, author a writer profile, run the free deterministic lint, then hand a critique prompt to your own model and validate the reply back into a report sidecar.
This page covers the first end-to-end pass. For the full flag surface, see the pks writing CLI reference.
dotnet tool install -g pks-cli, or without .NET via npm install -g @pks-cli/cli..md file. The examples below use a blog post.pks writing init
This creates ~/.pks-cli/writing/ and seeds a profile.md template on first run. When the current directory is inside a git repository, it also creates ./.pks/writing/ and adds it to the nearest .gitignore. Outside a repository the project layer is skipped with a yellow warning, not an error.
Add --dry-run to see what would be created without touching the filesystem.
Note. Re-running
initnever overwrites an existingprofile.md. It is safe to run again.
The profile is what makes the linter and the critic sound like you rather than a generic style guide.
pks writing profile author
The interactive menu offers two paths: print a "cowork" authoring prompt to paste into a model that already knows your writing, or open profile.md in $EDITOR for manual authoring. If $EDITOR is unset, the editor path searches PATH for code, nano, vim, and vi.
If you took the cowork path, save the model's JSON reply and ingest it:
pks writing profile ingest ~/Downloads/cowork-reply.md
The bundle may be raw JSON or markdown containing a fenced json block. Confirm the result:
pks writing profile show
You should see the resolved profile.md plus counts and paths for anglicisms, allowlist terms, the active channel, and reference samples.
pks writing lint blog-posts/my-post/da.md
The lint is offline and calls no model. It scans against your anglicism list and allowlist and writes blog-posts/my-post/_review/da.WRITING-REPORT.{json,md}. Up to 20 findings render in the terminal table; the full set is in the sidecar. A file with zero findings has any stale sidecar deleted.
Pass a folder to recurse over *.md, skipping node_modules/, _review/, and .pks/:
pks writing lint blog-posts/
Lint is informational by design and exits 0 for any number of findings, so it will not break a pipeline — except it exits 1 if the profile's anglicism list is empty (run pks writing init first).
Emit the critique bundle:
pks writing prompt blog-posts/my-post/da.md
Stdout is a self-contained JSON bundle: a system prompt, a user prompt, the reply JSON schema, and metadata. The post body, writer profile, channel rubric, and reference samples are all embedded. The pks banner is suppressed for this command so the output stays pipe-clean.
Feed that bundle to your model, save the reply as reply.json, and submit it:
pks writing accept blog-posts/my-post/da.md --from reply.json --model haiku
The reply is validated against the score schema — five dimension scores from 1 to 5 plus notes, with finding line numbers checked against the source file's actual line count. On success the critique is merged with existing lint findings and written to the report sidecar. You can pipe instead of using --from:
your-llm-call | pks writing accept blog-posts/my-post/da.md --model haiku
On a schema failure the command exits 1 and prints a machine-readable line whose hint field tells an agent what to correct:
RESULT: {"ok":false,"errors":[...],"hint":"..."}
pks writing profile show
You should see your profile and non-zero anglicism and allowlist counts. Then open the report sidecar at blog-posts/my-post/_review/da.WRITING-REPORT.md. It contains the merged lint findings and the rubric critique with per-dimension scores.