Configuration
Kronika has no configuration file of its own. Behavior is set by CLI flags (defaults in cli), Brama access by environment variables, and the sync loop by the per-repository manifest described in sync.
Environment
| Variable | Required | Purpose |
|---|---|---|
BRAMA_URL |
yes, for check/write/sync |
Brama origin for model commands |
BRAMA_API_KEY_ROLE |
yes, for check/write/sync |
ROLE#FIELD reference resolved through stado credentials get --role; not a secret value or vault item name |
WISENT_APP_AGENT_ID |
optional | request-signing agent identity |
WISENT_APP_AGENT_AUTH_SECRET_ROLE |
with the signing agent identity | ROLE#FIELD reference for the request-signing secret |
KRONIKA_MODEL |
optional | default --model selector; any when unset |
STADO_BIN |
optional | Credential resolver executable; otherwise stado on PATH |
KRONIKA_CREDENTIALS_FILE |
explicit alternative without Stado | Owner-only JSON object mapping role to field to secret value; never committed |
init, gui, sources, onboarding and help need no Brama credentials.
Model operations refuse a missing URL or BRAMA_API_KEY_ROLE.
Only role references travel in the environment: the bearer and signing secret
are resolved when needed. The signing identity and secret must be supplied
together. Credential resolution failures identify the role, field and failed
operation. The opened credentials descriptor must be a regular file owned by
the caller and deny group and other access before any secret is read from that
same descriptor. Its JSON must hold a nonempty string for the requested field.
A present blank file declaration refuses instead of selecting Stado; file
refusals name the declaration, path and actual cause.
The Brama request
Every model interaction is one POST to <BRAMA_URL>/v1/chat/completions
(trailing slashes on the URL are stripped) with an OpenAI-compatible body:
model and messages, plus max_tokens only when declared. Headers:
authorization: Bearer <resolved bearer>— always.- When the signing pair is set:
x-agent-id,x-agent-timestamp(Unix seconds), andx-agent-signature— an HMAC-SHA256 over<agentId>:<timestamp>:<sha256-hex-of-body>keyed with the secret, so the signature commits to the exact JSON body.
The request has no time limit: it ends with Brama's answer or a transport
error. A non-2xx response surfaces as
Brama returned HTTP <status> with the server's error detail. The response
may carry content directly or the OpenAI choices[0].message.content
shape (string or text parts); an empty completion is the error
Brama returned no documentation content. Every transport sentence, with
meaning and fix, is in the
runbook.
Model selection
--model (default KRONIKA_MODEL, then any) is passed through to Brama
as the model field. Kronika does not resolve providers or models itself —
Brama owns client authorization, model selection, and inference. In the
sync loop, a per-document model in the manifest overrides the flag.
Budgets
Every budget is an optional flag with a per-document override in the sync
manifest, and none has a default: --max-input-bytes and
--max-file-bytes bound the source payload (sources),
--max-tokens bounds the completion, and --max-diff-bytes bounds the
audited Git diff — an oversized diff is refused, never truncated. Unset, every
source is read whole, the whole diff is audited, and Brama's alias sets its own
output limit.
The site pipeline's endpoint
The kronika-site pipeline resolves BRAMA_URL,
otherwise the address published by Stado in ~/.stado/forwards/brama.local.
If neither is available, the refusal names both declarations; no endpoint is
built in. An unreachable endpoint exits 69. Generation sampling
belongs to the Brama route, and failed HTTP responses retain their complete
error body. See site pipeline.