lock family docs GitHub

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-hosts lines), 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_LOCKSQL turned on) needs its own flag, --allow-egress, --allow-host-keys, --allow-code or --allow-lock, on top of --yes; --dry-run shows which and writes nothing (LEA_LOCKMQ and LEA_LOCKFILE are not shared);
  • without --yes it 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.