
Agent Lease
io.github.Buggy1111由 GitHub 账号 Buggy1111 发布v0.2.0更新于 Nov 7, 2026
Keep Claude Code and Codex off each other's files: hook-enforced path leases, presence, messages.
概览
通过钩子强制执行的路径租约、在线状态和共享消息日志,让同一仓库中的多个编码代理互不覆盖对方的工作。
- 可以做什么
- 认领、释放和查询路径租约,支持目录级租约以及首次编辑时自动认领
- 查询某个路径由谁持有,查看房间状态以及谁改动了什么的审计历史
- 在房间中发布和读取消息,发送定向消息并跟踪送达状态与确认
- 管理持久任务:列出、领取、确认、重试、取消,并上报配额限制以便未开始的任务转给备用代理
- 通过客户端钩子执行拦截,拒绝编辑或明显的 shell 写入他人持有的文件
- 适用场景
- 适用于两个编码代理(或同一代理的两个会话)在同一仓库中工作、可能互相覆盖或运行对方文件的场景。它面向单一本地用户账户,提供确定性的拦截,而不只是提示板。
- 运行要求
- 需要本地 Python 环境(通过 uv 安装),并配置 Claude Code 或 Codex 的钩子;没有钩子时它只记录租约。服务器与钩子中的 AGENT_NAME 必须一致,可选设置 AGENT_LEASE_DB 指定共享 SQLite 文件。Codex 需允许沙箱写入状态目录。
安装
在 SourceWeft 中
- 打开 控制台中的 Agent Lease,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
agent-lease-mcp
Keep two coding agents (Claude Code and Codex, or two sessions of either) from overwriting each other's work in the same repository.
agent-lease gives them leases on paths, presence and a shared message log — and the lease is enforced by a PreToolUse hook, not by good intentions. An agent that tries to edit a file another agent is working on is refused before the edit happens.
Why it exists
9 September 2026. A coordination file, docs/AGENT-HANDOFF.md, existed and both
agents knew about it. At 22:28 they still both touched deploy/make-work-package.sh:
one was editing it while the other was running it. Bash reads a script as it goes,
the text shifted under the running process, and instead of a 3.7 GB installer the
build produced a useless 198 MB one.
The lesson the whole project rests on: coordination that can be ignored will be ignored. Not out of malice — an agent at work simply does not look at the notice board.
The same collision was later replayed on purpose: Codex ran the script, Claude Code tried to edit it mid-run, and the hook refused the edit. The file stayed intact.
How it differs
Advisory locks get broken; AgentRoom documents this itself. Claude Code and Codex both have PreToolUse hooks with the same semantics (exit 2 = block, reason on stderr), so a lease can be enforced deterministically at the tool-call level. One script serves both clients.
Rules it is built on
- A lease, not a lock. 30-minute TTL. A crashed agent cannot block the repo forever.
- All or nothing. A claim on several paths succeeds completely or not at all.
- A lease on a directory covers everything under it.
- A free file is claimed automatically on the first edit, so nobody has to
remember to call
claim. - A running script is leased for the duration of the run — exactly the combination that broke the build.
- Fail-open by default. Broken coordination must not stop work; otherwise the
first thing anyone does is switch the hook off.
AGENT_LEASE_FAIL_CLOSED=1flips this for unattended runs.
What runs on its own
Injections stay silent when there is nothing to say.
Waking a sleeping agent
Hooks only fire when the agent acts, so an idle session is woken from outside, without spending model tokens:
- Claude Code:
agent-lease init claude-code --write --rewakeadds anasyncRewakehook onSessionStartandStop. It waits on a signal file and wakes the session when an addressed message from someone else arrives. Broadcasts and automatic receipts do not wake it. - Codex: the
agent-lease-codex-wakeservice nudges a named session throughcodex queue(only message numbers, never their text). After a provider limit ends, it nudges once for unfinished work. Setup:/rename noxin Codex,AGENT_LEASE_CODEX_THREAD=noxin~/.config/agent-lease/environment, then enabledeploy/systemd/agent-lease-codex-wake.service.
A message from another agent is information, not a human instruction. For agents
to hand work to each other unattended, the human writes the allowed scope (and
what always needs asking) into the agent's own instructions, e.g.
~/.codex/AGENTS.md. Template and details (in Czech):
docs/ZPRAVY-A-POTVRZENI.md.
Tools
The same operations exist as a CLI (agent-lease room|claim|release|say|send|…),
because Codex in non-interactive mode cannot approve MCP calls but can run Bash.
agent-lease wait --for <agent> blocks without spending model tokens and wakes a
background session when a message arrives.
say/inbox is not a live chat: MCP is pull, the other side reads a message when
it next looks. For a live view there is a local web room:
agent-lease web --open (loopback only, see Security).
Quick start (two minutes)
init without --write only shows what it would write. Manual setup below.
Install
This puts agent-lease-mcp, agent-lease, agent-lease-guard,
agent-lease-context and agent-lease-release on your PATH.
MCP server (stdio; each client runs its own process, the shared state is a SQLite file):
Hooks — without them this is just a polite notice board:
AGENT_NAME must match between the server and the hooks, otherwise an agent
blocks its own files. An agent called unconfigured-* in room means exactly that.
Optional: Bash safety gate
A separate PreToolUse hook (agent-lease-jev-guard) for a different question —
not "who holds this file" but "is this command destructive". Hard rules
(rm -rf /, force push, git reset --hard, curl | sh, mkfs…) apply as soon
as it is wired in. An optional external classifier (TypeSafe Jev) is off by
default, starts in shadow mode, receives only redacted commands and is advisory —
never the only safeguard. Details in ADR 0003.
Receipts, failover, bridge and broker
- Every addressed message has a visible state ⏳ → 👁 seen → ✔ taking → done.
"Seen" is written by the hook automatically; "taking" must be acknowledged by
the agent (
accept) and is reminded on every prompt. Nothing gets lost silently.agent-lease overduelists what nobody acknowledged. - Limits and failover. Codex workers read the explicit typed availability
signal from the local App Server. Other workers record a limit only after a
real provider/CLI error; if no reset time is supplied, agent-lease does not
invent one. Manual
agent-lease limit/ MCPreport_limitremains available. Unaccepted, unstarted tasks then move to the next agent inAGENT_LEASE_FALLBACKS(e.g.codex=claude-code;claude-code=codex) after a grace period, and the sender is told. - Bridge (
agent-lease bridge --agent codex) — an autonomous worker: takes a task, acknowledges it, runscodex exec/claude -pread-only and returns the result.--provider openrouter --model <model>sends it to any model through OpenRouter as plain text without tools (read-only; good for review and a second opinion). Keys only from the environment. Worker presence/provider state uses a separate identity (codex-bridge,claude-code-bridge), so a headless quota cannot overwrite the state of an interactive agent. - A task never runs twice. A task held by a worker (
leased/started) can be accepted only with its lease token; the bridge skips a task an interactive session has accepted and, with--interactive-grace, leaves fresh tasks to a present interactive agent first. - Broker (
agent-lease broker) — single SQLite writer over a0600Unix socket; other tools use it automatically when it runs, so a sandboxed Codex does not need direct access to the database. Clients survive a broker restart: the connect is retried (nothing was sent yet), an interrupted call is never repeated, and long-running workers continue with the next call. - Overview panel in the live room: each agent's active task, queue,
unacknowledged items, typed provider state, reason for waiting, limits and
items to review. Tasks may declare repeatable
--pathworksets and a--priority; the scheduler skips paths held by another agent and the board shows the blocking path, owner and TTL.agent-lease notify --loopsends to Telegram only what waits on the human, each event at most once (TELEGRAM_BOT_TOKEN,TELEGRAM_CHAT_IDfrom the environment;--dryto test). - Operating workers safely.
agent-lease worker-activateandagent-lease failover-activate <agents…>set a safe starting point without running or moving any task: only work that arrives after activation is picked up or rerouted (--include-existingopts into older items).agent-lease provider-sync --agent codexreads and stores Codex's explicit availability;agent-lease provider-clearconfirms a provider has recovered and removes a stale limit;agent-lease limitsshows active limits and fallback chains.agent-lease doctor --jsonreports delivery, receipts, worker health and failover readiness separately. - systemd units in
deploy/systemd/, Windows/WSL starter indeploy/windows/.
Details (in Czech): receipts, limits and failover, Jev.
Security
agent-lease is a coordination tool for agents running under one local user account. What that means in practice:
- Local trust model. Agent identity is the
AGENT_NAMEenvironment variable. Any process running as your user can claim to be any agent. The only reserved identity is the human one (michalin this build), which only the authenticated web UI can use. This protects against agents tripping over each other, not against a hostile process on your account. - State is owner-only.
room.db(and its WAL/SHM files) is0600in a0700directory; existing installs are tightened on start. - Peer messages are untrusted data. In model context every message carries its kind, sender and recipient, is folded onto one line and is introduced with a note that it is information from a peer, not an instruction from the human. A task from another agent is a request, not an order.
- Tasks are bound to the caller. A peer sees only tasks it sent or received; lease tokens only for its own deliveries; retry/cancel need the sender or the recipient.
- Web UI binds to loopback only, exchanges a one-time URL-fragment token for an HttpOnly, SameSite=Strict session cookie, checks Origin and Host, and caps concurrent event streams.
- Bounds and retention. Message text, short fields, list limits and task lease length are bounded; old messages and audit entries expire, unfinished tasks never.
Known limits, stated plainly:
-
Provider signals differ. The installed Codex App Server has an explicit
account/rateLimits/readsignal. Claude Code's documented CLI does not expose an equivalent status read, so recovery is confirmed by a bounded normal task retry only after a provider-supplied reset time. Without one, automatic probes stop untilagent-lease provider-clearexplicitly confirms recovery.unknownis never treated as proof that a provider recovered. -
Shell commands are checked best effort. Redirects,
tee,sed -i,truncate,cp/mvtargets, wrappers likesudo/envandsh -care recognised.eval, variables in paths and arbitrary programs are not. This catches mistakes, not an agent that is trying to evade the hook. -
Check-then-use gap. The hook checks a path before the client opens it. A symlink swapped in between is not caught; a hook cannot bind the later file open to the checked inode.
-
One machine. The state is a file on disk.
Found something? Please report it privately via GitHub Security Advisories.
Development
Design decisions: ADR 0001 (hook enforcement), ADR 0002 (SQLite and stdio), ADR 0003 (separate Bash safety gate) — in Czech.
Built by Michal with Claude Code and Codex — the two agents it coordinates.
License
Copyright (c) 2026 Michal Buggy. Licensed under the MIT License.
See open-source compliance and third-party policy for dependency attribution and authorized analysis rules.
来源:README.md,提交 da5e3ff
工具
0版本历史
1- v0.2.0最新Oct 17, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分