Reference
CLI
livybolt is the primary way to use Livybolt. It generates and holds your keys locally, pays Lightning invoices in two phases, and decrypts responses on your machine. The server never sees a private key.
Install
npm i -g livybolt
livybolt --helpEvery command talks to https://livybolt.com by default. Override it with --host on any command, or the LIVYBOLT_HOST environment variable.
The whole loop
livybolt id new --password "correct horse battery staple"
livybolt create survey.json # → invoice + handle
# ...pay the invoice...
livybolt create --resume <handle> --preimage <hex> # → public URL + vaulted
livybolt balance --survey <id> # watch the pool fill
livybolt vault read --survey <id> # decrypt responses locally
livybolt unlock --survey <id> --count 25 # got more than you prepaid?
livybolt unlock --resume <handle> --preimage <hex> # pay to read the overageEverything below is the reference for those commands.
Concepts
- Seed — one BIP-39 mnemonic from
livybolt id new, stored at~/.livybolt/identity.json. Everything derives from it: the identity key at account 0, each per-survey key at the next index. The 12 words are the single backup. - Identity key — account 0. Locks your vault at rest; never sent to the server, encrypts no responses.
- Per-survey key — derived at a fresh index by
livybolt create. Its public half is the survey'sencryption_pubkey(answers are sealed to it); its private half decrypts responses and signs your reads. Derived, so never stored — it re-derives from the seed on demand. - Vault —
~/.livybolt/vault.jsonl, sealed to your identity. Per survey it holds only the id and key index — no secrets. Lose it andlivybolt vault rebuildreconstructs it from the seed.
Reads are authenticated by the survey's own keys. The CLI signs a short-lived NIP-98 proof with the per-survey key, and the server checks the signer is one of that survey's registered pubkeys (encryption_pubkey, or view_pubkey for the dashboard) — so the identity key signs nothing and there is no read token to store or leak. NIP-98 is the only read auth.
livybolt id
Manage your self-custody identity. All operations are local.
| Command | What it does |
|---|---|
livybolt id new | Generate a fresh identity. Prints the npub + seed words once. Seal at rest with --password, or store unencrypted with --plaintext (local at-rest choice only — unrelated to response encryption). |
livybolt id show | Print the stored npub / x-only pubkey. Never prints the secret. |
livybolt id export | Print the ncryptsec1… backup blob — the password-encrypted seed, restored with --ncryptsec. It is not a portable nsec; your seed words are the canonical backup. |
livybolt id restore | Rebuild the store from --seed "<words>" or --ncryptsec <blob>. |
livybolt id unlock | Verify the store opens (prompts for the password if encrypted). |
Back up your seed words. They are shown once and never sent anywhere. With them you can restore the identity and rebuild every survey's decrypt key from scratch (livybolt vault rebuild). Lose the seed and every response ever sealed to your surveys is permanently unreadable — there is no server-side copy and no other recovery.
livybolt create
Two-phase, because you pay the invoice out of band. Phase 1 derives the next per-survey key pair from your seed — the encryption key and its dashboard view key, at the same index — sends only their public halves, and returns an invoice + a short handle. Phase 2 mints the survey after you pay.
# phase 1 — describe the survey, get an invoice
livybolt create survey.json
# handle: 9f3a2b1c0d
# total: 5100 sats
# invoice: lnbc...
# pay the invoice with any Lightning wallet, then:
# phase 2 — mint after paying
livybolt create --resume 9f3a2b1c0d --preimage <preimage-hex>
# survey created ✔
# public: https://livybolt.com/s/<slug>
# Sealed into your vault.Phase 2 seals the new survey's id and key index into your vault, so a later livybolt vault read can re-derive the decrypt key and open the responses — you never handle keys by hand.
survey.json
{
"title": "Launch feedback",
"expected_responses": 100,
"per_response_sats": 50,
"questions": [
{ "id": "q1", "text": "How did you hear about us?", "type": "short_text" },
{ "id": "q2", "text": "How likely are you to recommend us?", "type": "rating" },
{ "id": "q3", "text": "Any other thoughts?", "type": "open_ended", "required": false }
]
}| Field | Required | Notes |
|---|---|---|
title | yes | Shown on the public form. |
expected_responses | yes | 1–100,000. Size of the prepaid pool. The first N submissions are immediately readable; overage is locked. |
per_response_sats | no | Defaults to the server price (50). Metering fee — respondents are not paid. |
questions[] | yes | Each needs id, text, type. Optional required (default true). |
Question type is one of: multiple_choice, multiple_select, open_ended, short_text, rating, yes_no. Choice types take an options array.
What you pay
total = create_fee + (expected_responses × per_response_sats)
= 100 + (100 × 50)
= 5,100 sats, paid once, up frontlivybolt balance
Prepaid-pool accounting for a survey. Owner-gated, no payment.
livybolt balance --survey <id>
# prepaid: 100
# consumed: 40
# remaining: 60 (3000 sats of credit)
# locked: 0 (overage awaiting unlock)
livybolt balance --survey <id> --json # machine-readablelivybolt unlock
Responses beyond the prepaid pool are stored locked. Unlocking pays an L402 invoice to promote the N oldest locked responses (FIFO). Two-phase, like create.
# phase 1 — invoice to unlock 10 overage responses
livybolt unlock --survey <id> --count 10
# handle: 4c5d6e...
# total: 750 sats
# invoice: lnbc...
# pay, then:
# phase 2 — unlock after paying
livybolt unlock --resume 4c5d6e... --preimage <preimage-hex>
# unlocked 10 responses ✔
livybolt vault read --survey <id> # they now appearBoth phases authenticate with NIP-98 signed by the survey key, so each asks for your identity password — phase 2 signs a fresh proof at resume time (the phase-1 signature expires while you pay), and the pending file never holds key material.
livybolt vault
| Command | What it does |
|---|---|
livybolt vault read --survey <id> | Pull responses and decrypt them locally with the per-survey key. Add --json for raw output, --since <iso> to page. |
livybolt vault list | List the surveys held in your vault. |
livybolt vault add --survey <id> --token <tok> | Roll a survey created elsewhere (e.g. via the API) into your vault so the CLI can manage it. |
livybolt vault rebuild [--gap <n>] | Reconstruct the vault from the seed alone. Walks account indexes, asks the server which derived pubkeys map to surveys, and re-seals the matches — recovering every survey after a lost machine. --gap sets how many empty indexes in a row end the scan (default 20). |
vault rebuild is the payoff of derived keys: your 12 seed words restore not just the identity but the full list of surveys and their decrypt keys, with no server-side account and nothing else to back up.
livybolt pair
Provision the browser dashboard with your view seed — the read-only hierarchy derived one-way from your master seed. The CLI asks for a new pairing password (it must differ from your identity password), then prints a QR code and a copyable ncryptsec1… string — the same encrypted blob in two encodings. Scan or paste it on the dashboard and enter the pairing password once; the browser re-wraps the view seed under Face ID / Touch ID / PIN.
livybolt pair # QR + pairing string
livybolt pair --no-qr # string onlyThe blob is durable and reusable — keep it in a password manager to pair future browsers without this machine. It grants read access only; your master seed and identity never leave the CLI.
Environment & files
| Name | Purpose |
|---|---|
LIVYBOLT_HOST | Override the server (default https://livybolt.com). |
LIVYBOLT_IDENTITY_PASSWORD | Non-interactive password for an encrypted identity (CI / agents). |
~/.livybolt/identity.json | Your identity key (encrypted if you set a password). |
~/.livybolt/vault.jsonl | Per-survey id + key index (no secrets), sealed to your identity. Rebuildable from the seed. |
~/.livybolt/pending/<handle>.json | In-flight create/unlock invoices awaiting payment (mode 0600). |