Files
n_signer/client/n_signer_client_README.md

7.0 KiB

nsigner_client — Linux CLI for n_signer

A standalone Linux command-line client that connects to a running n_signer process and calls its JSON-RPC verbs over stdin/stdout. Designed for pipe-to-nak workflows.

Build

make clients

Produces build/nsigner_client. Links nostr_core_lib exactly like the existing examples.

Usage

nsigner_client [global options] <verb> [verb args...]

Global options

Flag Default Meaning
--socket-name, -n <name> auto-discover Abstract socket name without @
--timeout <ms> 5000 Transport timeout
--tcp <host:port> none TCP transport (requires --auth-privkey)
--serial <device> none USB CDC-ACM serial transport
--qrexec <qube:service> none Qubes qrexec transport
--auth-privkey <32-byte hex> none Auth envelope privkey for TCP
--auth-label <text> none Auth envelope label

Selector options (for nostr_* verbs)

Flag Meaning JSON emitted
--role <name> Named path-role registered in the signer {"role":"<name>"}
--path <path> Full BIP-44 derivation path {"role_path":"<path>"}

Algorithm options (for algorithm-based verbs)

Flag Default Meaning
--algorithm <alg> none secp256k1/ed25519/x25519/ml-dsa-65/slh-dsa-128s/ml-kem-768/otp
--index <N> 0 Algorithm derivation index
--scheme <schnork|ecdsa> schnorr secp256k1 sign/verify only
--encoding <base64|hex> base64 OTP encrypt/decrypt only
--format <plain|structured> plain nostr_get_public_key output shape

Mine-event options

Flag Meaning
--difficulty <N> Target leading zero bits
--threads <N> Mining threads (default 1)
--timeout-sec <N> Mining timeout in seconds

Verb reference

Utility

Verb stdout
list Lists running n_signer abstract sockets (one @name per line)

Metadata

Verb RPC method stdout
get-info get_info raw result JSON (name, version, verbs, algorithms)

Nostr verbs (role-based)

Verb RPC method stdin/argv stdout
get-public-key nostr_get_public_key none pubkey hex (or structured JSON with --format structured)
sign-event nostr_sign_event event JSON from argv or stdin signed event JSON
mine-event nostr_mine_event event JSON from argv or stdin signed mined event JSON
nip04-encrypt <peer> nostr_nip04_encrypt plaintext from argv or stdin ciphertext
nip04-decrypt <peer> nostr_nip04_decrypt ciphertext from argv or stdin plaintext
nip44-encrypt <peer> nostr_nip44_encrypt plaintext from argv or stdin ciphertext
nip44-decrypt <peer> nostr_nip44_decrypt ciphertext from argv or stdin plaintext

Algorithm-based verbs

Verb RPC method argv stdout
get-public-key get_public_key none structured JSON {"algorithm":...,"public_key":...,"key_id":...}
sign <msg-hex> sign hex bytes structured JSON {"signature":...,"algorithm":...,"key_id":...}
verify <msg-hex> <sig-hex> verify hex bytes valid / invalid (exit 0/1)
derive <data> derive UTF-8 data (argv or stdin) structured JSON
encapsulate <peer-pubkey-hex> encapsulate hex structured JSON
decapsulate <ciphertext-hex> decapsulate hex structured JSON
derive-shared-secret <peer-pubkey-hex> derive_shared_secret hex shared secret hex
encrypt <plaintext> encrypt plaintext (base64 by default) ciphertext
decrypt <ciphertext> decrypt ciphertext plaintext

Generic escape hatch

Verb RPC method input stdout
call <method> <method> JSON params array from stdin or argv raw result JSON

Selector explanation

The nostr_* verbs select a key via the options object using both --role and --path:

  • --role <name> --path <path> — Both are required for all nostr_* verbs. The role authorizes the request and determines the encryption scheme. The path selects the specific key to derive. Sends {"role":"<name>","role_path":"<path>"} to the server.
  • --role without --path — Client-side error: --path is required for nostr verbs.
  • --path without --role — Client-side error: --role is required for nostr verbs.

For algorithm verbs, --algorithm and --index populate the options object instead.

Pipe-to-nak recipes

# Get public key
nsigner_client --role main --path "m/44'/1237'/0'/0/0" get-public-key

# Sign an event and publish via nak
echo '{"kind":1,"content":"hello nostr","tags":[],"created_at":1700000000}' \
  | nsigner_client --role main --path "m/44'/1237'/0'/0/0" sign-event \
  | nak publish

# Mine a proof-of-work event
echo '{"kind":1,"content":"pow","tags":[],"created_at":1700000000}' \
  | nsigner_client --role main --path "m/44'/1237'/0'/0/0" mine-event --difficulty 20 --threads 4

# NIP-44 encrypt
nsigner_client --role main --path "m/44'/1237'/0'/0/0" nip44-encrypt <peer-pubkey> "secret message"

# Algorithm-based signing
nsigner_client --algorithm ed25519 --index 0 sign 68656c6c6f

# Verify a signature
nsigner_client --algorithm secp256k1 verify <msg-hex> <sig-hex> && echo "valid"

# Get signer info
nsigner_client get-info

Transport options

Transport Flag Notes
UNIX abstract socket --socket-name <name> or auto-discover Default. Auto-discovers if exactly one @nsigner* socket exists.
TCP --tcp <host:port> Requires --auth-privkey for auth envelope.
Serial (USB CDC-ACM) --serial <device> e.g. --serial /dev/ttyACM0
Qubes qrexec --qrexec <qube:service> e.g. --qrexec sys-signer:qubes.NsignerRpc

Exit codes

Code Meaning
0 Success
1 Invalid (verify verb only — signature is invalid)
2 Error (transport, RPC, or usage error)

For verify: exit 0 = valid signature, exit 1 = invalid signature, exit 2 = error.

stdin/stdout contract

  • All payload output goes to stdout as a single line, newline-terminated.
  • All diagnostics (errors, warnings) go to stderr.
  • sign-event, nip04-*, nip44-*, derive, encrypt, decrypt read their payload from argv if present, otherwise from stdin (one line).
  • sign, verify, encapsulate, decapsulate, derive-shared-secret take hex from argv only (binary payloads).
  • call reads a JSON params array from stdin (one line) or argv.

See also