Limits and safeguards¶
Look up exact limits for a skipped file, a partial reply or a stopped program. For recovery steps, start with Troubleshooting; for what to review before collecting or sharing, see Privacy.
Size bounds¶
| Resource | Limit |
|---|---|
bf.yaml, machine registry, eval suite |
1 MiB each |
| YAML structure, including frontmatter | 32 nesting levels and 20,000 parser events; integers up to 4,300 decimal digits in any base |
| Authored note | 4 MiB |
| Note or record title | 4,096 characters; listings show 200, then … |
Note aliases, links, tags |
1,000 each |
| Search or page reply | Items end early near 32 KiB and continue at next_offset; home lists as many projects as fit the reply as printed, with projects_total |
| Any search or read reply | 4 MiB; a larger one fails with response exceeds its byte limit; narrow the request |
| Exact read | Text pages near 32 KiB; the first page adds all other fields, such as attributes |
| Paged note divided by headings | Opens with 4 KiB of text; its outline lists up to 200 sections |
| Backlink previews | 5 newest items per relation, excerpts of 160 characters; 64 relation groups, then backlinks_omitted |
| Source folder settle time | 5 seconds: a memories/SOURCE folder changed more recently is listed again at each search or read |
| Claims of a subject | 20 per relation and 50 in all |
| Record file | 16 MiB |
Record fields other than text |
2 MiB as UTF-8 JSON, so an exact read's first page stays within the reply limit |
| Record id | 1–4,096 characters and 7,988 once percent-encoded |
| Record text | 4,194,304 characters |
| Record links, aliases, field names | 1,000 each |
| Record URL, link, field value | 8,192 characters |
| Listed field value | 200 characters; longer values stay in the exact read |
| Listed fields of one item | 2 KiB of JSON, in field-name order; later fields stay in the exact read |
| Entries per record source or authored folder | 100,000 |
| Folder depth | 64 levels below a scanned folder |
| Note path | 7,988 characters once percent-encoded |
| Search query | 4,096 characters; the first 32 distinct words match |
| Search results per page | 50 |
| Page sizes | Folders and tags 200; memories/SOURCE 20; other pages 50 |
| Offsets | 2^53−1 |
| Skipped files per brain | 200 listed in problems, each error cut to 1 KiB with …, then a count |
| Validation problems, warnings | 200 each, then a *_truncated flag; 20 spellings per warning |
| Reasons named by one diagnostic | The first 5 distinct reasons, then and N more |
Relation targets |
64 prefixes of at most 1,024 characters |
| Retrieval suites | 100 suites per run, 200 cases per suite |
| Records changed by one collection | 99,999; narrow the window or split the source |
| Reprojection | 1,000 changed records per transaction; 200 failed records listed |
| Sensor output | 64 MiB by default, up to 256 MiB |
| Action routine output | 1 MiB by default, up to 4 MiB; a log routine's output only feeds its log |
Routine or prompt input from bf run |
1 MiB, ending within 10 seconds when piped |
| Prompt output | 1 MiB by default, up to 4 MiB |
| Prompt file, expanded prompt | 120,000 bytes each, as an argument or on standard input; below Linux's 128 KiB bound on one argument |
| Program name | 64 characters |
| Program command | The program and up to 127 arguments of at most 16,384 characters each |
Routine hooks |
16 events |
Program timeout |
1–3,600 seconds |
refresh, lookback, overlap, reconcile, silent_after |
up to 365 days |
keep |
1–10,000 routine actions; 1–50,000 prompt records |
| Program log | 1 MiB per logs/NAME.log; per run, the last 256 KiB of stderr and of a log routine's stdout |
Each record takes one folder entry. bf status warns above 80,000 entries without failing --check; a tree over the limit fails the scan and names the folder. Split a crowded source's sensor or archive its older records, and keep bulky imports in inputs/ or originals/, which are not scanned. A long pasted question matches only its first 32 distinct words after function words are dropped: keep the distinctive terms.
Page sizes bound one reply, not the result: follow next_offset. SQLite still ranks every match up to a deep offset, so very deep pages take longer.
Processes and logs¶
Sensors, routines and prompts run from the brain folder with direct arguments, without a shell. Their standard input is closed, except for what a hook or bf run --stdin pipes to a routine and the expanded prompt of a prompt command without {{prompt}}. They receive BF_BRAIN set to that brain, so a nested bf call reads the brain running it.
BF removes environment variables that could load code before your program starts, such as BASH_ENV or PYTHONPATH:
| Removed | Reason |
|---|---|
LD_*, DYLD_*, GCONV_PATH |
Can inject loader libraries or conversion modules. |
BASH_ENV, ENV, BASH_FUNC_*, SHELLOPTS, BASHOPTS, PS4, ZDOTDIR |
Can supply shell startup code, options or functions. |
PYTHON*, Java, Node, Ruby, Perl, PHP and .NET startup options, R_PROFILE_USER, LUA_INIT*, LUA_PATH*, LUA_CPATH* |
Can alter interpreter startup or module loading. |
Relative or empty PATH entries |
Could run an unexpected program from the brain folder. |
Other variables, including provider credentials and absolute PATH entries, remain. The list is best effort, not a sandbox. When a program needs dependencies, use an explicit runtime such as uv run --no-project sensors/example.py.
A timeout, cancellation or closed terminal kills the program's whole process group, as does output beyond max_bytes from a sensor or action routine; partial output never replaces stored records. Cancellation during startup waits until BF owns the new process, then kills its group too. A program that another process kills, such as the out-of-memory killer, fails naming the signal: program was killed by SIGKILL. A run ends when the program exits and its output closes. A background helper that keeps output open more than a second after the exit fails the run: redirect its output, for example to /dev/null. Watch and generated schedules allow 60 seconds after a stop request, so an interrupted record write can roll back.
Each run appends entries to the program's logs/NAME.log in the brain: a == TIME OUTCOME == heading when the program exits, followed by its stderr and a log routine's stdout, then another heading with the run's result, such as the records collected or the failure. The log keeps its newest whole entries within 1 MiB. Errors and run history name the log without quoting provider output. bf init ignores logs/ in Git and search never reads it, but a log can hold provider output: keep it private and never paste it into a public issue. Search and read keep a local usage.jsonl with the time, operation and result count, never queries or refs. Beyond 1 MiB, BF drops events older than 30 days, then the oldest ones beyond 768 KiB. bf status summarizes 7 and 30 days and marks a window this cut shortened.