Configuration
Styre reads one settings file: config.json, at ~/.config/styre/config.json. It holds
operator policy — which tracker, which agent, notifications, telemetry. Every key has a default,
so the file is optional; you only write the keys you want to change.
config.json is separate from a repo’s profile. The profile describes a
project’s shape and is written by styre setup; config is your policy and is written by hand. They
never merge into each other.
Every setting
Section titled “Every setting”| Key | Default | What it does |
|---|---|---|
issueTracker |
"linear" |
Which tracker to read tickets from: linear or jira. |
forge |
"github" |
Which code host to push to. Only github is available. |
agent |
Claude | The agent provider and its per-tier models. See below. |
notifier |
"none" |
Outbound notifications: none or slack. |
notify |
"escalations" |
How much to send: escalations, transitions (also stage changes), or everything (also loopbacks). |
slack.channel |
— | The Slack channel to post to. Required when notifier is slack. |
onPlanDefect |
"escalate" |
When review finds a flaw in the plan: escalate to a human, or redesign to loop back and re-plan. |
complexityGrading |
false |
Opt in to a complexity grader when sizing work. Off means sizing is based on sprawl alone. |
implementDisposition |
"reject" |
How implementation handles files the plan did not declare: reject (the proven default) or discard. |
jira |
built-in | Jira-specific policy. See below. |
pricing |
built-in | Price table for the cost estimate in telemetry. See below. |
telemetry |
true |
Anonymous usage analytics. See Telemetry. |
The agent block
Section titled “The agent block”Sets the provider and the model for each of the three tiers Styre uses — deep for planning and
review, standard for implementation, cheap for small mechanical steps.
{ "agent": { "provider": "claude", "models": { "deep": "claude-opus-4-8", "standard": "claude-sonnet-4-6", "cheap": "claude-haiku-4-5-20251001" } }}That block is also the default — omit agent entirely and you get exactly this. The Codex
equivalent:
{ "agent": { "provider": "codex", "models": { "deep": "gpt-5.6-sol", "standard": "gpt-5.6-terra", "cheap": "gpt-5.6-luna" } }}Only relevant when issueTracker is "jira". Absent, Styre uses built-in defaults.
| Key | Default | What it does |
|---|---|---|
jira.statusMap |
built-in | Maps each Styre ticket state to one of your Jira statuses. See below. |
jira.bugTypeNames |
["Bug"] |
Which Jira issue types count as bugs, deciding the fix/ versus feat/ branch prefix. |
jira.statusMap
Section titled “jira.statusMap”Styre tracks a ticket through five internal states and projects each one onto a status in your Jira workflow. The default map assumes a fairly standard board:
{ "jira": { "statusMap": { "in_progress": { "status": "In Progress" }, "in_review": { "status": "In Review" }, "done": { "status": "Done", "resolution": "Done" }, "canceled": { "status": "Done", "resolution": "Won't Do" }, "blocked": { "status": "In Progress" } } }}Each entry is a status — the exact name of a status in your Jira project — and an optional
resolution set when the issue moves there. The five state keys are fixed; the values are what you
change to match your board’s status names.
Unlike the other nested blocks, statusMap is filled in per state: any state you leave out
keeps its default from the table above, so you can override just the one or two states whose names
differ on your board.
Pricing
Section titled “Pricing”Styre’s telemetry includes a rough cost estimate per run. The pricing block lets you supply your
own rates if the built-in table is stale or does not cover a model you use.
{ "pricing": { "version": "my-rates@2026-07", "rates": { "claude-sonnet-4-6": { "input": 3.0, "cacheRead": 0.3, "cacheWrite": 3.75, "output": 15.0 } } }}Rates are USD per million tokens. Two things to know:
- This only affects the estimate. The actual cost your provider reports is passed through untouched and never overwritten by this table.
ratesreplaces the whole built-in table, not one entry. A model you do not list becomes unpriced rather than keeping its built-in rate. To adjust one model, copy the full built-in table and change the one line.
How config resolves
Section titled “How config resolves”There are two ways config is loaded, and they do not mix:
With --config <path> — that file is the only source. Nothing else is read or merged. Use
this when you want a run to be fully self-contained and reproducible.
Without it — Styre layers two files: a per-project ~/.config/styre/<slug>/config.json on top
of the global ~/.config/styre/config.json, then fills any remaining gaps with the defaults.
Two things that catch people out:
- There is no per-ticket configuration. A ticket cannot carry settings. Runtime policy lives
only in
config.json(or--config). Anything you put in a ticket to configure a run is ignored. - Telemetry has one env-var override.
DO_NOT_TRACKorSTYRE_TELEMETRY=0turns analytics off even iftelemetryistruein config. It is the only setting an environment variable can override — see Telemetry.
For where these files live on disk, see Files and paths. For the profile
that styre setup writes, see Project setup.