The agentic L402 payments client. One CLI · Two custody modes · Pay any HTTP-402 API over Lightning.
Install · Quick start · Docs · SKILL for AI agents · Discussions
Loka Payment CLI + Go SDK. Pay L402-protected (HTTP 402) APIs over Lightning — settlement chain is whatever your lnd backend speaks (today: BTC and SUI; EVM-class chains on the roadmap), and the same one-liner CLI works against two custody models:
| Route | Wallet location | Backend | When to pick it |
|---|---|---|---|
| node (recommended) | Your own machine | lnd-sui / lnd-btc REST gateway + macaroon — lokapay node can install + run a loka-lnd for you |
"I want self-custody and direct Lightning channels." |
| hosted | Loka custodial server | agents-pay-service REST + X-Api-Key — https://agents-pay.loka.cash |
"I just want to pay things; don't make me run a node." |
You pick the route once during lokapay init; every subsequent
request / fund / pay command dispatches transparently — the
L402Doer takes a Wallet interface and both backends satisfy it.
┌──────────────┐ hosted: agents-pay.loka.cash ┌─────────────────────┐
│ lokapay │ ───────────────────────────────►│ agents-pay-service │
│ (CLI/SDK) │ │ + lnd backend │
│ │ node: your own lnd └─────────────────────┘
│ │ ───────────────────────────────► loka-lnd (BTC / SUI / …)
└──────────────┘
│ L402 challenge / preimage replay
└──────► Prism (prism.loka.cash)
# curl (recommended — works on macOS / Linux)
curl -fsSL https://github.com/loka-network/paycli/releases/latest/download/install.sh | sh
# Homebrew — coming soon (tap repo + PAT not yet provisioned;
# the goreleaser pipeline is already wired so this lights up
# as soon as loka-network/homebrew-tap is published).
# brew install loka-network/tap/lokapay
# Go (installs from main; requires Go 1.25+)
go install github.com/loka-network/paycli/cmd/lokapay@latestPick the custody route during lokapay init. The rest of the workflow
is mostly the same; the differences are in how funds enter the wallet.
Wallet lives on Loka's agents-pay-service (default
agents-pay.loka.cash). End users top up via Stripe / PayPal — no
Lightning node, no on-chain SUI custody required.
lokapay init # pick route=hosted; register or log in
lokapay services # browse Prism's service catalog
lokapay fund --amount 5 --unit USD --via stripe --open
# opens a Stripe Checkout URL in your browser
lokapay request -i --debug https://service1.prism.loka.cash/data.json
# pays the 402 challenge, returns the responseSee docs/fiat-onramp.md for operator-side Stripe / PayPal setup (API keys, webhooks, test cards).
init downloads + starts a local lnd (Sui-backed), hits the faucet on
devnet/testnet, connects to Loka seed peers, and opens a 5 SUI outbound
channel so routing works immediately. All on-chain capital stays in
your wallet.
lokapay init # pick route=node + guided (default)
# ↳ downloads lnd, spawns it, faucet,
# connect-seeds, openchannel — all in one go
lokapay node status # confirm pubkey + channel is active
lokapay services # browse Prism's service catalog
lokapay request -i --debug https://service1.prism.loka.cash/data.json
# 402 → invoice → local-lnd pays → 200If you need extra SUI later (devnet/testnet only):
lokapay node faucet # top up the lnd walletThe URL you pass to lokapay request is whatever the L402 service
publishes. Prism routes by Host header (matched against each
service's host_regexp in the catalog), not by URL path. In production
the merchant owns a real domain that DNS-resolves to the gateway, so
you just point at it:
lokapay request -i https://api.some-merchant.com/v1/dataFor local dev where everything lives on 127.0.0.1, override the Host
header explicitly to match whichever service's host_regexp you want
(lokapay services shows them all):
# Catalog says service1 has host_regexp=^service1.com$ — fake the Host header.
lokapay request -H "Host: service1.com" --insecure-target -i --debug \
https://127.0.0.1:8080/data.jsonRe-run lokapay init any time to reconfigure (switch route, change
network, point at a different agents-pay-service / prism URL).
Persistent state lives at ~/.lokapay/ (auto-migrated from the legacy
~/.paycli/ on first run). For everything else — fund / pay / topup /
fiat onramp / managed-node lifecycle / SDK usage — read on:
- CLI reference — every command, every flag (incl.
lokapay mcp) - SKILL for AI agents — intent → command map for chat-driven agents
- SDK reference —
github.com/loka-network/paycli/pkg/sdk - Fiat onramp — Stripe / PayPal operator setup
- Manual test playbook — bring up the full local stack and verify
lokapay mcp exposes the CLI as a stdio Model Context Protocol server
so AI clients can drive it via structured JSON tool calls instead of
shell-execing. Add to claude_desktop_config.json:
{
"mcpServers": {
"lokapay": {
"command": "lokapay",
"args": ["mcp"]
}
}
}Exposed tools: whoami, services, pay, request, history. Run
lokapay init in a terminal once first to populate ~/.lokapay/config.json.
Stdio-only by design — no network socket is bound. Details:
docs/cli.md → lokapay mcp.
pkg/sdk/ Go client SDK (importable as github.com/loka-network/paycli/pkg/sdk)
cmd/lokapay/ CLI binary
docs/ CLI + SDK + onramp + integration-test playbooks
scripts/ install.sh + local integration-test runner
.goreleaser.yml release config — tag-driven multi-platform build
Why a separate binary instead of folding this into lncli?
- Upstream rebase friction —
lncliis vendored from upstream lnd; mixing custodial REST commands intocmd/commands/*.gomakes every upstream merge harder. - Different audience, different scope —
lncliis a node operator's gRPC tool.lokapayis an end-user / AI-agent payments CLI with HTTP, L402, fiat-onramp, and managed-node lifecycle on top. - Decoupled dependencies —
lokapayneedsnet/http+urfave/cli+survey/v2. No lnd build tree, no SUI compiler.
The SDK is the seam: any future Go integration (loka-cloud agents, MCP
servers, dashboards) imports pkg/sdk instead of reimplementing
REST + L402 + Stripe + node-install logic.