CLI reference
Every lnbot command with its flags and the output it prints: wallets, invoices, payments, addresses, webhooks, keys, backup and MCP config.
lnbot is a single binary (version 1.1.2 as of October 2026) that calls the ln.bot API with the key lnbot init saved. Install it with curl -fsSL https://ln.bot/install.sh | bash, or see the other install options. lnbot <command> --help lists the same flags as this page.
Global flags
| Flag | Effect |
|---|---|
-w, --wallet <name|id> |
Use this wallet instead of the active one. A wal_ ID is used as given; a name is looked up in your wallet list. |
--json |
Print JSON instead of text. |
-y, --yes |
Skip confirmation prompts. |
pay, address buy, address transfer, address delete and key rotate ask (y/N) before they act. When nothing answers (a script, an agent, a pipe), the answer is no: the command prints Cancelled. and exits with status 0 without doing anything. Pass --yes whenever no one is at the keyboard.
Configuration
lnbot init writes ~/.config/lnbot/config.json, readable only by you, with three values:
{
"primary_key": "uk_...",
"secondary_key": "uk_...",
"active_wallet_id": "wal_..."
}That is all the CLI keeps; wallet names, balances and addresses come from the API each time. Set LNBOT_CONFIG to use another file, for example one per agent:
LNBOT_CONFIG="$HOME/agents/research/lnbot.json" lnbot balanceOnce a day, a command also checks GitHub for a newer release and prints a notice on stderr when there is one. Set LNBOT_NO_UPDATE_CHECK=1 to skip the check.
Getting started
lnbot init
Registers an account, creates its first wallet and writes the config file. Run it once per machine or per agent; add wallets with lnbot wallet create.
$ lnbot init
Registering account... done
Creating wallet... done
✓ Account and wallet created
Wallet: x4k7m2 (wal_c7i0hnuoxxupuwej)
Address: x4k7m2@ln.bot
API key: uk_9Qf3Lx7Tz...6bHc
⚠ Recovery passphrase, shown only once. Keep it safe:
orbit garden pilot smoke valley ticket museum hollow drift cabin lemon fragile
Config saved to /home/you/.config/lnbot/config.jsonThe passphrase is printed only this once: save it, because lnbot restore recovery needs it to get back in. If a config file already exists, init prints Already initialized. Config at <path> and changes nothing. With --json, the last line of output is a JSON object with primary_key, secondary_key, wallet_id, wallet_name, address and recovery_passphrase.
Wallet
lnbot wallet create
Creates another wallet on the account, with a generated name and its own random Lightning address. It becomes the active wallet only if there was none. There is no command to delete a wallet.
$ lnbot wallet create
✓ Wallet created
ID: wal_x8j2knroyyqpvwfh
Name: k3p9tq
Address: k3p9tq@ln.botlnbot wallet list
Every wallet on the account; ● marks the active one. Alias: ls.
$ lnbot wallet list
● x4k7m2 wal_c7i0hnuoxxupuwej
k3p9tq wal_x8j2knroyyqpvwfhlnbot wallet use <name|id>
Makes another wallet the active one.
$ lnbot wallet use k3p9tq
✓ Switched to k3p9tq (wal_x8j2knroyyqpvwfh)lnbot wallet rename <new-name>
Renames the active wallet, or the one --wallet names, on the server. The local config holds only the keys and the active wallet's ID, so nothing changes locally.
$ lnbot wallet rename production
✓ Renamed to productionlnbot balance
$ lnbot balance
Balance: ₿500
Available: ₿500
On hold: ₿0Available is what the wallet can spend now; On hold is reserved for payments still in flight, with their fees.
lnbot status
The wallet's name, ID, first address and balance, and how long the API took to answer.
$ lnbot status
Name: x4k7m2
ID: wal_c7i0hnuoxxupuwej
Address: x4k7m2@ln.bot
Balance: ₿500
Available: ₿500
On hold: ₿0
API: ✓ Connected (112ms)lnbot whoami
$ lnbot whoami
Wallet: wal_c7i0hnuoxxupuwej
Name: x4k7m2
Address: x4k7m2@ln.bot
API key: uk_9Qf3Lx7Tz...6bHcPayments
lnbot invoice create --amount <sats> [--memo <text>]
Creates an invoice, prints it and waits for the payment.
| Flag | Effect |
|---|---|
--amount <sats> |
Required. A whole number of sats: 1000 is ₿1,000. |
--memo <text> |
A memo embedded in the invoice. |
--no-wait |
Print the invoice and exit instead of waiting. |
$ lnbot invoice create --amount 1000 --memo "first invoice"
Amount: ₿1,000
Status: Pending
BOLT11:
lnbc10u1p5x8k2a...
Waiting for payment... (Ctrl+C to stop)
✓ Payment received: +₿1,000The CLI follows the API's event stream until the invoice is paid. An invoice is valid for 60 minutes, and one paid just before it expires can still settle, so if it expires first the CLI prints Invoice expired. Checking for a payment made just before it did..., keeps checking for another minute, and then prints No payment arrived. Ctrl+C stops waiting; the invoice stays payable until it expires. The output is the BOLT11 string only, with no QR code. With --json, the invoice is printed as JSON once it settles or that minute is up, or right away with --no-wait.
lnbot invoice list [--limit <n>] [--after <n>]
Invoices, newest first, 20 at a time. --after <n> starts below invoice number n, and when a page is full its last line gives the --after value for the next one. Alias: ls.
$ lnbot invoice list
# 2 Pending ₿5,000 just now
# 1 Settled ₿1,000 12m agolnbot pay <address-or-bolt11> [--amount <sats> | --all] [--max-fee <sats>]
Pays a Lightning address (name@domain), an LNURL (lnurl1...) or a BOLT11 invoice (lnbc...).
| Flag | Effect |
|---|---|
--amount <sats> |
Required for a Lightning address or an LNURL, unless you pass --all. A BOLT11 invoice carries its own amount. |
--all |
Send everything the wallet can to a Lightning address or LNURL, after fees. |
--max-fee <sats> |
The most to pay in network fees. The default is 1% of the amount, at least ₿20. |
--no-wait |
Exit as soon as the API accepts the payment. |
pay prices the payment, shows the amount, the fees and the total, and then asks. Between ln.bot wallets there are no fees:
$ lnbot pay k3p9tq@ln.bot --amount 500
Amount: ₿500
Fees: ₿0 (to an ln.bot wallet)
Total: ₿500
Send ₿500 to k3p9tq@ln.bot? (y/N) y
✓ Payment settled in 414ms
Amount: ₿500
Fees: ₿0
Available: ₿500A payment out to Lightning pays a 0.25% service fee, at least ₿1, and the network fee, 0.25% plus routing. The quote gives the network fee as an estimate; the result shows what was charged, and Total: is what left the balance, as lnbot transactions shows it:
$ lnbot pay alice@example.com --amount 250000
Amount: ₿250,000
Network fee: ₿700 (estimate)
Service fee: ₿625
Total: ₿251,325
Send ₿250,000 to alice@example.com? (y/N) y
✓ Payment settled in 1840ms
Amount: ₿250,000
Fees: ₿1,323 (network ₿698, service ₿625)
Total: ₿251,323
Available: ₿48,675Without --yes, a script or an agent gets Cancelled. and exit status 0, and nothing is paid. --yes skips the quote along with the question, which saves pricing a Lightning address: that fetches an invoice from the recipient. If the network fee quote is above the default cap, pay prints the API's warning and stops with Error: the network fee is above the default cap; pass --max-fee <sats> to allow it. With --all, it sends the most the balance covers after fees; that can't be combined with --amount or --max-fee.
If the payment is still in flight when the API answers, pay prints Waiting for settlement... (Ctrl+C to stop) and waits for the result. A payment that can't be routed yet stays pending while ln.bot retries it, for up to 24 hours or until its invoice expires; if the wait ends first, pay prints Still pending. ln.bot keeps retrying it; check with 'lnbot payment list'.
A failed payment prints ✗ Payment failed: <reason> and Nothing was deducted. on stderr, and still exits with status 0, so scripts should use --json and check that status is settled. The REST API reference lists the reasons. Not enough balance is an error from the API: Error: sending payment: ... and exit status 1. With --no-wait you get the payment's status and number:
$ lnbot pay r7vq3np@ln.bot --amount 500 --yes --no-wait
Status: Processing
Number: 1lnbot payment list [--limit <n>] [--after <n>]
Outgoing payments, newest first, 20 at a time. Alias: ls.
$ lnbot payment list
# 1 Settled ₿500 4m ago k3p9tq@ln.botlnbot transactions [--limit <n>] [--after <n>]
Every credit and debit with the balance after it, newest first, 20 at a time. Aliases: tx, txns.
$ lnbot transactions
Debit -₿500 Balance ₿500 4m ago
Credit +₿1,000 Balance ₿1,000 11m agoAddresses
lnbot address list
$ lnbot address list
x4k7m2@ln.bot (generated)
mybot@ln.bot (vanity, ₿100)lnbot address buy <name>
Claims name@ln.bot for the wallet and pays for it from the balance, once: ₿100 for five characters or more, ₿1,000 for four, ₿10,000 for three. Names are 3 to 20 lowercase letters and digits. Every address also takes a tag after a plus sign: mybot+order42@ln.bot pays the same wallet.
$ lnbot address buy mybot --yes
✓ Address claimed: mybot@ln.bot
Cost: ₿100lnbot address transfer <address> --target-key <wallet-key>
Moves a vanity address to another wallet. Only bought addresses can move; the API refuses a generated one. --target-key takes the receiving wallet's key: the SDK test suites pass a wallet key (wk_...), although the example in lnbot address transfer --help shows a user key. The CLI can't create wallet keys; make one with the REST API or an SDK (w.key.create()).
$ lnbot address transfer mybot@ln.bot --target-key wk_... --yes
✓ Transferred mybot@ln.bot to wallet wal_x8j2knroyyqpvwfhlnbot address delete <address>
Removes the address from the wallet. There is no refund for a vanity address.
$ lnbot address delete mybot@ln.bot --yes
✓ Address deletedWebhooks
lnbot webhook create --url <url>
Registers an HTTPS URL for the wallet's events and prints its signing secret, once. A wallet can have up to 10, one per URL. The API reference shows what a delivery carries and how to check its signature.
$ lnbot webhook create --url https://example.com/hooks/lnbot
✓ Webhook created
ID: e82a6e9a410c916a
URL: https://example.com/hooks/lnbot
Secret: 15a10301168f123cba107d4c3126a53944e5cbd5ff5796af821c31f9e6545e08
Save the secret now: it won't be shown again.lnbot webhook list
$ lnbot webhook list
e82a6e9a410c916a Active https://example.com/hooks/lnbot just nowlnbot webhook delete <id>
Deletes the webhook without asking.
$ lnbot webhook delete e82a6e9a410c916a
✓ Webhook e82a6e9a410c916a deletedKeys & security
lnbot key show
Prints both user keys in full, from the config file. Either one reaches every wallet on the account.
$ lnbot key show
Primary: uk_9Qf3Lx7TzM2pW8vR4kNs6bHc
Secondary: uk_Jd5Tq8Wm3ZrK7pXv2NfL9sCylnbot key rotate <0|1>
Replaces the primary (0) or secondary (1) user key. The old key stops working at once; the new one is printed and written to the config file. Anything else that uses the old key, such as an MCP client config, needs the new one.
$ lnbot key rotate 0
Rotate the primary key? The old key will stop working. (y/N) y
✓ Primary key rotated
Key: uk_R4kV8nP2xQ7mL3tZ9wJ5cH6d
Save it now: it won't be shown again.lnbot backup recovery
Generates a new 12-word recovery passphrase. The previous one stops working.
$ lnbot backup recovery
⚠ Recovery passphrase, shown only once. Keep it safe:
copper rival tunnel fiscal mango switch elbow canvas oyster rely brave glimpse
Any previous recovery passphrase is now invalid.lnbot backup passkey
Registering a passkey needs WebAuthn, which only a browser has. Run the command in the terminal on the ln.bot home page; the binary prints that pointer and exits with status 1.
lnbot restore recovery --passphrase "word1 word2 ... word12"
Gets back into an account with its recovery passphrase, on any machine. Restoring rotates the account's API keys: the old ones stop working at once, and the config file is replaced with the new keys and the restored wallet.
$ lnbot restore recovery --passphrase "orbit garden pilot smoke valley ticket museum hollow drift cabin lemon fragile"
✓ Account restored
Wallet: wal_c7i0hnuoxxupuwej
Name: x4k7m2
Address: x4k7m2@ln.botlnbot restore passkey
Like backup passkey, this works only in the terminal on the ln.bot home page. The binary prints a pointer there and exits with status 1.
MCP
lnbot mcp config --remote
Prints the config block for the active wallet's MCP server (--wallet picks another), with the account's primary user key in the Authorization header:
$ lnbot mcp config --remote
Add to your MCP client config:
{
"mcpServers": {
"lnbot": {
"headers": {
"Authorization": "Bearer uk_9Qf3Lx7TzM2pW8vR4kNs6bHc"
},
"type": "url",
"url": "https://api.ln.bot/v1/wallets/wal_c7i0hnuoxxupuwej/mcp"
}
}
}Without --remote it prints Local MCP server is not available yet., and lnbot mcp serve says the same. MCP server shows how to add the server to Claude Code, Cursor and other clients.
Install & update
macOS / Linux
curl -fsSL https://ln.bot/install.sh | bashThe script downloads the latest release from GitHub and installs it to /usr/local/bin, using sudo if it has to, or to ~/.local/bin when sudo isn't available.
Windows
In PowerShell:
iwr -useb https://ln.bot/install.ps1 | iexIn CMD:
curl -fsSL https://ln.bot/install.cmd -o install.cmd && install.cmd && del install.cmdBoth install lnbot.exe to %LOCALAPPDATA%\lnbot and add that folder to your user PATH. Open a new terminal afterwards.
Homebrew
brew install lnbotdev/tap/lnbotGo
go install github.com/lnbotdev/cli@latestGo names the binary after the module path, so this installs cli, not lnbot, in $(go env GOPATH)/bin (or $GOBIN if you set it). Rename it:
mv "$(go env GOPATH)/bin/cli" "$(go env GOPATH)/bin/lnbot"Archives for every platform are also on the releases page.
Update
$ lnbot update
Current version: 1.1.2
You're up to date.lnbot update only checks. When a newer release exists, it prints Latest version: and the command to run (the PowerShell and CMD lines on Windows); it doesn't replace the binary. A Homebrew install upgrades with brew upgrade lnbot. lnbot version prints the version alone.
Shell completions
source <(lnbot completion bash) # Bash
source <(lnbot completion zsh) # Zsh
lnbot completion fish | source # FishPowerShell: lnbot completion powershell | Out-String | Invoke-Expression. lnbot completion --help shows how to load them in every new shell.