Persona files
Persona files
Built-in personas ship with homebot. Your files go in
$XDG_CONFIG_HOME/homebot/personas/<id>.toml (normally
~/.config/homebot/personas/<id>.toml). A local file with a built-in ID
overrides that built-in. IDs are 1–32 ASCII characters: a lowercase letter
followed by lowercase letters, digits or hyphens. none is reserved for
turning the voice off. Run homebot persona ids for the current list of
messages a persona may reword.
schema = 1
id = "tester" # optional; must match tester.toml
name = "Tester"
emoji = "🧪"
tagline = "A careful eye on the details"
extends = "neatpik" # optional; omitted means the embedded Neatpik
lang = "en" # optional
[colors]
accent = { light = "#31466B", dark = "#AFC4E9" }
ok = { light = "#245D38", dark = "#9DE0AF" }
muted = { light = 240, dark = 248 }
[lines]
"inbox.header.count" = ["{n:# thing needs|# things need} you."]
schema = 1, a name and one emoji are required. id is optional but, when
present, must match the filename. The name is 1–32 characters. The tagline
is one line of at most 100 characters and cannot contain $ or a backtick.
lang is a BCP 47 language tag; English is the default. Colours may be
#RRGGBB or ANSI indices 0–255. Each light/dark token omitted here is
inherited from the parent. extends = "none" stops traversal of explicit
parents; embedded Neatpik still supplies missing colours and lines, followed
by the catalog’s English for messages with no persona line. Explicit parent
chains may have at most four files, the persona included (the embedded
Neatpik does not count), and cannot cycle. An explicit extends = "neatpik"
uses a local neatpik.toml if you have one; omitting extends always uses the
embedded copy. For each message ID,
the first file in that chain with usable lines supplies all its variants.
File safety and checks
User files must be regular files of at most 256 KiB. A symlink is accepted
only when it points to a regular file. Pipes, devices, sockets and folders
are refused; reading cannot block the background helper on a pipe. Unknown
TOML keys, invalid syntax, a bad header, an invalid ID or an invalid parent
make the persona unusable. An invalid line variant is dropped; usable
variants remain, and an ID with none falls through to its parent. homebot persona validate <id> checks the file itself, including warnings, and that
its extends target exists; it exits with an error for invalid lines. It does
not load the parent chain, so problems further up (a parent’s header, too many
levels, a cycle) show only in homebot persona show <id> or preview <id>,
which load the whole chain. validate <file.toml> reads a file directly.
homebot persona use <id> refuses a file with any error, even a single bad
line variant that would otherwise just be dropped.
Line IDs must be in homebot persona ids and marked for voice. A variant
must parse, preserve required and fixed placeholders, plural counts,
leading/trailing whitespace, punctuation that protects an appended command,
and the original number of line breaks. The validator rejects control and
format characters, including terminal escapes and bidi controls. In a line,
it allows only the same newlines as the English; the emoji field alone may
contain the joiner and variation marks needed for one emoji. It warns about
low colour contrast, uncertain emoji width, duplicate or long variants,
non-English language tags and possible added facts. A variant beyond the
hard length limit is rejected. Run homebot persona preview <id> to see the
voice in both themes, or add --event <message-id> and --all-variants to
inspect individual lines.
Selection and rotation
HOMEBOT_PERSONA (when nonempty) wins over persona: in homebot.yml; the
default is Neatpik. none selects the neutral voice. A missing or unusable
choice falls back to the embedded Neatpik, even if a broken local
neatpik.toml shadows the built-in. A configured failure raises
persona_broken in the inbox; a failing environment override warns once on a
terminal. The neutral English is used when a message has no usable variant.
For each message ID, homebot picks one variant per process and tries not to
repeat the previous process’s choice. Previous picks are stored per machine
in $XDG_CACHE_HOME/homebot/voice.json; a cache read or write failure only
changes the pick. The main nudge line uses a stable pick keyed on the inbox
items; notifications and the nudge’s urgent suffix always use the same variant
for a persona. Neither changes wording on every refresh. This state
stays outside the home repo.