Changelog · Changelogs
lea changelog
Unreleased #
Features:
lea web(#414): the deck in your browser. It serves, on127.0.0.1only, a live board of the lea's agents (a tree of leads and their agents, with state, status, next step, blocker, branch, context use, cost, unread messages), each agent's messages with a box to write to it, rename, pause, hold, role and stop, a form to start an agent or a Control Tower, the tower's chat with its questions, and the permissions agents wait on, with Allow, Deny and Always. While a browser shows it, permission prompts wait for it as for the deck in tmux. The printed link signs one browser in once (a 32-byte token traded for anHttpOnly,SameSite=Strictcookie); foreignHostorOriginheaders are refused, and only a fixed list of the daemon's methods, for this lea's agents, is reachable. Phone width, light and dark, keyboard shortcuts.
Changes:
- lea no longer copies on select (#419): a drag in an agent's terminal no longer enters tmux's
copy mode, copies the selection or flashes "Copied". Claude Code copies on select itself, through
the same clipboard bridge: a copy worked and looked one way or the other depending on whether
Claude held the mouse. In a pane
whose program does not take the mouse (a split shell, the scrolled-back history),
shift+drag lets your terminal select, as in any tmux.ctrl+vpaste and wheel scrolling are unchanged.
Fixes:
- A granted
git commitruns at once (#393): the pinned commit no longer runsrm -rfin itssh -cscript (Claude Code's safety check asked for approval, hook allow or not, and the commit timed out). It copies the index tolea-commit/indexin the worktree's git directory, reused and overwritten at each commit, besidelea-push(#381); nothing is left in/tmp.
v0.15.1 (2026-11-09) #
Fixes:
-
The control tower replies in the language of your latest message (#396): it switches as soon as you do, its agents' messages (mostly in English) never change it, and a wake-up keeps the last language you used. In tower mode lea reminds it on every prompt; nothing changes outside it.
-
LEA_LOCKHTTP=1 leano longer starts lea without the gate in silence (#398): the configuration (lea's defaultLEA_LOCKHTTP=0, or yours) still wins over the environment, since lea-proxy and its gate are shared by every lea on the machine, but lea now warnsLEA_LOCKHTTP=1 in the environment is ignored (the configuration says LEA_LOCKHTTP=0): set it in ~/.config/lea/lea.conf, then lea stop --all, and lea; the same forLEA_LOCKHTTP_MITM.lea doctorprints alockhttpline in every case:off, with how to turn it on, oronwith the gate's state. -
lea updateon a Homebrew install runsbrew updateandbrew upgrade davidgodefroid/tap/lea, then the new Cellar version refreshes its images and checks the dependencies (#354). It used to run lea's own installer, which left a second lea in~/.local/share/lea-install, linked at~/.local/bin/lea, beside Homebrew's. A failing brew failslea updatewith brew's status; without brew onPATH, lea refuses to update a Homebrew install itself. The background update installs nothing on a Homebrew install, even withLEA_AUTOUPDATE=1: it only announces the release.lea initno longer links~/.local/bin/leato the Cellar version on a Homebrew install (brew links<prefix>/bin/lea; that link outlivedbrew upgrade). install.sh and git installs are unchanged. -
Docker out of address pools is reported as such (#397): when Docker refuses lea's network with
all predefined address pools have been fully subnetted, lea quotes Docker's message and says to remove unused networks (docker network prune) or adddefault-address-poolsin/etc/docker/daemon.json, instead of asking for Docker Engine 28.0 orLEA_ALLOW_GATEWAY=1. The gateway-mode advice comes only when Docker rejectsgateway_mode_ipv4itself, with Docker's message; any other refusal is Docker's own message.lea doctorcounts Docker's free address pools and warns when none is left.
v0.15.0 (2026-11-08) #
Changes:
- Pause the tower's inbox while you answer it (#95):
Hin the deck (or Hold messages in a row's menu) orlea hold [--off] [AGENT]holds the messages agents send it; your notes and the replies to what it sends during the pause still arrive, an agent'saskto it fails at once, and the row shows⏸ N. On release (yours, or lea's afterLEA_HOLD_MAXminutes, 30; 0: never) the tower gets them all and briefs you once. Only the user pauses or releases an inbox.Qin the deck (Questions… in the tower's menu) lists its questions to you and drops a queued one; the tower's status line shows❓ 1 · 3 queuedand⏸ messages paused (N). - Security: the text of the tower's next question, and of a question's reminder, reaches its
context framed as untrusted data, as
msg_inboxframes an agent's message, with its control, bidi and zero-width characters replaced (#95): an agent's words in a queued question could pass for lea's instructions. - One handle per agent,
label (name)(#356, #368): the deck row, the tower,lea boardandlea agentsname an agent by its label then its name. A lead gives a spawn alabel(agents_spawn,agents_request_spawn); without one, an agent started with a brief is named after its brief, not after lea's first prompt. Labels are unique among the running agents of a container, whatever their case: an automatic label that clashes gets2,3…, and the user's rename to a running agent's label is refused. An agent's label, or the namer's from an agent's brief or prompt, is plain ASCII (letters, digits, spaces,- _ . #) and never reads asuser,the user,lea,tower(alone or numbered:Tower 2,user #1) or holdsControl Tower,Tower ControlorCtrl Tower(The Control Tower,CT), whatever its case, punctuation or look-alike digits (C0ntrol 7ower): those are the user's and lea's. lea config claude(#334): your base settings for Claude Code in lea, without editing a file or rebuilding the image:defaultMode, entries to add to or remove fromallow,ask,denyandadditionalDirectories(lea's built-in rules included),env,model,language,outputStyle,alwaysThinkingEnabled;lea config claudealone shows every effective setting with its source. Kept inclaude.jsonnext tolea.conf, never in~/.claude/settings.json; they outrank the host'spermissionsand apply to the containers started from then on. lea's hooks,allowManagedPermissionRulesOnly,disableBypassPermissionsMode, the status line and lea's own variables are refused with the reason. Host only;lea doctorlists the overrides,lea config exportnever carries them.- The deck's first agent is a Control Tower (#339):
lea deck-openwith no agent running starts a lead on Claude labelledControl Tower, whose first prompt runs/lea:control-tower;Nstarts another (Control Tower 2…), and the provider picker moves fromNtoP. Host only. - The agent containers no longer rely on Docker's default resolver (#98): lea starts them with
--dns 192.0.2.1(TEST-NET-1, never routed, out of reach of the internal network), so a lookup of an external name, from an agent or a nested container, is never forwarded to the host's resolver (lea-proxy, which resolves names for the agents, is still answered).lea doctorfails on a running container that resolves an external name, and warns about one started without it (lea stop, thenlea).make test-isolationchecks that no lookup, direct query to a public resolver or long TXT name reaches a decoy DNS server, on the decoy network or on the host's 127.0.0.1:53. - The control tower asks you one question at a time (#95): its new
user_asktool (leads only) opens a question when none is open and queues it otherwise, by priority (incident,blocking,normal) then in order; the queue is kept in lea.db. Your next prompt, or your answer to the tower'sAskUserQuestion, answers the open question: lea tells the tower which agent the answer goes back to and gives it the next question. While you have a question, lea denies the tower any otherAskUserQuestionand holds the questions agentsaskit until you answer. One left unansweredLEA_QUESTION_REMINDminutes (120; 0: never) is asked again once, prefixed withreminder:. The deck shows the tower as❓ 1 · 3 queued;lea questionslists the questions andlea questions drop IDdrops a queued one. - A
gh pr create --body-fileorgh release create --notes-filerefused for its file now says why (#384): the hint names the file (cut past 80 characters) and the rule the matcher applies (a relative path inside the worktree of at most 256 characters fromA-Za-z0-9._/-, not starting with.,-or/, with no empty,.or..segment, outside.git) with an example,pr-body.md. - Deck colour themes (#337):
LEA_THEMEpickscatppuccin(the default),gruvbox,nord,tokyo-night,solarized,high-contrastormono;Tin the deck (or its right-click menu) opens a picker that previews each theme live (enterkeeps and saves it,escrestores), the settings screen's Theme row applies at once, and the tmux pane borders follow.NO_COLORgivesmonowhileLEA_THEMEis not set; an unknown name givescatppuccinwith a warning. - The agents show your own Claude Code status line (#374): when your
~/.claude/settings.jsonhas astatusLinecommand,lea statuslinestill reports the agent's context and usage to the daemon, then runs your command with the same JSON (1.5 s at most, killed past it) and prints its output; lea's own line comes back when it fails, prints nothing or times out. A script below~/.claudethe command names is mounted read-only into the containers (and lea-ctl). release-creategrant action (#353):gh release create <tag> --verify-tag [--title T] [--notes-file F | --generate-notes] [--prerelease] [--latest], one plain command at the root of the agent's worktree, pinned like every allowed gh call, for a pushed semver tag matching the grant's--tagglob (lea allow release --repo R --tag 'v0.15.*', orgrants_requestwithtag).--draft,--target, assets and the othergh releasesubcommands stay uncovered;delivernever includes it. A call the grant does not cover tells the agent the form, the glob andgrants_request.- In the deck, a folder header's summary sets each state mark apart from its count (
6 ◐ 6, not6 ◐6) (#355): the marks are East Asian Ambiguous width, and a terminal that draws them wide drew the half-moon over the digit. - A granted
git push -u origin <branch>from a worktree branch created fromorigin/maingoes through at the first try (#381): the pinned push no longer runsrmin itssh -cscript (Claude Code refused it, hook allow or not), it runs from a bare repository reused in the worktree's git directory; once pushed, it recordsorigin/<branch>and-umakes it the branch's upstream (it did nothing, so the branch kept trackingmain). The agent prompt says to create the worktree withgit worktree add --no-track. - The first run and upgrades ask the deck question (#335): the first
leaon a terminal (the Homebrew journey,lea init --first-run) asks "Use the lea deck ...? [Y/n]" and, on no, the command to start in the lea container, before it opens anything. An install whose user config has noLEA_DECK(made before v0.10.0) gets the same question once, at its nextleaon a terminal. The answer is recorded (the end of input records the deck) with the command that switches it; no terminal, orLEA_DECKalready set (environment or user config): no question, the deck as before. lea allow(#319): one allowance model and one command for whatlea grantandlea deliverydid.lea allow deliver(push, pr, merge, delete-branch),lea allow merge issues --repo api,lea allow push --branch 'feat/*' --agent dev-1 --for 2h,lea allow stop-finished: one call records one set of grants, shown as one line bylea allow(capabilities, repositories and pins, time left, last use) and revoked as one unit bylea allow off N(or a capability,deliver, or everything of the lea).lea allow loglists this lea's uses. The container is always the projects directory's lea, and every forge capability is pinned to each repository'sorigin(GitHub or GitLab,--gitlab HOSTremembered), with the pin confirmationlea delivery onhad: on a terminal,record these? [y/N]; off one,--yes DIGEST. Recorded again, an allowance that holds until revoked keeps the ids of its unchanged rows.- Lifetime: an allowance holds until revoked unless
--for DURATION(1m to 30 days) says otherwise, hand grants included (they used to expire after 8 h). - The deck has an Allowed screen (
g): the lea's allowances, withxto revoke one after the usual confirmation. - An agent's first prompt lists the forms lea runs without asking only for what covers it when it
starts; otherwise it says
lea allow deliver --repo <repo>lets it push and open PRs without asking. A merge, PR or push no allowance covers gets a hint naminglea allow <capability> --repo <repo>. lea doctorreportsallowances(the pin and credential checks of delivery).- Deprecated:
lea delivery on|off|statusandlea grant add|lsare aliases oflea allowfor this minor release, with a notice; they go in the next one.lea grant add --github Xis refused when X is not the repository's origin. The daemon methodsgrant_add,grant_listanddelivery_setare replaced byallow_set,allow_listandallow_off(host only). lea.dbgainsgrant_setsandgrants.set_id: on open, a lea's standing grants become onedeliverallowance and every other active grant an allowance of one; ids do not change, and an older lea still reads the table.- Agents point the user to
lox run, neverlox uporlox approve(#343): a newlock_hinttool (read-only, agents only) tells an agent whose Lock client finds no console what the user must do, from lea's state of the lock rather than a guess: "lock NAME waits for you: answer in lox run (or lox attach NAME)" whilelox runruns it, "start lox run in the projects directory" when none serves, "restart lea" for a lock added while lea runs; never a command that restarts or recreates a lock. The first prompt sends agents to it, and the agents' status line says "no lox run: start it in the projects directory" while none serves. TheLEA_LOX_UPwarning and LockHTTP's refusal page no longer mentionlox uporlox approve. - The "Copied" notice a mouse selection's release shows closes after 0.6 s instead of 1.5 s (#373).
- A granted
gh pr createorgh release createwhose--titlereads like the file flag (-F,--body-file,--notes-file) hands gh the body or notes file the parser approved (#382): the pinned command took the file's index from a second scan of the args, which took the title's value for the flag and swapped the wrong argument for-. - A lead's child spawned without
repostarts where its lead works (#364): the lead's repository, or without one the lead's own directory, not the directoryleawas last launched from. An explicitrepostill wins;agents_spawnwithforkeeps the request's repo and branch.
v0.14.1 (2026-11-08) #
Changes:
- A spawn never gets the name of an agent that still runs (#350, #358): a row marked done while its session lived (a nested Claude's SessionEnd, or a missed reconcile) could be reused in place, and the live session received the new brief, repository and branch. A name now comes free only once its row is removed and no running process answers to it; hooks from another Claude session than the agent's own are ignored; reconcile marks an agent done only after a 3 s grace check.
- In the deck, an agent that gets back the name of a done or forgotten agent leaves that agent's folder and joins its own lead's folder, or stays at the root (#340, #357).
- Removed: rtk is no longer installed in the agent image (#359, #360). Nothing in lea called it, and its release download was an extra fetch on every image build.
v0.14.0 (2026-11-08) #
Changes:
lea egress allow|deny|list|denied(#345): the user allows a domain from the host, live. The proxy's allowlist moves into a file on its tmpfs;lea egress allow DOMAINchecks the domain asLEA_EGRESS_ALLOWis checked (no URL, IP literal, wildcard or DNS-over-HTTPS resolver; at most 64 entries), writes it back tolea.conf(defaultkept, private, no symbolic link followed) and reconfigures squid in the running proxy: no proxy, container or agent restart.denytakes a domain back,listshows the list,deniedthe hosts the proxy refused lately (the access log now carries squid's error name). An editedLEA_EGRESS_ALLOWis applied the same way at the nextleainstead of recreating the proxy. The command is host-only (refused inside lea, kept on the host withLEA_CTL=1); no MCP tool or grant reaches it.- Refusal pages start with one plain line naming the host, why, and, for the allowlist, the exact
lea egress allowcommand; an agent's first prompt says how to recognise an egress refusal behindCONNECT tunnel failed, response 403and to hand the user that command instead of working around the proxy. - The deck's width no longer changes when a drag crosses the divider (#341, #347): selecting text in the deck, or in a program that takes the mouse, then moving over the divider resized the deck and stored the new width. Only a press on the divider itself starts a resize now.
- Granted
ghcalls work again (#348, #349): lea's read-only forge-gh config now carries gh's currentversion: "1", so gh no longer migrates it and tries to write it back, which made every granted call fail withfailed to write config after migration.
v0.13.0 (2026-11-07) #
Changes:
- Grant requests (#342, #344): a lead turns the user's approval given in its chat into a lea grant
its children honour. The new
grants_requesttool (leads only, checked likelea grant add) queues a request and records nothing; the user decides on the host withlea requests,lea approve gN [gM...] [--expires 30d],lea deny gN [reason]orlea grant requests|approve|deny. An approved grant covers the lead and its children only. The lead is told on approval, denial and expiry (a day without an answer). A merge no grant covers now tells the agent to ask its lead for one. The control tower may callgrants_listandgrants_request. release-taggrant action (#342, #344):git push origin refs/tags/vX.Y.Z, one new semver tag on a commit of the remote's default branch, pushed by lea's pinned command without force. Every other tag push stays a hard deny;lea delivery onnever records it.
v0.12.0 (2026-11-07) #
Changes:
- lea's agents start in the permission mode a local Claude Code starts in (#333, #336): the managed
settings no longer pin
defaultModetodefault(manual), so Claude Code's own default applies (auto on the accounts that have it). A validpermissions.defaultModein the host's~/.claude/settings.jsonis still the agents'; bypass stays disabled. An agent that writes adefaultModeinto its own settings can change its own mode, never to bypass.
v0.11.0 (2026-11-07) #
Changes:
- locklog (#324, #330):
LEA_LOCKLOG=1(or a locklog lock underlox run) lets lea's agents read logs through a locklog console. Records are masked, and an unmask is approved atlox run. Its client is in lea's image (config/locks.lock, now the lockkit v0.13.1 set with locklog v0.2.1 and lox v0.10.0), Codex agents get it as an MCP server, andlea locklog,lea init --locklogandlea doctorknow it.
v0.10.0 (2026-11-06) #
Upgrading from v0.9.x:
- lea refuses to start an agent container on an internal network without
gateway_mode_ipv4=isolated(#307): Docker Engine older than 28.0, Podman, or a network left by an older lea. Upgrade Docker or remove the old network;LEA_ALLOW_GATEWAY=1opts in to the weaker network.lea doctorprints each internal network's gateway mode and fails on a non-isolated one. - The GitHub token now lives in the proxy only (#304): agents use it through
ghandgitbut cannot read it. A token found in an agent's state is adopted once, when the proxy has none, and is otherwise discarded;lea github loginsets it. - The agent image has no
sudoand no setuid/setgid file any more (#100, #305). - The deck is optional now (#323):
lea config deck offruns your own tool (Claude Code by default,lea config tool CMD) in the lea container instead,lea config deck onbrings it back. Since #335, an install withoutLEA_DECKis asked once at its nextleaon a terminal.
Changes:
- Optional deck (#323):
LEA_DECK=0(lea init,install.sh --no-deck [--tool CMD],lea config deck on|off,lea config tool) runs your own tool in the lea container.lea attach [--print] [AGENT];lea requests,lea approveandlea denyanswer lea's permission and spawn requests, with desktop notifications without the deck;lea board --watch. - Plugins and permissions work inside lea (#111, #311): each projects directory's container has its
own writable copy of
~/.claude/settings.jsonand~/.claude/plugins, kept across restarts and never written back to the host, so/plugin install, marketplaces and/permissionswork. lea's hooks are now in Claude Code's managed settings, so an agent cannot remove them, andlea doctorchecks them. LEA_RUNTIMEruns the agent containers on gVisor (runsc) or Kata Containers (kata), a second kernel between the agents and the host;lea doctorshows each container's runtime (#106, #309).- Limits (#132, #303): lea restarts an idle lea container to apply limits it could not apply in
place; rootless Podman without the cpu, memory or pids controller starts without that limit
(with a warning) instead of failing;
lea doctorreports stale limits and cgroup delegation. Fixed: limits were never applied to running containers on Docker 29 (PidsLimitprinted as<no value>). - The deck's width is resizable (
</>, a border drag,LEA_DECK_WIDTH), persisted across restarts and clamped to 24..min(60, half the window) (#275, #318). - Deck folders are calm section headers (#295, #322): each shows its agent count and a status summary (needs you, working, limited, done); folder agents lose the vertical guide, and a blank line separates the folders and the root agents after them.
- An idle agent is woken for a message in its inbox after a lea daemon restart, after its session is resumed, and after more than an hour idle (#297, #317). Wakes are held while the agent is paused or limited, are rate-limited per agent, and show as "woken by lea" in the deck.
- Security (#100, #305): lea's seccomp profile is Docker's default (pinned moby/profiles) plus a
reviewed, justified list of the syscalls the nested Podman needs; keyctl, reboot, syslog,
fanotify, the new mount API's fsopen family and others are refused again. The AppArmor profile
restores docker-default's
/procwrite denies. - Security (#102, #308): lea-proxy runs confined: all capabilities dropped except SETUID/SETGID, no-new-privileges, a read-only root, pids and memory limits; squid, the TCP forwarders and lea-keyproxy no longer run as root.
lea doctorand the README list the credentials an agent can still read (#103, #304).- Bash guard: a jq filter such as
.[]is no longer denied as a glob on a protected file; glob brackets follow bash's rules (still failing closed), and redirect targets are checked as globs (#273, #314). - Deck: an agent spawned by a lead in a folder always joins that folder, even when a layout save happens in the same second (#296, #316).
- Drag-selecting in a pane and holding the pointer at its top or bottom edge (or past it) keeps scrolling the history, faster the longer it is held (#280, #321).
- install.sh creates its install directories 0755 under any umask; an existing group-writable one gets a warning with the fix (lockfamily#15, #313).
- Tests: the daemon's keepalive, subagent TTL and stack idle timers are driven by the test instead of racing the wall clock (#278, #315).
v0.9.0 (2026-11-06) #
Upgrading from v0.8.x:
lox upis gone: lea no longer starts the hub or the locks. Approvals happen inlox run(lockhub v0.9.0), run in another terminal of its own;lea doctorneeds lox 0.9.0 (brew upgrade lox).LEA_LOX_UPandLEA_SOUND_DONEare removed: lea warns aboutLEA_LOX_UPand ignores it, and no longer usesLEA_SOUND_DONE(a turn end rings no sound).LEA_LOCKSQL_IMAGEis obsolete too (warned). Remove them from your configuration.
Changes:
- Approvals move out of lea into
lox run(#300): lea no longer runslox init,lox uporlox attach, and shows no hub panel, hub ticket, lock console or lock request. When the workspace has locks and nolox runserves them, lea's start, the deck's status line andlea doctorsay to run it, and lea starts anyway (agents' requests wait).lea lock, the deck'sL/H/Y/Okeys, the agents'lock_requesttool andLEA_LOCKSQL_AGENT_PROFILESare gone. This supersedes #291 (merged after v0.8.1, naming the start question a waiting lock console asks): lea attaches to no lock console any more. - lea's image ships the Lock clients as one set,
config/locks.lock(#134): lockkit v0.13.0, with locksql v0.17.0, lockmq v0.8.0, lockfile v0.8.0, lockhttp v0.8.0 and lox v0.9.0, each pinned by digest or checksum and verified by its cosign signature. The set is bumped as a whole.lea doctorchecks each lock lox runs against lea's client of its type (from the image it pins, or the console's hello handshake) and says what to run (lea update, orbrew upgrade loxthenlox add TYPE NAME --version); a pair with different protocols fails. lea no longer builds a locksql image or updates Lock releases.LEA_<LOCK>_REFis kept for this release as a dev override thatlea doctorwarns about. - Sounds ring only when lea needs you (#294): a question or request to you, a permission or an approval to give, an agent blocked on a human. A turn that simply ends no longer rings.
- Codex agents pass
LEA_AGENTandLEA_AGENT_TOKENto the Locks' MCP servers, so Lock grants, plans and tickets name the requesting agent (#253, #302).
v0.8.1 (2026-11-04) #
a,dandYwork after a click on the hub ticket shown in the right pane (#289): a click (left or right) on the ticket pane keeps the keyboard on the deck, and ctrl+space no longer stops on it. The wheel still scrolls the ticket.- The ticket pane keeps lea's own words (the name a production ticket awaits, a refusal, the
approve-all report, the keys) in a banner above the ticket, each line marked
▌; the ticket's own text can never draw such a line. An unknown key in the hub panel now says thataapproves,ddenies andescleaves.
v0.8.0 (2026-11-04) #
- Hub tickets are shown whole in the large right pane (#284): selecting a ticket in the hub panel
(
H, the arrows or a click on its line) shows it where the agent's session shows, with its warnings, production, the agent's note, instance, requester, created and expires first and the Lock's screen under them; the wheel,j/kand the page keys scroll it.escbrings the agent back. There is no fold, noenterdetails and novstep any more. aapproves the ticket shown andddenies it, at once, once the right pane shows that very ticket (a key pressed twice never answers the next one). A ticket lea had to cut is still refused. A hub refusal shows under the ticket with its fix (lox upfor a hub older than lockhub 0.7.0, orlox approve).Yin the hub panel approves every pending ticket after one question naming how many and how many are production (approve 3 tickets, 1 production? y/n). Tickets that ask for a typed name, cut ones and duplicates are skipped and listed; refusals are listed with their reasons.- At start, when a lock's console waits for its start question, lea attaches to it after the [Y/n] prompt and detaches by itself as soon as the lock serves, then goes on into the deck: no Ctrl-P Ctrl-Q any more (it still detaches sooner). Several waiting consoles are answered one after the other, each named "n of m" (#282).
- After
brew upgrade lea,leaandlea stop --allstop the daemon of the previous version, even when Homebrew removed its directory (#283). A daemon that ignores SIGTERM for 5 s gets SIGKILL, and lea says so in one line.
v0.7.1 (2026-11-04) #
- The done sound rings when the agent's turn really ends (#274): it no longer rings 10 s or more after the deck shows the agent done, nor while the agent works again after a Stop hook blocked its stop. It waits for an agent-type Stop hook's verdict (60 s at most), and its quiet wait drops from 10 s to 3 s. The hook binary in a running container keeps the old behaviour until the agent restarts.
v0.7.0 (2026-11-04) #
- The deck asks for a name to type before approving a hub ticket only when the hub's queue item
names one (its
retype, lockhub 0.7.0); otherwiseaapproves at once, production or not (#260). A hub older than lockhub (lox) 0.7.0 sends noretype: approving a production ticket from the deck is then refused by the hub, and the refusal stays under the ticket's card until the selection moves (uselox approve, or upgrade lox). - The hub panel is clickable (#256): a click on a ticket selects it, a click on the title enters
the panel, and
enter(or a click on the selected ticket) shows its details: who requested it, when it was created and when it expires. The panel's title names its keys. A ticket whose lock was removed reads as an orphan on approve, deny, reveal and renew, and any other hub refusal names its code and HTTP status. - A ticket requested by an agent that runs its Lock through the shell (
locksql run) now reaches that agent once decided (#261): lea delivers the decision to the agent the requester names, in its inbox, and wakes it when idle. The card still marks the requester as unverified. - Renaming an agent or a folder, naming a new folder and editing a text setting open a modal over the deck instead of a field in the status line (#257).
- Agents inside a folder are indented under it (#258).
- At each start, lea checks the console of every lock its agents mount (#259): a console that is
not running says to run
lox up; one waiting for its start question sayslox attach NAME, and at a terminal lea offers to attach to it now.LEA_LOX_UP=1also runslox upwhen the hub runs but a lock's console does not. - After
lea stop, an agent whose Claude session never wrote a transcript (it sat on its login or trust dialog) starts afresh instead of failing with "No conversation found" (#255). - A delivery grant covers
gh pr merge N --delete-branchandglab mr merge N --remove-source-branchon the caller's own branch (#271). A merge, create or push that the caller's grant would cover in another form gets a hint naming the covered forms.
v0.6.1 (2026-11-03) #
- The image ships locksql 0.16.0. It brings grants: with
locksql_grant(CLIlocksql grant), an agent asks once for a bounded read scope (tables, duration, budget) and, once you approve it, runs its covered masked reads without a ticket each. Grants need lockhub (lox) 0.6.0 or later; an older hub refuses the grant's ticket and everything else works as before. lea already gives each agent theLEA_AGENT_TOKENa grant needs. - It also brings locksql 0.15.0's TLS change: transport security is left to the database driver,
and a remote profile without
tlsnow connects withpreferinstead ofverify-full(listed once on the first start after the upgrade). Settls = "verify-full"in a profile to keep verifying the server's certificate.
v0.6.0 (2026-11-03) #
LEA_LOX_UP=1in~/.config/lea/lea.conf(default0, #243): whenleastarts and the projects directory has.lockfamily/lockfamily.yamlbut no running hub, lea runslox upthere first, then lists each console waiting for its start questions with itslox attach NAMEline. A failinglox upis a warning; lea starts anyway.lea init --locksqlwith a locksql lock declared in.lockfamily/lockfamily.yaml(found by its type) builds no console image when the lock pins its own, skips the profile wizard and says the one step left:lea stop, thenlea. It warns when the lock'sallowed_uidslacks your uid.lea init --<tool>or--no-<tool>configures the tools it names only: the other lock tools keep their setting and are asked about on a barelea initalone./lea:tower-controlremoved, use/lea:control-tower.- Deck folders are simpler (#241): a click on a folder folds or unfolds it,
hon an agent folds its folder,utakes an agent out of its folder (also Remove from folder in its menu),xon a folder asks before deleting it, and the status line shows the keys of the selected folder. - A folder can take a colour (
c, or Colour… in its menu), saved by name in the deck's layout. - An agent a lead starts joins the lead's folder.
- The deck shows every pending ticket of the hub, attributed to an agent or not (#244): a
⚠ hub · N pendingpanel above the rows, one line per ticket with its lock, instance, risk, the agent it waits for (orno agent), its age and time left.Hmoves the selection into the panel, wherea,d,v,oandract on the selected ticket as on a card. A ticket for no agent rings the attention sound. - A stray
ptyped on the deck no longer freezes an agent (#240):pon a running agent asks first (ypauses it, any other key cancels),pon a paused one resumes it at once, andenteron a paused agent resumes it before focusing it. The row menu's Pause / Resume stay one click.
v0.5.0 (2026-11-01) #
- The image ships locksql 0.14.0, lockmq 0.7.0 and lockfile 0.7.0, which reach one lock among
several with
--instance. - lea initialises itself on its first run: it checks Docker, pulls and verifies its images,
installs its AppArmor profile, records the projects directory and starts the Lock Family hub
with
lox init. The journey isbrew install davidgodefroid/tap/lockfamily,lea, thenlox addfor each Lock.loxmust be on thePATH, 0.5.0 or later (config/host-minimums). - An image lea cannot pull stops it with the command to retry; lea no longer builds an unverified
lea:devin its place and records it. - The projects directory of a first run is
LEA_PROJECTS_DIRwhen it is preset, else the working directory. - A lock tool (locksql, lockmq, lockfile) is on as soon as
lox upruns a lock of its type, unlessLEA_<TOOL>=0is set in the user's configuration. - Several locks of one tool reach the agents, each on
/run/<tool>/<instance>; a Codex agent gets one MCP server per lock, and lea tells a Claude agent to pass--instance NAME. - A lock added while lea runs is seen by the daemon: the deck and the agents' status lines say to
restart lea (
lea stop, thenlea).