lea · Start
Configure
~/.config/lea/lea.conf holds your settings as KEY=value lines (lea init writes it);
config/lea.conf in the installation documents every key and its default.
The deck's , opens a settings screen over the same file: the keys that matter, grouped, each
with its value, where it comes from (default, your file, the environment) and a one-line help.
enter or space flips a toggle, takes the next choice or opens a field (enter saves, esc
cancels); a value is checked before it is written. Sounds, the theme and the deck width apply at once; the screen says
when the others apply (after lea stop --all, or at the next lea). A key the environment sets
(LEA_PROJECTS_DIR, LEA_APPROVALS, LEA_APPROVAL_TIMEOUT) wins over the files, so it is shown
read-only. The screen runs in the deck on the host: agents cannot open or drive it.
| Key | Default | What it does |
|---|---|---|
LEA_PROJECTS_DIR |
asked by lea init |
the directory lea's agents see |
LEA_GIT_SSH |
empty | git SSH endpoints (host:port …) |
LEA_GIT_KNOWN_HOSTS |
~/.config/lea/git_known_hosts |
their pinned host keys |
LEA_LOCKSQL |
0, on when lox run runs a locksql lock |
1: wire lea for the locksql console of lox run (lea init --locksql) |
LEA_LOCKMQ, LEA_LOCKFILE, LEA_LOCKLOG |
0, asked by lea init; on when lox run runs a lock of the type and the key is unset (=0 keeps it off) |
let the agents reach a lockmq / lockfile / locklog console on this host |
LEA_LOCKSQL_REF, LEA_LOCKMQ_REF, LEA_LOCKFILE_REF, LEA_LOCKLOG_REF |
empty: the set of config/locks.lock |
a dev override of a client's release (lockfile v0.1.1 or later), for this release only; lea doctor warns while one is set |
LEA_LOCKHTTP |
0 |
send the agents' web requests through a LockHTTP gate (refuses LEA_GIT_SSH and LEA_OTEL_UPSTREAM) |
LEA_HUB |
1 |
follow the Lock Family approval hub (lockhub's facade socket: LEA_HUB_SOCKET, else $XDG_RUNTIME_DIR/lockhub/facade.sock): an agent whose Lock call waits for a decision there is suspended until it comes, and lox run, outside lea, decides them (lea shows and answers no ticket); while no hub answers, no agent is suspended, the deck says lockhub unreachable and lea doctor warns. 0: lea reads no hub and resumes the agents it suspended. Upgrading from v0.2: the default was 0; put LEA_HUB=0 in ~/.config/lea/lea.conf to keep that, then restart lea |
LEA_HUB_KEEPALIVE |
300 |
seconds (0 to 3600) an agent suspended on a hub ticket keeps its process before lea stops it alone, keeping its session for the decision or a message to resume it; read only with LEA_HUB=1 (changing it while the hub is off restarts nothing) |
LEA_LOX_UP |
none | obsolete (#300): set, lea and lea doctor warn and ignore it. Run lox run in another terminal instead |
LEA_INTERNAL_HOSTS |
none | private hosts the proxy may reach (format in config/internal-hosts) |
LEA_EGRESS_ALLOW |
empty (lea's default list) | the only web domains agents may reach, comma separated (subdomains included); default stands for lea's list, * opens the web |
LEA_NESTED_NETWORKS |
empty | networks your compose files expect, created at start |
LEA_RUNTIME |
empty (the engine's default, runc) | the OCI runtime of the agent containers only: runsc (gVisor) or kata (Kata Containers) puts a second kernel between the agents and the host's (a second kernel); applies to a container started after the change (lea stop, then lea) |
LEA_CPUS, LEA_MEMORY, LEA_MEMORY_SWAP, LEA_PIDS_LIMIT |
75%, 50%, no swap, 16384 |
the lea container's limits: CPUs (a share of Docker's, at least 2, a number such as 8, or 0), memory (a share of Docker's, a size such as 16g, or 0), memory plus swap (-1: no limit), processes and threads (0: no limit); the next lea applies them to a running container, or restarts it with them once no agent or session runs in it; rootless Podman needs Delegate=cpu cpuset io memory pids for user@.service (lea doctor checks it) |
LEA_APPROVALS, LEA_APPROVAL_TIMEOUT |
deck, 60 |
who answers permission requests |
LEA_PROVIDER, LEA_MODEL |
claude, empty |
the default provider and model of a new agent (providers) |
LEA_PROVIDERS |
~/.config/lea/providers |
your OpenAI-compatible endpoints and their key files |
LEA_AUTO_RESUME, LEA_RESUME_DELAY |
on, 60 |
resume agents stopped on a usage limit, so many seconds after its reset (0: off) |
LEA_STACK_IDLE |
10 |
minutes an agent stays idle before lea stops (not removes) the containers it started in the nested Podman (0: never); lea board lists what it freed |
LEA_QUESTION_REMIND |
120 |
minutes a control tower's question waits for your answer before the tower asks it again, once, prefixed with reminder: (0: never) |
LEA_HOLD_MAX |
30 |
minutes a pause of an inbox (the deck's H, lea hold) lasts before lea releases it (0: never) |
LEA_AGENT_CPUS |
4 |
each agent's CPU window, the least shared CPUs: the agent, its tools and its nested containers run there, so nproc, PHPStan, Go… see that many CPUs (0: no window) |
LEA_HEAVY_SLOTS, LEA_HEAVY_WORKERS |
0 (¾ of the CPUs ÷ workers), 4 |
heavy jobs (lea heavy -- <command>): how many run at once per container, and the CPUs and workers each gets |
LEA_ADMIT_CPU_PSI, LEA_ADMIT_MEM_PCT, LEA_ADMIT_MEM_PSI, LEA_ADMIT_IO_PSI, LEA_ADMIT_LOAD |
70, 85, 10, 40, 2 |
host pressure above which new agents wait: PSI in percent, memory in percent of the lea container's limit (the host's from 90 %), the host's load per CPU (0: that one off) |
LEA_SHED_MEM_PCT, LEA_SHED_MEM_PSI, LEA_SHED_CPU_PSI, LEA_SHED_AFTER, LEA_SHED_RESUME |
95, 30, 80, 30, 60 |
host pressure that pauses the lowest-priority agent once it lasts LEA_SHED_AFTER seconds (0: never), resumed after LEA_SHED_RESUME seconds of calm |
LEA_SOUND, LEA_AUTONAME |
on | the deck's sounds, automatic names (0: off) |
LEA_SOUND_ATTENTION |
freedesktop sound | the file of the sound lea plays when it needs you (0: off) |
LEA_OTEL_UPSTREAM |
empty | send Claude Code usage telemetry to this OTLP collector |
LEA_ASCII |
off | ASCII marks in the deck (1) |
LEA_THEME |
catppuccin (mono when NO_COLOR is set) |
the deck's colours: catppuccin, gruvbox, nord, tokyo-night, solarized, high-contrast or mono (no colour: bold, faint and reverse video); T in the deck picks one with a live preview, and the tmux pane borders follow it. An unknown name gives catppuccin |
Share a configuration with your team #
lea config export [--output FILE] [--include-personal] writes the shared part of your
configuration as one JSON file, fit to commit in a team repository: the keys your
~/.config/lea/lea.conf sets among LEA_GIT_SSH, LEA_EGRESS_ALLOW, LEA_OTEL_UPSTREAM,
LEA_IMAGE, LEA_PROXY_IMAGE, LEA_LOCKSQL, LEA_LOCKSQL_REF,
LEA_RELEASES_URL, LEA_NESTED_NETWORKS, LEA_K8S_NAMESPACE,
LEA_APPROVALS and LEA_APPROVAL_TIMEOUT (LEA_SOUND too with --include-personal), and the
content of your pinned git_known_hosts and of your internal-hosts file. Never exported:
LEA_PROJECTS_DIR and every path, any other key (skipped with a warning), lea's SSH key, forge
tokens, locksql and Vault credentials, ~/.claude and lea's state. A value or a line that does
not pass the import's checks (a locksql checkout's path, a @cert-authority line…) is skipped
with a warning.
lea config import FILE|- [--dry-run] [--replace] [--yes] reads such a file as data, never as
shell: only those keys and the two files are taken, and every value and line is checked with
lea's own rules (an approval mode, a timeout of 1 to 600 s, host:port endpoints, plain host
names and pinned keys without wildcards, https:// URLs, image references…). Anything else, a
value on more than one line or holding shell syntax, or a format newer than this lea reads, is
refused and nothing is written. The configuration it gives is loaded once more before any write.
It prints what changes (KEY: old -> new, + and - lines of the files), then:
- a change that widens what the agents reach (
[egress]:LEA_GIT_SSH,LEA_EGRESS_ALLOW,LEA_OTEL_UPSTREAM,internal-hostslines), pins SSH host keys ([host key]) or chooses the code lea runs ([code]: images,LEA_LOCKSQL_REF,LEA_RELEASES_URL) or wires a lock tool ([lock tool]:LEA_LOCKSQLturned on) needs its own flag,--allow-egress,--allow-host-keys,--allow-codeor--allow-lock, on top of--yes;--dry-runshows which and writes nothing (LEA_LOCKMQandLEA_LOCKFILEare not shared); - without
--yesit asks on the terminal (and refuses without one).
By default the import merges: the keys it carries replace yours, the others (LEA_PROJECTS_DIR,
your sounds…) stay; its files' lines are added to yours, and a host you already pinned to another
key is refused (--replace replaces your pins). --replace replaces the shared part: shared keys
the file does not set are removed, and the files it carries replace yours. The files are written to
~/.config/lea/git_known_hosts and ~/.config/lea/internal-hosts (LEA_GIT_KNOWN_HOSTS or
LEA_INTERNAL_HOSTS then points there), only when the import adds lines: a file you use at its
own path (an organisation's shared file) stays in use, untouched, when the import adds nothing to it; every file it replaces is kept as *.bak; every write is private (0600), at once,
and refused through a symbolic link. A key the environment sets beats the file: the import says
so. Changes apply after lea init (endpoints, keys, images, locksql) or lea stop --all
(approvals, egress), as it reminds you.