@lightninglabs/lightning-mcp-server 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/.claude-plugin/marketplace.json +36 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/README.md +307 -0
  4. package/bin/lightning-mcp-server +15 -0
  5. package/docs/architecture.md +455 -0
  6. package/docs/commerce.md +357 -0
  7. package/docs/l402-and-lnget.md +267 -0
  8. package/docs/mcp-server.md +285 -0
  9. package/docs/quickref.md +263 -0
  10. package/docs/security.md +298 -0
  11. package/docs/two-agent-setup.md +394 -0
  12. package/package.json +52 -0
  13. package/postinstall.js +160 -0
  14. package/skills/aperture/SKILL.md +330 -0
  15. package/skills/aperture/scripts/install.sh +68 -0
  16. package/skills/aperture/scripts/setup.sh +155 -0
  17. package/skills/aperture/scripts/start.sh +81 -0
  18. package/skills/aperture/scripts/stop.sh +57 -0
  19. package/skills/aperture/templates/aperture-regtest.yaml +36 -0
  20. package/skills/aperture/templates/aperture.yaml.template +64 -0
  21. package/skills/aperture/templates/docker-compose-aperture.yml +59 -0
  22. package/skills/commerce/SKILL.md +211 -0
  23. package/skills/lib/config-gen.sh +127 -0
  24. package/skills/lib/rest.sh +69 -0
  25. package/skills/lightning-security-module/SKILL.md +253 -0
  26. package/skills/lightning-security-module/references/architecture.md +133 -0
  27. package/skills/lightning-security-module/scripts/docker-start.sh +117 -0
  28. package/skills/lightning-security-module/scripts/docker-stop.sh +53 -0
  29. package/skills/lightning-security-module/scripts/export-credentials.sh +268 -0
  30. package/skills/lightning-security-module/scripts/install.sh +178 -0
  31. package/skills/lightning-security-module/scripts/setup-signer.sh +307 -0
  32. package/skills/lightning-security-module/scripts/start-signer.sh +152 -0
  33. package/skills/lightning-security-module/scripts/stop-signer.sh +240 -0
  34. package/skills/lightning-security-module/templates/docker-compose-signer.yml +35 -0
  35. package/skills/lightning-security-module/templates/signer-lnd.conf.template +69 -0
  36. package/skills/lnd/SKILL.md +441 -0
  37. package/skills/lnd/profiles/debug.env +4 -0
  38. package/skills/lnd/profiles/default.env +3 -0
  39. package/skills/lnd/profiles/regtest.env +4 -0
  40. package/skills/lnd/profiles/taproot.env +3 -0
  41. package/skills/lnd/profiles/wumbo.env +3 -0
  42. package/skills/lnd/references/security.md +156 -0
  43. package/skills/lnd/scripts/create-wallet.sh +464 -0
  44. package/skills/lnd/scripts/docker-start.sh +256 -0
  45. package/skills/lnd/scripts/docker-stop.sh +109 -0
  46. package/skills/lnd/scripts/import-credentials.sh +145 -0
  47. package/skills/lnd/scripts/install.sh +195 -0
  48. package/skills/lnd/scripts/lncli.sh +150 -0
  49. package/skills/lnd/scripts/start-lnd.sh +241 -0
  50. package/skills/lnd/scripts/stop-lnd.sh +218 -0
  51. package/skills/lnd/scripts/unlock-wallet.sh +134 -0
  52. package/skills/lnd/templates/docker-compose-regtest.yml +122 -0
  53. package/skills/lnd/templates/docker-compose-watchonly.yml +71 -0
  54. package/skills/lnd/templates/docker-compose.yml +49 -0
  55. package/skills/lnd/templates/litd-regtest.conf.template +61 -0
  56. package/skills/lnd/templates/litd-watchonly.conf.template +57 -0
  57. package/skills/lnd/templates/litd.conf.template +88 -0
  58. package/skills/lnd/templates/lnd.conf.template +91 -0
  59. package/skills/lnget/SKILL.md +288 -0
  60. package/skills/lnget/scripts/install.sh +69 -0
  61. package/skills/macaroon-bakery/SKILL.md +179 -0
  62. package/skills/macaroon-bakery/scripts/bake.sh +337 -0
  63. package/skills/mcp-lnc/SKILL.md +280 -0
  64. package/skills/mcp-lnc/scripts/configure.sh +130 -0
  65. package/skills/mcp-lnc/scripts/install.sh +103 -0
  66. package/skills/mcp-lnc/scripts/setup-claude-config.sh +162 -0
  67. package/skills/mcp-lnc/templates/env.template +16 -0
  68. package/versions.env +23 -0
