# Brevi reference (for models)

Details kept out of the core guide. `brevi guide WORD` prints only the lines about one name.

Details kept out of the core guide, which every session reads. `brevi guide SECTION` prints one section; `brevi guide WORD` prints every line about a name.

## Strings
Strings interpolate: `"{name} is {age}"`, `"{-x} {xs.len()} {p.0}"` (`{` followed by a letter, `(`, `-`, `!` or `"` starts an expression, and strings may appear inside: `"{m["k"]}"`). Any other `{` is a plain brace; `\{` and `{{` always are, so `"{{"` is ONE brace (write `'{{'` for two); template tags such as `"{{#each "`, `"{{/if}}"` and `"{{else}}"` keep both braces.
Python format specs work inside `{}`: `"{x:.2f} {n:03d} {name:<10} {total:>8,}"`.
Escapes: `\n \t \r \0 \" \\ \{ \}`.
`'single quotes'` need no `\"` and keep `{` plain unless a name or `(` follows (`{{` is two braces), so JSON and template text is easy: `'{"id":{i},"error":"not found"}'`, `t.starts_with('{{#each ')`.
`"a".code()` is 97 and `97.char()` is "a". `"7".digit()` is 7 (-1 if not a digit). `len` counts characters; `chars` gives a list of one-character strings; `words` splits on any run of whitespace; `ints()` gives all whitespace-separated ints.
`s.slice(a)` runs to the end and `s.slice(i, i + 1)` is one character; negative bounds count from the end. `s.int().or(-1)` tests a number. `(a, _, b) = s.partition("=")`.

## Lists
`[0].repeat(n)` is n zeros; `unique` sorts and drops repeats; `(0..10).step(3)` is [0, 3, 6, 9]; `(0..n).rev()` counts down. `join(sep)` takes any items.
`xs.sort_by(f, desc)` sorts largest first when `desc` is true, keeping ties in order (as `sorted(xs, key=f, reverse=desc)`).
`first`, `last` and `pop` return the item itself and stop the program on an empty list; `min` and `max` fail on an empty list. `pop` and `remove(i)` return the removed item. In map/filter/any/all/count/sort_by, `(a, b) => b - a` unpacks a tuple item. `and`/`or` short-circuit.
`2.5.fmt(2)` is "2.50"; f64 `round(n)` rounds to n places.

## Type details
`let (a, b) = t` or `(a, b) = t` destructures a tuple. `Point(x, y)` works as a constructor when variables x and y exist. A `mut` parameter is called as `f(x)`. A return type is optional (`fn f(x: int) = x * 2`); write `-> T` if an error asks.
A missing map key reads as the type's zero (0, 0.0, "", [], dec 0). `print(a, b)` puts a space between.

