Quick start
How do you go from a repository with existing documentation to a reconciled workspace? This page is the one happy path: build the CLI, adopt the existing Markdown without generating it, inspect the evidence boundary, configure Brama, audit one change, preview one document, and turn on the sync loop. Everything else — the full flag surface, the selection rules, and the loop's exact state machine — lives in cli, sources, and sync.
Build the CLI
Prerequisites: Git, Node.js 22 or newer, npm.
git clone https://github.com/wisent-ai/kronika.git
cd kronika
npm install
npm run build
npm link
npm run build compiles TypeScript into dist/; the kronika binary is
dist/src/cli.js. npm link puts kronika on your PATH; without it, run
node dist/src/cli.js directly. The package has no runtime dependencies.
Adopt the existing documentation
kronika init --repo /path/to/project
Without explicit --docs, init selects an existing root
README.md and Markdown beneath docs/. It validates the
whole selection and atomically writes only kronika.sync.json. It
does not generate, copy, or rewrite a document, execute repository commands,
or call Brama. Repeat --docs and --source to declare
exact document and evidence paths. An identical manifest is unchanged; a
different retained manifest is reported as a conflict and preserved unless
--replace is explicit. See
kronika init.
Graphical alternative
kronika gui --repo /path/to/project
Open the exact session URL printed by the foreground command. Select
repository-relative Markdown and evidence paths, review the destination and
conflict policy, then import. The GUI invokes the same adoption function as
init and reads the persisted manifest back; it does not open a browser
itself, call Brama, generate documentation, or run repository commands. See
the graphical importer.
Inspect the evidence boundary
kronika sources --repo /path/to/project
This makes no model request and changes no file — it needs no Brama configuration at all. It prints JSON: the selected files with byte counts, the total, and every skipped file with its reason. Captured against a toy repository (paths and counts will differ):
{
"repo": "/private/tmp/kronika-docs.OnmsmX/toy",
"output": "README.md",
"totalBytes": 442,
"sources": [
{ "path": "README.md", "bytes": 87 },
{ "path": "docs/usage.md", "bytes": 80 },
{ "path": "src/greet.js", "bytes": 93 },
{ "path": "kronika.sync.json", "bytes": 182 }
],
"skipped": [
{ "path": "credentials.json", "reason": "credential or generated lock file" }
]
}
Add --source <path> (repeatable) to select explicit files or directories
instead of automatic discovery. Review this boundary before configuring
Brama: it is exactly what the model will see.
Configure Brama
export BRAMA_URL=<your-brama-origin>
export BRAMA_API_KEY_ROLE='<bearer-role>#<field>'
# Optional request signing; set both or neither:
export WISENT_APP_AGENT_ID=<agent-id>
export WISENT_APP_AGENT_AUTH_SECRET_ROLE='<signing-role>#<field>'
export KRONIKA_MODEL=any
BRAMA_URL and
BRAMA_API_KEY_ROLE are required for model commands. These role
references are resolved through stado credentials get --role;
secrets themselves do not belong in the environment. The signing identity
and secret reference must be supplied together. Without Stado, explicitly
select an owner-only KRONIKA_CREDENTIALS_FILE as described in
configuration.
KRONIKA_MODEL selects the route; unset, it is any.
Audit one change
kronika check --repo /path/to/project --base origin/main --json
check resolves --base and --head (default HEAD) to commit SHAs,
sends the bounded Git diff plus current sources to Brama, and prints a
structured verdict. Exit 0 means the documentation already covers the
change; exit 1 means at least one blocker finding names a concrete defect
— captured blocked and passing runs are in
walkthrough-check.
Preview one document
kronika write \
--repo /path/to/project \
--output docs/architecture.md \
--source README.md --source src \
--instruction 'Document components, request flow, invariants, and failure modes.'
Without --apply, write prints the generated Markdown to stdout and
changes nothing. Add --apply only after reviewing the preview: it
atomically replaces the output file, which must stay inside the repository.
Turn on the sync loop
The earlier kronika init created
kronika.sync.json at the repository root. Review the imported
declarations before the first sync; its established shape is:
{
"schemaVersion": 1,
"documents": [
{
"output": "docs/architecture.md",
"sources": ["src", "README.md"],
"instruction": "Keep the existing section order."
}
]
}
Then run:
kronika sync --repo /path/to/project --commit --push
The first run for each document records the current commit as its baseline
and generates nothing. The output has this shape, with the repository's commit in place of <commit>:
$ kronika sync --commit
Kronika sync at <commit>
baseline docs/usage.md — first sync records <commit> as the baseline; nothing is generated on a first run
committed
Every later run audits only documents whose declared sources changed,
rewrites only documents whose audit found blockers, and records the
reconciled commit in kronika.sync-state.json. --dry-run reports without
writing anything. Exit 1 means at least one document failed to reconcile.
The full state machine is the sync loop; every action, captured
tick by tick, is walkthrough-sync-cycle.