@@ -0,0 +1,357 @@
1
+ # Agent Commerce
2
+
3
+ > Setting up buyer and seller agents for autonomous Lightning payments.
4
+
5
+ Lightning Agent Tools enables a payment pattern where agents buy and sell
6
+ resources from each other over the Lightning Network without any pre-arranged
7
+ billing relationship. A buyer agent uses `lnget` to fetch paid content. A
8
+ seller agent uses `aperture` to gate access behind Lightning invoices. Both run
9
+ their own `lnd` nodes for payment infrastructure. The three components compose
10
+ into a self-contained commerce loop.
11
+
12
+ This document walks through setting up both sides and running them together.
13
+
14
+ ## The Commerce Loop
15
+
16
+ When a buyer agent fetches a resource from a seller, the following exchange
17
+ happens automatically:
18
+
19
+ ```mermaid
20
+ sequenceDiagram
21
+ participant BA as Buyer Agent
22
+ participant BL as Buyer lnd
23
+ participant LN as Lightning Network
24
+ participant SL as Seller lnd
25
+ participant AP as Aperture
26
+ participant BE as Backend Service
27
+
28
+ BA->>AP: GET /api/data (via lnget)
29
+ AP->>SL: Generate invoice (100 sats)
30
+ SL-->>AP: BOLT11 invoice
31
+ AP-->>BA: 402 + L402 challenge
32
+
33
+ BA->>BL: Pay invoice (100 sats)
34
+ BL->>LN: Route payment
35
+ LN->>SL: Deliver payment
36
+ SL-->>LN: Preimage
37
+ LN-->>BL: Preimage
38
+ BL-->>BA: Payment settled
39
+
40
+ BA->>AP: GET /api/data + L402 token
41
+ AP->>AP: Validate token
42
+ AP->>BE: Proxy request
43
+ BE-->>AP: Response data
44
+ AP-->>BA: 200 OK + data
45
+ ```
46
+
47
+ From the buyer agent's perspective, this is a single command:
48
+
49
+ ```bash
50
+ lnget --max-cost 100 -q https://seller-host:8081/api/data | jq .
51
+ ```
52
+
53
+ From the seller's perspective, aperture handles everything: invoice
54
+ generation, challenge issuance, token validation, and request proxying. The
55
+ backend service just serves HTTP requests.
56
+
57
+ ## Buyer Agent Setup
58
+
59
+ A buyer agent needs two components: an `lnd` node for payments and `lnget` for
60
+ HTTP requests with automatic L402 handling.
61
+
62
+ ### Install
63
+
64
+ ```bash
65
+ # Pulls Docker images by default; add --source to build from source.
66
+ skills/lnd/scripts/install.sh
67
+ skills/lnget/scripts/install.sh
68
+ ```
69
+
70
+ ### Create and Start the Node
71
+
72
+ All commands below auto-detect Docker and launch containers. Pass `--native` to
73
+ any script to use a locally built binary instead.
74
+
75
+ ```bash
76
+ # Create a wallet (standalone mode for testing, watch-only for production)
77
+ skills/lnd/scripts/create-wallet.sh --mode standalone
78
+
79
+ # Start lnd (launches a litd Docker container)
80
+ skills/lnd/scripts/start-lnd.sh
81
+
82
+ # Verify it's running
83
+ skills/lnd/scripts/lncli.sh getinfo
84
+ ```
85
+
86
+ For production deployments, use watch-only mode with a remote signer. See
87
+ [Security](security.md#tier-1-watch-only-with-remote-signer).
88
+
89
+ ### Fund the Wallet
90
+
91
+ The node needs on-chain bitcoin to open payment channels.
92
+
93
+ ```bash
94
+ # Generate a funding address
95
+ skills/lnd/scripts/lncli.sh newaddress p2tr
96
+
97
+ # Send BTC to this address from an exchange or another wallet
98
+
99
+ # Check balance (wait for confirmations)
100
+ skills/lnd/scripts/lncli.sh walletbalance
101
+ ```
102
+
103
+ ### Open a Channel
104
+
105
+ Lightning payments travel through channels. The buyer needs at least one channel
106
+ with outbound capacity to reach the seller (or a path to the seller through the
107
+ network).
108
+
109
+ ```bash
110
+ # Connect to a well-connected node
111
+ skills/lnd/scripts/lncli.sh connect <pubkey>@<host>:9735
112
+
113
+ # Open a channel (amount in satoshis)
114
+ skills/lnd/scripts/lncli.sh openchannel --node_key=<pubkey> --local_amt=1000000
115
+
116
+ # Wait for the funding transaction to confirm (typically 3-6 blocks)
117
+ skills/lnd/scripts/lncli.sh pendingchannels
118
+ skills/lnd/scripts/lncli.sh listchannels
119
+ ```
120
+
121
+ ### Configure lnget
122
+
123
+ ```bash
124
+ # Initialize config (auto-detects local lnd)
125
+ lnget config init
126
+
127
+ # Verify backend connection
128
+ lnget ln status
129
+ ```
130
+
131
+ ### Fetch Paid Resources
132
+
133
+ ```bash
134
+ # Fetch with a spending cap
135
+ lnget --max-cost 500 https://api.example.com/paid-data.json
136
+
137
+ # Preview cost without paying
138
+ lnget --no-pay --json https://api.example.com/paid-data.json | jq '.invoice_amount_sat'
139
+
140
+ # Pipe to other tools
141
+ lnget -q https://api.example.com/market-data.json | jq '.price'
142
+ ```
143
+
144
+ ## Seller Agent Setup
145
+
146
+ A seller agent needs three components: an `lnd` node for invoice generation,
147
+ `aperture` as the L402 reverse proxy, and a backend HTTP service to serve the
148
+ actual content.
149
+
150
+ ### Install
151
+
152
+ ```bash
153
+ skills/lnd/scripts/install.sh
154
+ skills/aperture/scripts/install.sh
155
+ ```
156
+
157
+ ### Create and Start the Node
158
+
159
+ ```bash
160
+ skills/lnd/scripts/create-wallet.sh --mode standalone
161
+ skills/lnd/scripts/start-lnd.sh # Docker container by default
162
+ skills/lnd/scripts/lncli.sh getinfo
163
+ ```
164
+
165
+ The seller's lnd node generates invoices for aperture. It needs inbound channel
166
+ capacity to receive payments. Other nodes must have channels open _to_ the
167
+ seller, not just from the seller.
168
+
169
+ ### Start a Backend Service
170
+
171
+ Aperture proxies authenticated requests to a backend HTTP service. For testing,
172
+ a simple file server works:
173
+
174
+ ```bash
175
+ mkdir -p /tmp/api-data
176
+ echo '{"market_data": {"btc_usd": 104250, "timestamp": "2025-02-09T12:00:00Z"}}' \
177
+ > /tmp/api-data/data.json
178
+ cd /tmp/api-data && python3 -m http.server 8080 &
179
+ ```
180
+
181
+ In production, the backend is whatever service you want to monetize: a REST
182
+ API, a data feed, an inference endpoint.
183
+
184
+ ### Configure and Start Aperture
185
+
186
+ ```bash
187
+ # Generate aperture config connected to local lnd
188
+ skills/aperture/scripts/setup.sh --insecure --port 8081
189
+
190
+ # Start the L402 proxy
191
+ skills/aperture/scripts/start.sh
192
+ ```
193
+
194
+ The `--insecure` flag disables TLS (suitable for development). For production,
195
+ configure TLS with Let's Encrypt (`--autocert`) or your own certificates.
196
+
197
+ For regtest testing, a Docker Compose file at
198
+ `skills/aperture/templates/docker-compose-aperture.yml` runs aperture alongside
199
+ a busybox backend on the same Docker network as the litd regtest stack.
200
+
201
+ Aperture's config (`~/.aperture/aperture.yaml`) defines which paths are
202
+ protected and how much they cost:
203
+
204
+ ```yaml
205
+ services:
206
+ - name: "market-data"
207
+ hostregexp: ".*"
208
+ pathregexp: "^/api/.*$"
209
+ address: "127.0.0.1:8080"
210
+ protocol: http
211
+ price: 100 # satoshis per request
212
+ authwhitelistpaths:
213
+ - "^/health$" # free health check endpoint
214
+ ```
215
+
216
+ Each request to a path matching `^/api/.*$` costs 100 satoshis. Requests to
217
+ `/health` pass through without payment. The `address` field points to the
218
+ backend service.
219
+
220
+ ### Verify
221
+
222
+ ```bash
223
+ # Should return 402 with L402 challenge
224
+ lnget -k --no-pay https://localhost:8081/api/data.json
225
+ ```
226
+
227
+ ## Running Both Sides
228
+
229
+ With both agents running, the buyer fetches data from the seller:
230
+
231
+ ```bash
232
+ # Buyer fetches paid data
233
+ lnget --max-cost 100 -q https://seller-host:8081/api/data.json | jq .
234
+ ```
235
+
236
+ Verify the payment went through:
237
+
238
+ ```bash
239
+ # On the buyer
240
+ lnget tokens list # shows cached token
241
+ skills/lnd/scripts/lncli.sh channelbalance # outbound decreased
242
+
243
+ # On the seller
244
+ skills/lnd/scripts/lncli.sh listinvoices # shows settled invoice
245
+ skills/lnd/scripts/lncli.sh channelbalance # inbound converted to local
246
+ ```
247
+
248
+ Subsequent requests from the buyer to the same domain reuse the cached token
249
+ without additional payment (until the token expires).
250
+
251
+ ## Deployment Diagram
252
+
253
+ A production deployment separates the signing infrastructure from the
254
+ agent-facing components:
255
+
256
+ ```mermaid
257
+ graph TB
258
+ subgraph Buyer["Buyer Agent"]
259
+ B_Agent["Agent Process"]
260
+ B_lnget["lnget"]
261
+ B_lnd["lnd (watch-only)"]
262
+ B_Signer["lnd signer<br/>(separate machine)"]
263
+
264
+ B_Agent --> B_lnget
265
+ B_lnget --> B_lnd
266
+ B_lnd <-->|"gRPC :10012"| B_Signer
267
+ end
268
+
269
+ subgraph Seller["Seller Agent"]
270
+ S_Agent["Agent Process"]
271
+ S_Aperture["aperture :8081"]
272
+ S_Backend["Backend :8080"]
273
+ S_lnd["lnd (watch-only)"]
274
+ S_Signer["lnd signer<br/>(separate machine)"]
275
+
276
+ S_Agent --> S_Aperture
277
+ S_Aperture --> S_Backend
278
+ S_Aperture --> S_lnd
279
+ S_lnd <-->|"gRPC :10012"| S_Signer
280
+ end
281
+
282
+ LN["Lightning Network"]
283
+ B_lnd <-->|":9735"| LN
284
+ S_lnd <-->|":9735"| LN
285
+ ```
286
+
287
+ ## Cost Management
288
+
289
+ Agents operating autonomously need spending guardrails at multiple levels:
290
+
291
+ **Per-request limits.** Set `--max-cost` on every lnget call. If the seller's
292
+ price exceeds the limit, lnget refuses to pay and exits with code 2:
293
+
294
+ ```bash
295
+ lnget --max-cost 500 https://api.example.com/data
296
+ ```
297
+
298
+ **Cost preview.** Before committing to a purchase, preview what the server is
299
+ charging:
300
+
301
+ ```bash
302
+ lnget --no-pay --json https://api.example.com/data | jq '.invoice_amount_sat'
303
+ ```
304
+
305
+ **Spending tracking.** Monitor cumulative spending through the token list:
306
+
307
+ ```bash
308
+ lnget tokens list --json | jq '[.[] | .amount_paid_sat] | add'
309
+ ```
310
+
311
+ **Wallet balance monitoring.** Check channel balance to ensure the agent has
312
+ sufficient capacity:
313
+
314
+ ```bash
315
+ skills/lnd/scripts/lncli.sh channelbalance
316
+ skills/lnd/scripts/lncli.sh walletbalance
317
+ ```
318
+
319
+ **Node-level controls.** Use a `pay-only` macaroon (via `macaroon-bakery`) for
320
+ the buyer agent. This restricts lnget to payment and invoice-decoding operations
321
+ only. The agent cannot open channels, change configuration, or access any
322
+ other node functionality:
323
+
324
+ ```bash
325
+ skills/macaroon-bakery/scripts/bake.sh --role pay-only
326
+ ```
327
+
328
+ For the seller agent, use an `invoice-only` macaroon for aperture. It only needs
329
+ to create and look up invoices.
330
+
331
+ ## Production Considerations
332
+
333
+ **Remote signer.** Both buyer and seller nodes should run in watch-only mode
334
+ with a remote signer in production. See
335
+ [Security](security.md#tier-1-watch-only-with-remote-signer).
336
+
337
+ **Inbound liquidity.** The seller's lnd node needs inbound channel capacity to
338
+ receive payments. This means other nodes must open channels _to_ the seller.
339
+ Options include requesting inbound channels from LSPs (Lightning Service
340
+ Providers), or using circular rebalancing to shift local capacity to the remote
341
+ side.
342
+
343
+ **Channel sizing.** Size channels based on expected payment volume. A 1,000,000
344
+ sat channel can handle many 100-sat L402 payments before rebalancing is needed.
345
+ Monitor channel balances and open new channels proactively.
346
+
347
+ **TLS for aperture.** Use `--autocert` with a domain name for automatic Let's
348
+ Encrypt TLS, or provide your own certificate. Never run `--insecure` on
349
+ public-facing endpoints.
350
+
351
+ **Stopping everything.**
352
+
353
+ ```bash
354
+ skills/aperture/scripts/stop.sh
355
+ skills/lnd/scripts/stop-lnd.sh
356
+ skills/lnd/scripts/stop-lnd.sh --clean # also remove Docker volumes
357
+ ```
@@ -0,0 +1,267 @@
1
+ # L402 and lnget
2
+
3
+ > The payment protocol that makes agent commerce work, and the CLI client that
4
+ > automates it.
5
+
6
+ L402 is an HTTP authentication scheme built on Lightning Network payments. It
7
+ repurposes the HTTP 402 "Payment Required" status code, reserved since the
8
+ early days of the HTTP spec but never widely adopted, to gate access to web
9
+ resources behind Lightning invoices. An agent doesn't need an account, an API
10
+ key, or a pre-existing relationship with the server. It pays a Lightning invoice
11
+ and receives access. That's it.
12
+
13
+ `lnget` is a command-line HTTP client (in the tradition of `wget` and `curl`)
14
+ that handles L402 payments automatically. When it encounters a 402 response, it
15
+ pays the embedded invoice, caches the resulting token, and retries the request.
16
+ To the agent, the paid resource looks like any other HTTP fetch.
17
+
18
+ ## The L402 Protocol
19
+
20
+ An L402 exchange has four steps:
21
+
22
+ ```mermaid
23
+ sequenceDiagram
24
+ participant C as Client (lnget)
25
+ participant S as Server (aperture)
26
+ participant LN as Lightning Network
27
+
28
+ C->>S: GET /api/resource
29
+ S-->>C: 402 Payment Required<br/>WWW-Authenticate: L402<br/>macaroon="...", invoice="lnbc..."
30
+
31
+ Note over C: Parse macaroon and BOLT11 invoice<br/>Check: amount ≤ max-cost?
32
+
33
+ C->>LN: Pay BOLT11 invoice
34
+ LN-->>C: Preimage (proof of payment)
35
+
36
+ Note over C: Construct token: macaroon + preimage<br/>Cache token for this domain
37
+
38
+ C->>S: GET /api/resource<br/>Authorization: L402 <macaroon>:<preimage>
39
+ S-->>C: 200 OK + response body
40
+ ```
41
+
42
+ **Step 1: The challenge.** The client requests a protected resource. The server
43
+ responds with HTTP 402 and a `WWW-Authenticate` header containing two values: a
44
+ macaroon (a bearer token encoding the access grant) and a BOLT11 Lightning
45
+ invoice (the payment request).
46
+
47
+ **Step 2: Payment.** The client decodes the BOLT11 invoice, verifies the amount
48
+ is acceptable, and pays it through the Lightning Network. Payment settlement
49
+ reveals a preimage, a 32-byte value that serves as cryptographic proof of
50
+ payment.
51
+
52
+ **Step 3: Token construction.** The client combines the macaroon from the
53
+ challenge with the preimage from the payment to form an L402 token. This token
54
+ is cached locally for future requests to the same domain.
55
+
56
+ **Step 4: Authenticated retry.** The client retries the original request with an
57
+ `Authorization: L402 <macaroon>:<preimage>` header. The server validates the
58
+ token (verifying that the preimage matches the payment hash embedded in the
59
+ macaroon) and serves the resource.
60
+
61
+ The key property of L402 is that credentials are **purchased, not provisioned**.
62
+ There is no signup flow, no API key management, no OAuth dance. Any client with
63
+ access to the Lightning Network can authenticate with any L402 server
64
+ instantly. This is what makes L402 native to agent workflows: agents can
65
+ discover and pay for resources on the fly without requiring a human to pre-register
66
+ accounts.
67
+
68
+ ## lnget
69
+
70
+ `lnget` automates the entire L402 flow in a single command:
71
+
72
+ ```bash
73
+ lnget https://api.example.com/premium-data.json
74
+ ```
75
+
76
+ If the server returns 200, lnget writes the response to stdout (or a file with
77
+ `-o`). If it returns 402, lnget parses the challenge, pays the invoice, caches
78
+ the token, and retries. All of this is transparent. Subsequent requests to the same
79
+ domain reuse the cached token without additional payment.
80
+
81
+ ### Installation
82
+
83
+ ```bash
84
+ skills/lnget/scripts/install.sh
85
+ ```
86
+
87
+ This runs `go install github.com/lightninglabs/lnget/cmd/lnget@latest`.
88
+
89
+ ### Lightning Backends
90
+
91
+ lnget needs a Lightning backend to pay invoices. It supports three:
92
+
93
+ ```mermaid
94
+ graph TD
95
+ lnget["lnget"]
96
+
97
+ lnget -->|"mode: lnd"| lnd["lnd (direct gRPC)<br/>Requires: host, TLS cert, macaroon<br/>Full payment capabilities"]
98
+ lnget -->|"mode: lnc"| lnc["LNC (Lightning Node Connect)<br/>Requires: pairing phrase<br/>Encrypted tunnel, no direct access"]
99
+ lnget -->|"mode: neutrino"| neutrino["Neutrino (embedded wallet)<br/>Self-contained light client<br/>No external node needed"]
100
+ ```
101
+
102
+ **lnd (direct gRPC).** Connects to an lnd node over gRPC using a TLS
103
+ certificate and macaroon. This is the standard mode when the agent runs its own
104
+ lnd node via the `lnd` skill. Configure with:
105
+
106
+ ```bash
107
+ lnget config init # auto-detects local lnd
108
+ ```
109
+
110
+ Or manually in `~/.lnget/config.yaml`:
111
+
112
+ ```yaml
113
+ ln:
114
+ mode: lnd
115
+ lnd:
116
+ host: localhost:10009
117
+ tls_cert: ~/.lnd/tls.cert
118
+ macaroon: ~/.lnd/data/chain/bitcoin/mainnet/admin.macaroon
119
+ network: mainnet
120
+ ```
121
+
122
+ Use a `pay-only` macaroon instead of `admin.macaroon` for agents. See
123
+ [Security](security.md#preset-roles).
124
+
125
+ **LNC (Lightning Node Connect).** Connects through an encrypted WebSocket
126
+ tunnel using a pairing phrase. No direct network access to the lnd node is
127
+ needed. Pair with:
128
+
129
+ ```bash
130
+ lnget ln lnc pair "your ten word pairing phrase from lightning terminal"
131
+ ```
132
+
133
+ **Neutrino (embedded wallet).** lnget runs its own lightweight Lightning wallet
134
+ internally, using the Neutrino light client. No external lnd node required.
135
+ Initialize with:
136
+
137
+ ```bash
138
+ lnget ln neutrino init
139
+ lnget ln neutrino fund # generates a funding address
140
+ ```
141
+
142
+ This mode is useful for quick experiments but has limited routing capability
143
+ compared to a full lnd node.
144
+
145
+ ## Spending Controls
146
+
147
+ Autonomous agents should never have unlimited spending authority. lnget provides
148
+ two mechanisms for cost control:
149
+
150
+ **Per-request ceiling.** The `--max-cost` flag sets the maximum amount (in
151
+ satoshis) that lnget will auto-pay for a single request. If the invoice exceeds
152
+ this amount, lnget exits with code 2 without paying:
153
+
154
+ ```bash
155
+ lnget --max-cost 500 https://api.example.com/data
156
+ ```
157
+
158
+ **Preview mode.** The `--no-pay` flag sends the request and displays the L402
159
+ challenge (including the invoice amount) without paying. Agents can inspect
160
+ costs before committing:
161
+
162
+ ```bash
163
+ lnget --no-pay --json https://api.example.com/data | jq '.invoice_amount_sat'
164
+ ```
165
+
166
+ For node-level spending limits, use the `macaroon-bakery` to bake a `pay-only`
167
+ macaroon. This restricts the agent to payment operations only and prevents it
168
+ from opening channels, modifying configuration, or performing other
169
+ state-changing operations on the node.
170
+
171
+ ### Exit Codes
172
+
173
+ | Code | Meaning |
174
+ |------|---------|
175
+ | 0 | Request succeeded |
176
+ | 1 | General error |
177
+ | 2 | Invoice amount exceeds `--max-cost` |
178
+ | 3 | Lightning payment failed |
179
+ | 4 | Network or connection error |
180
+
181
+ ## Token Caching
182
+
183
+ Paid L402 tokens are cached at `~/.lnget/tokens/<domain>/` and reused
184
+ automatically on subsequent requests to the same domain. This means an agent
185
+ pays once per domain (until the token expires) rather than once per request.
186
+
187
+ Manage cached tokens with:
188
+
189
+ ```bash
190
+ lnget tokens list # list all cached tokens
191
+ lnget tokens show api.example.com # show token for a specific domain
192
+ lnget tokens remove api.example.com # remove a token (force re-payment)
193
+ lnget tokens clear --force # clear all tokens
194
+ ```
195
+
196
+ ## Configuration
197
+
198
+ lnget reads its configuration from `~/.lnget/config.yaml`. Initialize it with:
199
+
200
+ ```bash
201
+ lnget config init # creates config with defaults, auto-detects local lnd
202
+ lnget config show # display current config
203
+ lnget config path # print config file path
204
+ ```
205
+
206
+ The config file controls L402 behavior, HTTP settings, Lightning backend
207
+ selection, and output formatting:
208
+
209
+ ```yaml
210
+ l402:
211
+ max_cost_sats: 1000 # default spending ceiling
212
+ max_fee_sats: 10 # max routing fee
213
+ payment_timeout: 60s
214
+ auto_pay: true # pay automatically on 402
215
+
216
+ http:
217
+ timeout: 30s
218
+ max_redirects: 10
219
+ user_agent: "lnget/0.1.0"
220
+ allow_insecure: false # set true for self-signed certs (dev only)
221
+
222
+ ln:
223
+ mode: lnd # lnd | lnc | neutrino
224
+
225
+ output:
226
+ format: json
227
+ progress: true
228
+ verbose: false
229
+
230
+ tokens:
231
+ dir: ~/.lnget/tokens
232
+ ```
233
+
234
+ ## Common Usage Patterns
235
+
236
+ ```bash
237
+ # Fetch and pipe to jq
238
+ lnget -q https://api.example.com/data.json | jq .
239
+
240
+ # Save to file
241
+ lnget -o data.json https://api.example.com/data.json
242
+
243
+ # POST with body
244
+ lnget -X POST -d '{"query":"test"}' https://api.example.com/search
245
+
246
+ # Check backend connection
247
+ lnget ln status
248
+ lnget ln info
249
+
250
+ # Track total spending
251
+ lnget tokens list --json | jq '[.[] | .amount_paid_sat] | add'
252
+ ```
253
+
254
+ ## The Server Side: Aperture
255
+
256
+ lnget handles the client side of L402. On the server side,
257
+ [Aperture](https://github.com/lightninglabs/aperture) is an L402-aware reverse
258
+ proxy that sits in front of a backend HTTP service and gates access behind
259
+ Lightning payments.
260
+
261
+ Aperture handles invoice generation (through its connected lnd node), L402
262
+ challenge issuance, token validation, and request proxying. The backend service
263
+ doesn't need any awareness of Lightning or L402. It just serves HTTP requests
264
+ that arrive through aperture.
265
+
266
+ For a complete walkthrough of setting up both the client and server sides, see
267
+ [Commerce](commerce.md).