## Python
Python spellings models write by habit are accepted: `True False`, `a if c else b`, `range(a, b, step)`, `for c in s`, `enumerate(xs) int(s) ord chr reversed`, `lambda x: x * 2`, `min(xs, key=f)`, `sorted(xs, key=f, reverse=True)`, `print(x, end="", sep=", ")`, `append strip split() startswith endswith isdigit items index get(k, d)`, `", ".join(xs)`, `&& || !` for `and or not`. `f"..."` is a plain string (Brevi strings already fill in `{x}`). Also `set(xs)` (a sorted list without repeats) with `s.add(x)`, `xs.extend(ys)`, `xs[::-1]` and `xs[::2]`, `divmod(a, b)`, `round(x)` and `round(x, 2)`, `enumerate(xs, 1)`, `m.setdefault(k, []).append(x)`, `defaultdict(int)`, `"%5.2f %s" % (x, s)`, `"{:>5} {}".format(a, b)`, `math.sqrt floor ceil`, `for line in sys.stdin`; `import sys`, `math`, `re` and `from collections import ...` lines are ignored. Also `rstrip() lstrip() strip(chars) splitlines() isupper() islower() isalnum()`, `heapq.heappush/heappop/heapify` on a plain list, `deque` with `popleft`/`appendleft`, `map(f, xs)`, `filter(f, xs)`, `list(xs)`, `int`/`str`/`float`/`len` as function values (`map(int, xs)`, `key=len`) and `sys.stdout.write(s)`. `Decimal(x)` is `x.dec()` and keeps its written places as Python does (`Decimal("1.50")`), with `d.quantize(Decimal("0.01"))` (half to even, or `rounding=ROUND_HALF_UP`); `csv.reader(sys.stdin)` or `csv.reader(lines)` gives the rows; `date.fromisoformat(s)` is `date(s)` and `(d2 - d1).days` counts the days between. `next(rows)` takes the first item; `xs.pop(i)` and `m.pop(k)` take an item out and give it back; `sorted(s)`, `enumerate(s, 1)` and `"-".join(s)` read a string by character; `sorted(m)` gives a map's keys; `OrderedDict()` is a map. The `re` module works as in Python: `re.compile(p)`, `re.match`, `re.fullmatch`, `re.search`, `re.findall`, `re.sub`, `re.split`, and on a compiled pattern `pat.match(s)` etc.; a match is `[whole, group1, ...]` (`[]`, which is false, when none), so `if m:`, `m.group(1)` and `m.groups()` work. `next(rows, None)` gives the empty value when nothing is left; `next(x for x in xs if c)` the first match. Also `zip(xs, ys)`, `Counter(xs)` with `most_common(n)`, `dict(pairs)`, `sys.exit(n)`, `s.count(sub)`, `zfill title center capitalize`, `xs.clear()`, `sys.argv`, `sorted(m, key=f)`, `date(y, m, d)`, `ljust rjust`, `split(sep, n)`, `rsplit(sep, n)`, `list(s)`, `set(a) - set(b)`, `s.update(xs)` / `m.update(m2)`, `datetime.date(y, m, d)`, `datetime.strptime(s, "%Y-%m-%d")`, `timedelta(days=n)`, `d.isoformat() toordinal() weekday() isoweekday()`, `calendar.monthrange isleap`, `format(x, spec)`, `isascii()`, `Fraction(...)` (as a decimal), `to_integral_value()`, `m.setdefault(k, v)`, `defaultdict(lambda: 0)`, `enumerate(xs, start=1)`, `bool(x)`, `sys.setrecursionlimit(n)`, `json.loads(s)`, `json.load(sys.stdin)`, `isinstance(v, T)` and `isinstance(v, (T1, T2))`, import aliases (`from datetime import date as Date`, `import datetime as dt`), `datetime.timedelta(...)`, `string.digits` / `ascii_lowercase` and the other `string` letter constants, `repr(x)`, `next(iter(xs))`, `groupby(xs, key=f)`, `del xs[a:b]`. A file with `def`, `class`, `global` or import lines prints values the Python way (`True`, `['a']`, `{'k': 1}`).

Functions are values: `ops = [add, mul]`, `for (name, f) in [("+", add)]: f(1, 2)`, `ops[0](3, 4)`. A map of functions works when at least one value is a named function: `ops = {"+": add, "-": lambda a, b: a - b}`, then `ops[op](a, b)`.

`None` works for int, float, str and tuple values: `best = None`, `if best is None or v > best: best = v`, `return None` from `-> int`. It is a reserved value, not an Option, so it cannot hold a user type.

## Tools
`brevi build f.bv -o app --release` builds an optimized binary. Runtime errors print `{"e":"runtime","line":N,"msg":...}`.
`brevi emit f.bv` shows the Rust. `--explain` on any command adds the guide lines under each error. `brevi check f.bv --fast` skips rustc. `del fn name` in a patch file removes a function.
A fixed typo prints `{"line":N,"fixed":"totl -> total"}`.
`allow read, write` at the top declares what a program touches (`read`, `write`, `native` for rust fn, py fn, crates and Python libraries such as `import subprocess`); in a Python file write it as a comment, `# allow read, write`, so the file stays valid Python. Under `brevi run --sandbox` and in the MCP tools only the caller grants capabilities (`--allow read,write,native`, `--allow-py requests`; MCP `allow`, `allow_py`), and an allow line in the file grants nothing; they refuse anything not granted, except path text (`os.path.join`, `pathlib.PurePath`) and `random`, which Brevi builds itself without `native`; a program with an `allow` line is held to it on every command. A refusal is final: it never falls back to a dynamic build, a library call or python3.
