Reference
Configuration
Two files decide how Prometheus behaves: a YAML file for settings and a separate env file for secrets. The split is deliberate, and the rule that follows from it is the only one you have to remember — nothing secret ever belongs in the YAML.
Where the config is found
Prometheus looks in a fixed order and takes the first hit. This is quoted from the shipped template itself, so it cannot drift from the search the code actually performs:
oara config --show-defaults | head -14 # Prometheus configuration — reference defaults # Copy to config/prometheus.yaml and customize (or run `prometheus setup`). # config/prometheus.yaml is gitignored — your secrets stay local. # # CONFIG SEARCH ORDER (first hit wins): # 1. an explicit --config path # 2. config/prometheus.yaml — repo-local (checkout installs) # 3. $PROMETHEUS_CONFIG_DIR/prometheus.yaml # (default ~/.prometheus/prometheus.yaml — pip installs; this is # what `prometheus setup --fast` writes) # # SECRETS never belong in this file — put them in the env file the daemon # and the systemd unit both load: ~/.config/prometheus/env # (PROMETHEUS_API_TOKEN, PROMETHEUS_TELEGRAM_TOKEN, ANTHROPIC_API_KEY, …).
If you installed with uv tool install or pip — which is
almost everyone — yours is ~/.prometheus/prometheus.yaml, and entry 2 never
applies. The repo-local path exists for people running from a checkout, and it wins over
your home directory when both are present. That is the one surprise in the list: a
checkout you forgot you were standing in will quietly take precedence.
oara doctor prints it on its first line —
✓ Config: loaded ~/.prometheus/prometheus.yaml, or a ✗ naming
every path it searched. That is the reliable answer; see
Verify it works.
Secrets go in the env file
~/.config/prometheus/env is a plain KEY=value file, mode
0600. Both the daemon and the systemd unit load it, which is why it is the env file and
not your shell profile — a service started at boot never sees your shell.
| Variable | What it is |
|---|---|
PROMETHEUS_API_TOKEN | Bearer token for the REST/WS API that Beacon and the iOS app authenticate with. See Tokens and the open web API. |
PROMETHEUS_TELEGRAM_TOKEN | Bot token, if you use the Telegram gateway. |
ANTHROPIC_API_KEY and friends | Cloud provider keys, when the model is not local. |
The YAML does have a model.api_key field that accepts a key
inline, and the template documents it while telling you not to use it. The reasoning is
worth repeating, because it is the reason the split exists: a prometheus.yaml
gets copied between machines and pasted into issues. An undocumented key that works is
worse than a documented one you are told to avoid.
Reading the defaults
There are 46 top-level sections. Rather than reproduce them here — where they would start going stale the day this page was written — read them from the binary you have installed:
oara config --show-defaults > reference.yaml grep -n '^[a-z_]*:' reference.yaml 16:system: 21:bootstrap: 25:model: 135:compaction: 153:checkpoints: … 1170:vault: 1184:doctor: 1189:tasks: 1197:heartbeat: 1216:documents: 1224:escalation:
It is worth actually reading rather than grepping. The comments carry the reasons — several of them record the incident that produced the setting, including dates. That is the closest thing to a design rationale the project has.
oara config with no flags prints its own help and exits 0. There is
currently no command that shows you the merged, loaded configuration —
--show-defaults prints the shipped template, which is not the same thing as
what your daemon is running. Until there is one, oara doctor is how you
confirm which file loaded, and reading that file is how you see what is in it.
The handful you are likely to change
Defaults below are the shipped values, read from the template.
| Key | Ships as | Why you might touch it |
|---|---|---|
model.providermodel.base_url | llama_cpphttp://localhost:8080 | Point at a different backend. oara setup writes these for you. |
model.model | empty | A hint, not an assertion — the backend is authoritative. Leave it blank unless your server cannot be asked what it is serving. |
web.enabled | true | The REST/WS control plane Beacon talks to. On by default, but not open by default — the daemon mints an API token on first start if none is set. |
web.api_port / ws_port | 8005 / 8010 | Change if something else owns those ports. |
security.workspace_root | ~/.prometheus/workspace | Where the file tools may write without asking. Widen deliberately — and read the next section before you do. |
coding.enabled | false | Coding mode runs model-authored commands against a clone of your repo, so it is opt-in at both entry points. |
gateway.telegram_enabled | false | Turn on the Telegram gateway. The token itself goes in the env file. |
What actually constrains the agent, in order
This is the part worth reading slowly, because the setting with the most reassuring
name is the weakest of the three and none of the first two covers bash. The
template states all of this in its own comments; it is collected here because it is spread
across a hundred and fifty lines and the order matters.
| Layer | Ships as | What it actually does |
|---|---|---|
security.workspace_root | ~/.prometheus/workspace | A prompt, on write_file and edit_file only. An accidental write outside your working area asks first. Nothing more. |
security.denied_paths | /etc, /sys, /boot, /*/.ssh, /*/.gnupg, /*/.config/*/*env | A refusal — but still only on calls that pass a file path. The globs span / deliberately, and the daemon's own config file is denied automatically from wherever it loaded. |
security.bash_confinement | "off" | The kernel read floor for bash, via AppArmor. Off by default because most hosts have no AppArmor, where required would refuse every bash call. |
security.bash_write_confinement | "auto" | The kernel write floor for bash, via bubblewrap. auto means "if bwrap is installed" — and on a machine without it, bash runs with no write floor at all. |
denied_paths is consulted only when a call passes a file_path,
and bash is handed a command string — so at both origins
cat ~/.ssh/id_* is allowed. The template records this as
measured, not inferred. Checking the command string instead does not work either:
ordinary shell defeats it (cd ~/.ssh && cat id_*, $HOME
indirection, globs, sh -c), which is why the floor for bash is a kernel
mechanism or nothing. On a stock machine with neither AppArmor nor bubblewrap, it is
nothing.
oara doctor reports both floors and their live state, including
! Bash write floor: mode 'auto' but UNAVAILABLE when bwrap is missing. If you
are about to expose this daemon to anything, that line is the one to read first — and
Tokens and the open web API is the other half of the question.
Credit where it is due: the required setting for the read floor refuses to
run bash at all if the AppArmor profile is missing or the transition does not happen,
rather than silently falling back to an unconfined shell. Being handed a weaker sandbox
than you asked for is the failure you would not notice, and it is refused by design in
several places here — coding.sandbox_type raises for the same reason.
Where everything else lives
| Path | What is in it |
|---|---|
~/.prometheus/ | The data root. Everything below is under it. |
~/.prometheus/prometheus.yaml | Your config, for a pip or uv install. |
~/.prometheus/memory.db | Extracted facts. Fails open — a missing or broken file never blocks a turn. |
~/.prometheus/data/ | Other databases, including training.db. |
~/.prometheus/logs/ | Logs. cli.log always gets INFO even when the console does not. |
~/.prometheus/workspace/ | The default write area for the file tools. |
~/.prometheus/skills/ | Recorded skills; generated ones land in skills/auto/. |
~/.prometheus/wiki/ | The hand- and machine-maintained knowledge tree. |
~/.prometheus/coding/sandboxes/ | Clones that coding runs work in. Never your original repo. |
~/.prometheus/trajectories/ | Where oara export-traces writes. |
~/.prometheus/SOUL.md~/.prometheus/AGENTS.md | Identity files loaded into every system prompt. Managed with oara identity. |
~/.config/prometheus/env | Secrets. Mode 0600, loaded by the daemon and the service unit. |
Two commands wipe things deliberately and are worth knowing before you need them:
oara --reset-telemetry deletes telemetry.db and exits, and
oara --reset-data deletes all user data — telemetry, memory, LCM, audit,
evals, wiki, sentinel and generated skills. Neither asks twice.