Non-custodial spend governance for AI agents.
Hard budgets, allowlists, rate limits, time windows, graded shutdown, signed audit trail.
Lightning (NWC), Cashu and x402/USDC on Base and Ethereum.
Website · Docs · FAQ · Community
- Chain (x402): the owner wallet grants a Spend Permission: at most
allowanceUSDC perperiod, untilend, revocable any time. leashd's agent key can never hold more than one period. - leashd (all rails): per-transaction max, endpoint/domain allowlists, rate limit, time windows, approval threshold, kill switch and graded shutdown, signed append-only audit. Deterministic; a prompt cannot talk it out of a decision.
- Not guaranteed: within one period, a fully compromised host running leashd can spend that period's allowance. Pick the period and allowance you can afford to lose.
| Rail | Funding | Chain-side cap |
|---|---|---|
| Lightning (NWC) | your node / Alby Hub | NWC connection budget |
| Cashu | mint proofs in the local store | balance |
| x402 / USDC | Base Account Spend Permission (or manual) | allowance per period |
Autonomous AI agents now discover services, buy compute, and pay other agents on their own. The moment you give an agent a wallet, one prompt injection, one dependency exploit, or one runaway loop can drain it. Probabilistic guardrails in the model are not a control. You need a deterministic gate between the agent and the money.
leashd is a bouncer with a rulebook standing between your AI agent and your funds. The agent asks to pay, leashd checks your policy (budget left, recipient allowed, under the limit, kill-switch off), then authorises or blocks it, and writes every decision to a signed log. It is non-custodial: leashd runs on your own machine and holds your wallet connection locally. It never touches your funds or keys.
AI agent ──pay 50 sat──▶ leashd (your machine)
│ check policy (caps · allowlist · rate · kill-switch)
├─ allowed ─▶ your wallet (NWC) ──▶ api.foo.com
├─ capped / denied ─▶ structured refusal to the agent
└─ signed audit event ──▶ control plane feed
The agent never gets your wallet. It gets a policy-gated pay tool over MCP that points at leashd. Funds settle directly between your own wallet and the counterparty. leashd sits in the policy path, never the custody path.
| Budget caps | per transaction, per task, rolling hourly / daily / monthly |
| Scoped credentials | allowlists and denylists for endpoints, domains, Lightning addresses, mints |
| Rate limits | cap transactions per window |
| Time windows | only let agents spend when you allow |
| Approval thresholds | human-in-the-loop above a value you set |
| Graded shutdown | a dimmer, not just a kill-switch: attenuate scope, drop tools, escalate approvals |
| Signed audit trail | append-only, tamper-evident, exportable. EU AI Act Article 12 grade |
| Multi-rail | Lightning (NWC) and L402, Cashu ecash, x402/USDC on Base and Ethereum |
| MCP-native | drops into Claude Code or any MCP host |
leashd is in early access. Install from source for now; a published one-line install is on the way.
# install from source (requires node >= 22.5 and pnpm)
git clone https://github.com/brainbytes-dev/leashd
cd leashd && pnpm install
# run leashd with your env (token + control plane URL)
LEASH_AGENT_TOKEN=lsh_live_xxxxxxxx \
LEASH_API_URL=https://leashd.dev \
pnpm --filter @repo/leashd devWire it into Claude Code via .mcp.json:
{
"mcpServers": {
"leashd": {
"command": "leashd",
"args": ["--mcp"],
"env": {
"LEASH_AGENT_TOKEN": "lsh_live_xxxxxxxx",
"LEASH_API_URL": "https://leashd.dev"
}
}
}
}Then create a workspace and agent, set a policy, and your agent's pay calls are policy-gated. Full guide at leashd.dev/docs.
leashd is open core. leashd (the program that runs on your machine) and the policy engine are open source under AGPL-3.0. The hosted control plane (policy authoring, audit aggregation, team, billing) is available at leashd.dev, and a commercial license is available (see COMMERCIAL.md).
packages/
leash-core/ deterministic policy engine + shared contract (zod)
leashd/ runs on your machine: MCP server, governor, rail adapters, audit
apps/
web/ the control plane (Next.js)
Stack: TypeScript, Next.js, Turborepo, Drizzle, node:sqlite. Zero native build for leashd.
You hold the keys. leashd holds the policy. The control plane stores only policies and the audit log, never funds or keys. Even a full compromise of leashd, or of the control plane, cannot move your money, because the keys never leave your machine. leashd is not a money transmitter.
- Lightning / L402 rail, policy engine, MCP server, signed audit
- Cashu ecash rail
- x402 / USDC rail (Base + Ethereum), on-chain enforced Spend Permissions
- Team and RBAC, audit CSV export
- Approval workflow UI, alerting, long audit retention
x402/USDC is funded non-custodially: your own wallet grants a per-period Spend Permission, and leashd's local agent key can never hold more than one period's allowance.
# 1. Generate a local agent key (private key never leaves this machine)
pnpm --filter @repo/leashd x402 keygen
# 2. Grant a Spend Permission from your own wallet — client-side, no server involved
# open the grant page and sign with the owner wallet, save the downloaded JSON:
open https://leashd.dev/dashboard/rails/x402/grant
# 3. Point leashd at the granted permission
LEASH_X402_NETWORK=eip155:8453 \
LEASH_X402_PRIVATE_KEY=0x... \
LEASH_X402_RPC_URL=https://mainnet.base.org \
LEASH_X402_FUNDING=base-spend-permission \
LEASH_X402_PERMISSION_PATH=~/.leashd/x402-permission.json \
LEASH_X402_OWNER_ADDRESS=0xYourOwnerWallet \
pnpm --filter @repo/leashd dev
# 4. Check remaining allowance and period end anytime
pnpm --filter @repo/leashd x402 statusRevoke the grant any time from the same grant page, or directly in the owner wallet. leashd's agent key can never pull more than the last granted period.
Gas: a spend() call measures roughly 186,880 gas in the contract's own gas snapshot. At the fees
recorded in docs/x402-spikes.md (Step 2, fetched live 2026-09-16) that's about $0.0027 on Base
(0.006 gwei) and about $0.083 on Ethereum mainnet (0.185 gwei) — point-in-time estimates, not a
promise, and Base is the launch rail for a reason.
Full list once filed: issues labelled help wanted.
- funding: ERC-7715 delegation as a second
FundingSource— MetaMask smart accounts, an erc20 periodic permission as an alternative to the Base Account Spend Permission. - funding: Kernel signature policy enforcing EIP-3009 typed data on-chain — a Kernel v3 policy that
validates a
transferWithAuthorizationtyped-data signature on-chain, capping an x402 payment without the pull-into-agent-key step. - rail: Solana x402 — the x402
exactscheme on Solana, non-custodial per-period cap (Spec 2).
PRs welcome. See CONTRIBUTING.md. The one invariant you must never break: leashd stays non-custodial. Report vulnerabilities per SECURITY.md.
leashd is built in the open by an indie solo-dev. If it saves your agents from spending your sats, send some back:
⚡ leashd@walletofsatoshi.com (TODO: replace with the real Lightning address)
A GitHub sponsor button is set up via .github/FUNDING.yml.
AGPL-3.0. Commercial licenses available, see COMMERCIAL.md.
Built by BrainBytes Studio, an indie solo-dev shop.