Command reference¶
bf --help lists the commands from setup to repair; bf COMMAND --help (or -h) lists a command's arguments, defaults and choices. Help reads no brain, runs no program and answers even when other values on the line are invalid. Start with Getting started for a first session, and Troubleshooting for recovery.
Commands¶
| Command | Purpose |
|---|---|
init PATH [--name NAME] [--full] |
Create a brain in a new, empty or freshly cloned folder; --full adds optional folders. |
register [PATH] |
Add or move a brain's entry in the optional machine registry. |
mcp |
Serve search and read over MCP stdio. |
skills DIR [--check] [--force] |
Install or update the packaged agent skills; see skills. |
schema [--kind KIND] |
Print a configuration or reply schema; defaults to bf.yaml. |
search QUERY [--scope SCOPE] [--limit N] [--offset N] |
Find words or an identity, optionally within one scope. |
read [REF] [--rel RELATION] [--offset N] |
Open home, a page, note, section, record or identity; --rel lists one relation's links. |
export [--kind edges\|identities] |
Print the graph of the selected brains as JSON Lines, from their caches. |
collect SENSOR [--since TIME] [--until TIME] [--dry-run] [--allow-removal] |
Run one sensor now. |
run [PROGRAM] [ARGS]... [--hook EVENT] [--stdin] [--dry-run] |
Run one routine or prompt, or every routine of a hook, now; see routines. |
update [--sensor NAME] [--routine NAME] [--prompt NAME] [--kind KIND] [--dry-run] |
Run due sensors, then due routines, then due prompts, then refresh the cache. |
watch [--interval N] [--poll-interval N] [--notify MODE] [--json] |
Run due programs until you quit, with a live dashboard; see watch. |
schedule [--backend NAME] [--every N] [--name NAME] [--output DIR] [--executable PATH] |
Generate native scheduler files and their installation commands; run nothing. |
status [--check] [--watch] |
Report caches, records, program health, logs and local usage. |
validate |
Check notes, links, actions, record files and program files. |
eval [--path evals] [--baseline FILE] |
Run retrieval cases; compare ranks with a saved reply. |
build [--reproject SENSOR [--dry-run]] |
Recover interrupted record writes and rebuild the search cache; --reproject re-applies mappings. |
Every command taking --brain NAME|PATH selects brains as Configuration describes. collect, run, update, watch and schedule act on exactly one brain; update, watch and schedule also accept repeatable --sensor, --routine and --prompt selectors.
Preview an update or a collection¶
bf update --dry-run
bf collect local-documents --dry-run
update --dry-run lists due programs with their windows, names enabled manual programs under manual, and runs nothing. collect --dry-run runs the sensor and returns up to three sample records without saving them or its run. run --dry-run runs its routines or prompt but writes no action or record and records no run; a prompt's reply still returns as text. Both can contact providers and still append to the program's log. The second example needs the local-documents sensor.
Without time options, collect covers the sensor's lookback through now. --since and --until accept now, today, yesterday, 12h, 7d, 2w, YYYY-MM-DD and ISO 8601 timestamps with a timezone. A snapshot sensor still returns its whole list, and --allow-removal accepts a large removal once.
Export the graph¶
bf export prints one JSON object per line for each claim in the selected brains and their direct references, for tools such as DuckDB or networkx. Like search, it reads the caches offline. On the example brain:
bf export | head -1
{
"brain": "example",
"origin": "bf://example/actions/2026-09-19_retention/ACTION.md",
"relation": "tagged-with",
"subject": "bf://example/actions/2026-09-19_retention/ACTION.md",
"target": "bf://example/tags/retention"
}
Each line has brain, subject, relation, target and origin, plus the origin's date for a note or time for a record, and observed for a record. relation is a declared relation, cites, tagged-with or links for an untyped link. Lines are sorted by subject, relation, target and origin within each brain.
bf export --kind identities prints one line for each note or record that answers to more than its own address, such as through an alias, with every name it answers to, so duplicate subjects stand out:
{
"brain": "example",
"kind": "note",
"names": ["bf://example/projects/example", "bf://example/projects/example.md", "repo:example/project"],
"ref": "projects/example.md",
"status": "stable",
"type": "project"
}
A busy cache is noted on stderr. A skipped file prints bf: BRAIN: FILE: ERROR on stderr and makes the command exit 1 after the other lines.
Shell completion¶
Load the completion script for your shell, for example from its startup file:
eval "$(_BF_COMPLETE=source_bash bf)" # bash, in ~/.bashrc
eval "$(_BF_COMPLETE=source_zsh bf)" # zsh, in ~/.zshrc
_BF_COMPLETE=source_fish bf | source # fish, in ~/.config/fish/config.fish
Typing bf sea and Tab then completes search.
Exit codes and errors¶
Results are compact UTF-8 JSON on stdout; help and version are plain text. Dashboards use the full terminal, and watch --json streams JSON Lines. Each diagnostic is one stderr line starting with bf:; it names files and positions without quoting your content.
Collected text and file names are data. Results, export lines, watch --json snapshots and MCP text escape DEL, C1 controls and Unicode format characters, such as soft hyphens and zero-width, bidi or tag characters, as JSON \uXXXX escapes, with a surrogate pair beyond U+FFFF; decoded values are unchanged. Diagnostics and MCP errors also escape the other control characters, including newlines, so a file name cannot forge another bf: line.
| Code | Meaning |
|---|---|
0 |
Success. |
1 |
Operation or check failed, including standard output that is closed, full or stops reading before the end. |
2 |
Invalid command-line input. |
130 |
Cancelled by Ctrl-C, SIGTERM or a closed terminal. |
Invalid input exits 2 with one line naming the argument, the reason and the help to read, before any brain is read when possible:
bf: invalid input: --limit: 0 is not in the range 1<=x<=50 (see bf search -h)
Other examples: bf search "!!!" (no word to search), bf read 2026-13 (no such month), bf read projects/../bf.yaml, bf read tasks#next (pages have no sections), bf read projects --rel cites (a page lists no relation), bf read projects/new-website.md --rel nope, which lists the valid relations, and an empty value choosing where or on what a command acts, such as --brain "", bf init "", bf collect "", run --hook "", --sensor "", collect SENSOR --since "", build --reproject "" or schedule --output "". An option that takes one value may appear once: bf search launch --scope projects --scope concepts is invalid instead of searching only the last scope. Only the program selectors repeat: --sensor, --routine, --prompt and update --kind.
A well-formed ref that names nothing exits 1 and suggests what exists: a close page, note, sensor, routine or prompt name (did you mean projects?), or the note's sections for a missing #section. collect and run suggest only enabled programs and fail on a disabled one with sensor NAME is disabled in bf.yaml; set enabled: true to run it.
update and run exit 1 when a program fails, and update and build when the refreshed cache skipped files; successful programs keep their results. status --check exits 1 on problems, unavailable brains or references, or scheduled programs that failed, are overdue or never succeeded, or fell silent. validate exits 1 on problems, never on warnings. skills exits 1 when it keeps a folder holding your edits, foreign files or a newer bf's copy, and --check unless every skill is current; see skills.
Using replies¶
Every reply states times with your local offset, and dates and field values as the retrieval reference describes, while files, run history and the cache keep UTC. Search and read replies follow that reference; problems is always a list of objects with error and, when known, brain and file.
An update reply has ok, dry_run, its brain, the sensors, routines and, when the brain declares any, prompts it ran or found due, manual for skipped manual programs, and the refreshed index. A run reply has ok, dry_run, any hook and its routines, each with a status of ran, skipped or failed; a prompt's has prompts: one entry with its status (ran or failed), the record it wrote (none on a dry run) and the reply text, or an error.
Program and source status¶
bf status groups results under brains. Each brain has its cache, notes, problems, attention, sources, routines, prompts, coverage totals and usage. healthy is false when any brain has a problem, an attention entry, an unavailable cache or cannot load. A brain that cannot load appears with only brain, error and, when known, path.
| Field | Meaning |
|---|---|
cache |
ready, or busy while a writer updates it. stale (the last cache) or missing (none) while an interrupted write awaits recovery, unlike the stale of search and read replies. |
pending_transaction |
true when memories/.pending holds an interrupted write; a problem names the command to recover it. |
runtime |
The installed bf version and, read as data from the brain's uv.lock, the pinned one, when the brain pins a runtime: compare their major versions before trusting either. |
attention |
Scheduled programs this machine runs that failed, are overdue or never succeeded, or are silent, such as {"sensor":"mail","freshness":"never","failed":true}, as on the home page. |
state |
As in source coverage; a routine or prompt is active or disabled. |
freshness |
fresh, overdue, never, manual or unknown; see timing and health. |
records, bytes, latest |
Indexed records of the source, their size on disk and the newest event time. |
changed, silent |
When this brain last gained a new or changed record of the source, and true when that is older than its silent_after. |
mode, window |
Sensor mode and, for window sensors, the contiguous collected interval {since, until}. |
last_collected |
The last collection that brought the source up to date, which freshness counts from; a backfill never does. Routines and prompts report last_success. |
last_run |
Counters of the last committed run: records, added, updated, unchanged, removed, requested_start, requested_end, reconcile, elapsed_seconds, output_bytes. |
reconciled |
The last scheduled reconciliation. |
action |
A routine's latest action. |
runs, record |
A prompt's successful runs and the record its latest run wrote; the last_run of its latest scheduled run holds at, elapsed_seconds and output_bytes. |
failed, error, failures, log |
The last attempt failed: its diagnostic, consecutive failures and logs/NAME.log. |
usage |
7d and 30d counts of search, empty (searches without results) and read; since, the oldest event counted, when rotation cut that window. |
For example, an hourly mail sensor that collected one message reports:
{
"state": "active",
"freshness": "fresh",
"mode": "window",
"last_collected": "2026-09-29T15:00:00+02:00",
"window": { "since": "2026-09-28T15:00:00+02:00", "until": "2026-09-29T15:00:00+02:00" },
"records": 1,
"bytes": 612,
"latest": "2026-09-29T14:20:00+02:00",
"last_run": { "records": 1, "added": 1, "updated": 0, "unchanged": 0, "removed": 0, "elapsed_seconds": 0.02 }
}
A brain also lists warnings when a source or authored folder holds more than 80% of the 100,000-entry scan limit, such as {"warning":"directory nears the scan limit","directory":"memories/mail","entries":81234,"limit":100000}. Warnings never fail status --check.
With jq, list projects needing review:
(
set -e
offset=0
while [ -n "$offset" ]; do
page=$(bf read projects --offset "$offset")
jq -r '.items[] | select(.review) | [.ref, .next // ""] | @tsv' <<<"$page"
offset=$(jq -r '.next_offset // empty' <<<"$page")
done
)
Each line holds a project ref and its first open task. Pages end near 32 KiB, often after a few dozen projects, so the loop follows next_offset until it is absent. The subshell stops at the first failed command and keeps its exit status without closing your shell.