lea · Start
Quick start
brew trust davidgodefroid/tap # Homebrew asks you to trust a third-party tap once
brew install davidgodefroid/tap/lockfamily # the Lock Family: lea, lox and the Locks' launchers
cd ~/projects # lea's projects directory, not a project inside it
lea # the first run sets everything up
lox add locksql # when your agents need a database (lockmq, lockfile, locklog, lockhttp likewise)
brew install davidgodefroid/tap/lea installs lea alone. The journey is brew, lea,
lox add: there is no separate setup command to run first.
On a first run lea initialises itself: it checks that Docker answers, pulls and verifies the
images, installs its AppArmor profile on Linux hosts that use it (it needs sudo once: when
sudo would prompt, lea stops with "the AppArmor profile 'lea' needs sudo once: run lea init,
then lea"), records the projects directory, then opens the deck. Before all that, on a
terminal and while LEA_DECK is not set, it asks once whether you want the deck or your own
tool in the lea container (see Without the deck): it records the answer
and the command that switches it, and opens that tool instead of the deck on a no. The projects directory is LEA_PROJECTS_DIR
when you preset it (in the environment or in ~/.config/lea/lea.conf: a preset value wins over
the working directory); when it is unset, it is the directory you ran lea from. If that
directory cannot be one (/, your home directory or a parent of it, or one that overlaps
~/.claude or a credentials directory), lea says why and to
cd into the directory that holds your projects and run lea again, or LEA_PROJECTS_DIR=DIR lea.
Approvals live outside lea, in lox run. lea runs no lox command: it starts no hub (no
lox init) and shows no approval, ticket or lock console. Keep
lox run open in a
terminal of its own, outside lea (lox 0.9.0 or later: brew install davidgodefroid/tap/lox):
it starts the projects directory's hub and locks, shows every request of the agents, approves
reads on its own and asks you for connections and writes. When the projects directory declares
locks (.lockfamily/lockfamily.yaml) and no lox run serves them, lea says, as it starts:
"Open another terminal (outside lea) and run lox run to approve the agents' connections and
writes." lea starts anyway: the agents reach the locks' sockets, and their requests wait at the
hub until lox run decides them. The deck's status line and lea doctor say the same while it
does not serve. LEA_LOX_UP is obsolete: lea warns when it is set, and ignores it.
lox add is how a Lock
gets set up for lea's agents, run in lea's projects directory (lea reads .lockfamily/up.json
only there; a plain claude on the host uses the nearest one from the project up). A tool
(locksql, lockmq, lockfile, locklog) is on for lea once lox run runs a lock of its type there: you
need not turn it on, and LEA_<TOOL>=0 in ~/.config/lea/lea.conf keeps it off. A lock added
while lea runs reaches the agents once lea restarts (lea stop, then lea): restarting an
agent or the deck does not give a running container a new mount. Without Homebrew,
lea's own installer:
curl -fsSL https://leadeck.dev/install.sh | sh
lea
The installer checks the requirements, downloads the release for your platform and verifies its
checksum and the release's signature (see Verify a release), links
~/.local/bin/lea, then runs lea init, which asks for your projects directory and pulls the
images. The first agent is a Control Tower (see Control tower); in it, run
/login once (Claude Code's own login, kept per projects directory). Press n for another
agent, N for another Control Tower.
Requirements #
- Linux, macOS, or Windows with WSL2 (run lea from WSL).
- Docker Engine (Linux) or Docker Desktop, running, usable without
sudo; a patched host kernel (see How lea keeps your machine safe). - On macOS, tmux 3.2 or later (
brew install tmux); the Linux release brings its own. Without the deck (--no-deck), onlylea newneeds it. curl,tar,ssh-keygen.- A Claude subscription or API key for Claude Code.
lea never runs sudo itself, except once in lea init on Linux hosts where Docker uses
AppArmor: it installs lea's AppArmor profile, and only when that profile changed.
Verify a release #
Each release is signed keyless with cosign (Sigstore, GitHub
OIDC) by the release workflow, on its v* tag: checksums.txt (bundle
checksums.txt.sigstore.json, a release asset) and the lea and lea-proxy images, by digest.
The installer verifies checksums.txt with cosign before trusting it: the cosign on your
PATH, else cosign v3.0.6, which it downloads from Sigstore's GitHub release and checks against
the SHA-256 pinned in install.sh (it never fetches a "latest" cosign). It stops on a bad
signature, on a missing signature, and when no cosign can be had: it never installs on the
checksum alone. The only exception is v0.1.0 and v0.1.1, which predate signing: their
checksums.txt must then be the genuine one, whose SHA-256 the installer pins (it stops
otherwise), and the install goes on by checksum, with a warning. LEA_REQUIRE_COSIGN=1 removes
that exception too. lea update and the background update verify the signature the same way
before they run the new release's installer. Each tag also bumps the lea formula of the
Homebrew tap (brew trust davidgodefroid/tap, then brew install davidgodefroid/tap/lea), from the same signed checksums.txt.
curl -fsSL https://leadeck.dev/install.sh | LEA_REQUIRE_COSIGN=1 sh
By hand, with the same identity and issuer:
cosign verify-blob --bundle checksums.txt.sigstore.json \
--certificate-identity-regexp '^https://github\.com/DavidGodefroid/lea/\.github/workflows/release\.yml@refs/tags/v[0-9]' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
checksums.txt
cosign verify \
--certificate-identity-regexp '^https://github\.com/DavidGodefroid/lea/\.github/workflows/release\.yml@refs/tags/v[0-9]' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/davidgodefroid/lea:<version> # and ghcr.io/davidgodefroid/lea-proxy:<version>
The limit: the installer comes from the same GitHub account as the release. The signature protects against a tampered asset or mirror, and every signature is logged publicly (Rekor), so it can be audited; it does not replace trusting that account.