nostr-bray 1.7.2 → 1.9.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.
- package/dist/cli.js +26 -1
- package/dist/help.d.ts +9 -0
- package/dist/help.js +102 -0
- package/dist/identity/tools.js +7 -7
- package/dist/social/tools.js +5 -5
- package/dist/trust/tools.js +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ import { handleTrustSpokenChallenge, handleTrustSpokenVerify } from './trust/spo
|
|
|
19
19
|
import { handleDuressConfigure, handleDuressActivate } from './safety/handlers.js';
|
|
20
20
|
import { handleZapSend, handleZapBalance, handleZapMakeInvoice, handleZapLookupInvoice, handleZapListTransactions, handleZapReceipts, handleZapDecode } from './zap/handlers.js';
|
|
21
21
|
import { handleDecode, handleEncodeNpub, handleEncodeNote, handleEncodeNprofile, handleEncodeNevent, handleVerify, handleEncrypt, handleDecrypt, handleCount, handleFetch, handleKeyPublic, handleEncodeNsec, handleFilter, handleNipList, handleNipShow } from './util/handlers.js';
|
|
22
|
+
import { getCommandHelp } from './help.js';
|
|
22
23
|
const args = process.argv.slice(2);
|
|
23
24
|
const command = args[0];
|
|
24
25
|
// No command = start MCP server
|
|
@@ -26,6 +27,14 @@ if (!command || command === 'serve') {
|
|
|
26
27
|
await import('./index.js');
|
|
27
28
|
process.exit(0);
|
|
28
29
|
}
|
|
30
|
+
// Per-command help: `nostr-bray post --help`
|
|
31
|
+
if (args.includes('--help') && command && command !== 'help' && command !== '--help' && command !== '-h') {
|
|
32
|
+
const help = getCommandHelp(command);
|
|
33
|
+
if (help) {
|
|
34
|
+
console.log(help);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
29
38
|
const HELP = `nostr-bray — Sovereign Nostr identities for AI agents
|
|
30
39
|
|
|
31
40
|
Usage: nostr-bray [command] [args]
|
|
@@ -127,7 +136,23 @@ Environment:
|
|
|
127
136
|
NOSTR_SECRET_KEY_FILE Path to secret key file
|
|
128
137
|
NOSTR_RELAYS Comma-separated relay URLs
|
|
129
138
|
NWC_URI / NWC_URI_FILE Nostr Wallet Connect URI
|
|
130
|
-
TOR_PROXY SOCKS5h proxy URL
|
|
139
|
+
TOR_PROXY SOCKS5h proxy URL
|
|
140
|
+
|
|
141
|
+
Quick examples:
|
|
142
|
+
nostr-bray whoami # show your npub
|
|
143
|
+
nostr-bray post "gm nostr" # publish a note
|
|
144
|
+
nostr-bray persona work # derive work identity
|
|
145
|
+
nostr-bray dm abc123... "secret message" # send encrypted DM
|
|
146
|
+
nostr-bray decode npub1... # decode any nip19 entity
|
|
147
|
+
nostr-bray nips # browse official NIPs
|
|
148
|
+
nostr-bray shell # interactive mode
|
|
149
|
+
|
|
150
|
+
Use 'nostr-bray <command> --help' for detailed help on any command.
|
|
151
|
+
|
|
152
|
+
Learn more:
|
|
153
|
+
Guide: https://github.com/forgesworn/bray/blob/main/docs/guide.md
|
|
154
|
+
Examples: https://github.com/forgesworn/bray/tree/main/examples
|
|
155
|
+
npm: https://www.npmjs.com/package/nostr-bray`;
|
|
131
156
|
if (command === 'help' || command === '--help' || command === '-h') {
|
|
132
157
|
console.log(HELP);
|
|
133
158
|
process.exit(0);
|
package/dist/help.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Per-command help with examples and detail */
|
|
2
|
+
export declare const COMMAND_HELP: Record<string, {
|
|
3
|
+
usage: string;
|
|
4
|
+
description: string;
|
|
5
|
+
examples: string[];
|
|
6
|
+
notes?: string;
|
|
7
|
+
}>;
|
|
8
|
+
/** Get formatted help for a single command */
|
|
9
|
+
export declare function getCommandHelp(cmd: string): string | null;
|
package/dist/help.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/** Per-command help with examples and detail */
|
|
2
|
+
export const COMMAND_HELP = {
|
|
3
|
+
// Identity
|
|
4
|
+
whoami: { usage: 'whoami', description: 'Show the active identity\'s npub.', examples: ['nostr-bray whoami'] },
|
|
5
|
+
create: { usage: 'create', description: 'Generate a fresh Nostr identity with a BIP-39 mnemonic seed. Returns the master npub and mnemonic for backup.', examples: ['nostr-bray create'], notes: 'Store the mnemonic securely — it will not be shown again.' },
|
|
6
|
+
list: { usage: 'list', description: 'List all known identities. Returns npub, purpose, and persona name. Never includes private keys.', examples: ['nostr-bray list'] },
|
|
7
|
+
derive: { usage: 'derive <purpose> [index]', description: 'Derive a child identity by purpose string and optional index. Deterministic — same inputs always produce the same npub.', examples: ['nostr-bray derive messaging', 'nostr-bray derive signing 0', 'nostr-bray derive signing 1 # different index = different key'] },
|
|
8
|
+
persona: { usage: 'persona <name> [index]', description: 'Derive a named persona (e.g. work, personal, anonymous). Shorthand for deriving with a semantic name.', examples: ['nostr-bray persona work', 'nostr-bray persona anonymous'] },
|
|
9
|
+
switch: { usage: 'switch <target> [index]', description: 'Switch the active identity. All subsequent operations sign as the new identity. Use "master" to return to root.', examples: ['nostr-bray switch work', 'nostr-bray switch master', 'nostr-bray switch messaging 0'] },
|
|
10
|
+
prove: { usage: 'prove [blind|full]', description: 'Create a cryptographic linkage proof between the master key and the active identity.\n blind — proves the link without revealing the derivation path (default)\n full — reveals the purpose and index (use with care)', examples: ['nostr-bray prove', 'nostr-bray prove blind', 'nostr-bray prove full'] },
|
|
11
|
+
'proof-publish': { usage: 'proof-publish [blind|full] [--confirm]', description: 'Publish a linkage proof to relays as a kind 30078 event. This is IRREVERSIBLE — once published, the link between identities is public.', examples: ['nostr-bray proof-publish blind', 'nostr-bray proof-publish full --confirm'], notes: 'Without --confirm, shows a preview of what will be revealed.' },
|
|
12
|
+
backup: { usage: 'backup <dir> [threshold] [shares]', description: 'Split the active identity\'s private key into Shamir shards written to files. Default is 3-of-5 (any 3 shards reconstruct the key). Shard files use 0600 permissions.', examples: ['nostr-bray backup ./shards', 'nostr-bray backup ./shards 2 3 # 2-of-3 scheme'] },
|
|
13
|
+
restore: { usage: 'restore <file1> <file2> ... -t <threshold>', description: 'Reconstruct a secret key from Shamir shard files.', examples: ['nostr-bray restore ./shards/shard-1.bray ./shards/shard-2.bray -t 2'] },
|
|
14
|
+
'identity-backup': { usage: 'identity-backup <pubkey-hex>', description: 'Fetch profile (kind 0), contacts (kind 3), relay list (kind 10002), and attestations for a pubkey. Returns a portable JSON bundle — no private keys.', examples: ['nostr-bray identity-backup abc123...'] },
|
|
15
|
+
'identity-restore': { usage: 'identity-restore <pubkey-hex>', description: 'Re-sign migratable events (profile, contacts, relay list) under the active identity. Skips attestations to protect the trust chain.', examples: ['nostr-bray identity-restore abc123...'] },
|
|
16
|
+
migrate: { usage: 'migrate <old-hex> <old-npub> [--confirm]', description: 'Full identity migration. Preview first (shows profile fields, contact count), then execute with --confirm. Publishes a linkage proof and re-signs migratable events.', examples: ['nostr-bray migrate abc123... npub1old...', 'nostr-bray migrate abc123... npub1old... --confirm'] },
|
|
17
|
+
// Social
|
|
18
|
+
post: { usage: 'post "message"', description: 'Publish a text note (kind 1) as the active identity.', examples: ['nostr-bray post "gm nostr"', 'nostr-bray post "Hello from my work persona!"'] },
|
|
19
|
+
reply: { usage: 'reply <event-id> <pubkey> "text"', description: 'Reply to a Nostr event with correct e-tag and p-tag threading.', examples: ['nostr-bray reply abc123... def456... "Great post!"'] },
|
|
20
|
+
react: { usage: 'react <event-id> <pubkey> [emoji]', description: 'React to a Nostr event (kind 7). Defaults to "+" if no emoji specified.', examples: ['nostr-bray react abc123... def456...', 'nostr-bray react abc123... def456... 🤙'] },
|
|
21
|
+
delete: { usage: 'delete <event-id> [reason]', description: 'Request deletion of an event you published (kind 5). Relays may or may not honour the request.', examples: ['nostr-bray delete abc123...', 'nostr-bray delete abc123... "posted by mistake"'] },
|
|
22
|
+
repost: { usage: 'repost <event-id> <pubkey>', description: 'Repost/boost a Nostr event (kind 6).', examples: ['nostr-bray repost abc123... def456...'] },
|
|
23
|
+
profile: { usage: 'profile <pubkey-hex>', description: 'Fetch and display a Nostr profile (kind 0) for any pubkey.', examples: ['nostr-bray profile abc123...'] },
|
|
24
|
+
'profile-set': { usage: 'profile-set \'{"name":"...","about":"..."}\'', description: 'Set the kind 0 profile for the active identity. If a profile already exists, shows a diff and requires --confirm to overwrite.', examples: ['nostr-bray profile-set \'{"name":"Bray User","about":"Powered by nostr-bray"}\'', 'nostr-bray profile-set \'{"name":"Updated"}\' --confirm'] },
|
|
25
|
+
contacts: { usage: 'contacts <pubkey-hex>', description: 'List who a pubkey follows (kind 3 contact list). Shows pubkeys, relay hints, and petnames.', examples: ['nostr-bray contacts abc123...'] },
|
|
26
|
+
follow: { usage: 'follow <pubkey-hex> [relay] [petname]', description: 'Follow a pubkey. Fetches current contact list, adds the pubkey, publishes updated kind 3.', examples: ['nostr-bray follow abc123...', 'nostr-bray follow abc123... wss://relay.example.com alice'] },
|
|
27
|
+
unfollow: { usage: 'unfollow <pubkey-hex>', description: 'Unfollow a pubkey. Removes from contact list and publishes updated kind 3.', examples: ['nostr-bray unfollow abc123...'] },
|
|
28
|
+
dm: { usage: 'dm <pubkey-hex> "message" [--nip04]', description: 'Send an encrypted direct message. Uses NIP-17 gift wrap by default (most private — sender identity hidden behind ephemeral key). Add --nip04 for legacy NIP-04 (requires NIP04_ENABLED=1).', examples: ['nostr-bray dm abc123... "Secret message"', 'nostr-bray dm abc123... "Legacy DM" --nip04'] },
|
|
29
|
+
'dm-read': { usage: 'dm-read', description: 'Read direct messages addressed to the active identity. Decrypts both NIP-17 and NIP-04 messages. Returns error metadata (not crash) on decryption failure.', examples: ['nostr-bray dm-read'] },
|
|
30
|
+
feed: { usage: 'feed [--limit N]', description: 'Fetch the kind 1 text note feed from your relays.', examples: ['nostr-bray feed', 'nostr-bray feed --limit 10'] },
|
|
31
|
+
notifications: { usage: 'notifications [--limit N]', description: 'Fetch mentions, replies, reactions, and zap receipts for the active identity.', examples: ['nostr-bray notifications', 'nostr-bray notifications --limit 5'] },
|
|
32
|
+
'nip-publish': { usage: 'nip-publish <identifier> <title> <content-or-file> [--kinds N,N]', description: 'Publish a community NIP (kind 30817) — a custom protocol specification on Nostr. Content can be inline markdown or a file path.', examples: ['nostr-bray nip-publish my-protocol "My Protocol" ./spec.md', 'nostr-bray nip-publish gaming "Gaming Events" ./gaming.md --kinds 30100,30101'] },
|
|
33
|
+
'nip-read': { usage: 'nip-read [--author X] [--kind N] [--identifier X]', description: 'Fetch community NIPs (kind 30817) from relays.', examples: ['nostr-bray nip-read', 'nostr-bray nip-read --author abc123...', 'nostr-bray nip-read --kind 30100'] },
|
|
34
|
+
// Blossom
|
|
35
|
+
'blossom-upload': { usage: 'blossom-upload <server> <file>', description: 'Upload a file to a blossom media server. Signs a kind 24242 auth event. Returns the blob URL and SHA-256 hash.', examples: ['nostr-bray blossom-upload https://blossom.example.com ./photo.jpg'] },
|
|
36
|
+
'blossom-list': { usage: 'blossom-list <server> <pubkey-hex>', description: 'List blobs uploaded by a pubkey on a blossom server.', examples: ['nostr-bray blossom-list https://blossom.example.com abc123...'] },
|
|
37
|
+
'blossom-delete': { usage: 'blossom-delete <server> <sha256>', description: 'Delete a blob from a blossom media server by its SHA-256 hash.', examples: ['nostr-bray blossom-delete https://blossom.example.com deadbeef...'] },
|
|
38
|
+
// Groups
|
|
39
|
+
'group-info': { usage: 'group-info <group-id>', description: 'Fetch NIP-29 group metadata (name, about, picture, open status).', examples: ['nostr-bray group-info my-group'] },
|
|
40
|
+
'group-chat': { usage: 'group-chat <group-id> [--limit N]', description: 'Fetch recent chat messages (kind 9) from a NIP-29 group.', examples: ['nostr-bray group-chat my-group', 'nostr-bray group-chat my-group --limit 50'] },
|
|
41
|
+
'group-send': { usage: 'group-send <group-id> "message"', description: 'Send a message to a NIP-29 group (kind 9 with h-tag).', examples: ['nostr-bray group-send my-group "Hello group!"'] },
|
|
42
|
+
'group-members': { usage: 'group-members <group-id>', description: 'List members of a NIP-29 group.', examples: ['nostr-bray group-members my-group'] },
|
|
43
|
+
// Trust
|
|
44
|
+
attest: { usage: 'attest <type> <identifier> [subject]', description: 'Create and publish a kind 31000 verifiable attestation (NIP-VA).', examples: ['nostr-bray attest identity-verification abc123... def456...', 'nostr-bray attest endorsement org-member'] },
|
|
45
|
+
'trust-read': { usage: 'trust-read [--subject X] [--type X] [--attestor X]', description: 'Read kind 31000 attestations from relays. All filters are optional.', examples: ['nostr-bray trust-read --subject abc123...', 'nostr-bray trust-read --type identity-verification'] },
|
|
46
|
+
'trust-verify': { usage: 'trust-verify <event-json>', description: 'Validate the structural correctness of a kind 31000 attestation event.', examples: ['nostr-bray trust-verify \'{"kind":31000,...}\''] },
|
|
47
|
+
'trust-revoke': { usage: 'trust-revoke <type> <identifier>', description: 'Revoke a previously issued attestation. Active identity must match the original attestor.', examples: ['nostr-bray trust-revoke identity-verification abc123...'] },
|
|
48
|
+
'trust-request': { usage: 'trust-request <pubkey> <subject> <type>', description: 'Send an attestation request via NIP-17 encrypted DM.', examples: ['nostr-bray trust-request abc123... def456... identity-verification'] },
|
|
49
|
+
'trust-request-list': { usage: 'trust-request-list', description: 'Scan received NIP-17 DMs for attestation request payloads.', examples: ['nostr-bray trust-request-list'] },
|
|
50
|
+
'ring-prove': { usage: 'ring-prove <type> <pk1,pk2,...>', description: 'Create a ring signature proving anonymous group membership. Your active identity must be one of the pubkeys in the comma-separated ring.', examples: ['nostr-bray ring-prove kyc-verified abc123,def456,ghi789'] },
|
|
51
|
+
'ring-verify': { usage: 'ring-verify <event-json>', description: 'Verify a ring signature proof.', examples: ['nostr-bray ring-verify \'{"kind":30078,...}\''] },
|
|
52
|
+
'spoken-challenge': { usage: 'spoken-challenge <secret> <context> <counter>', description: 'Generate a spoken verification token for in-person identity confirmation. Both parties share a secret and verify via spoken words.', examples: ['nostr-bray spoken-challenge aabbccdd... meeting-2026-03-25 1'] },
|
|
53
|
+
'spoken-verify': { usage: 'spoken-verify <secret> <context> <counter> <input>', description: 'Verify a spoken token response.', examples: ['nostr-bray spoken-verify aabbccdd... meeting-2026-03-25 1 castle'] },
|
|
54
|
+
// Relay
|
|
55
|
+
'relay-list': { usage: 'relay-list [--compare npub]', description: 'List the relay set (read/write) for the active identity. Optionally warn about shared relays with another identity.', examples: ['nostr-bray relay-list', 'nostr-bray relay-list --compare npub1other...'] },
|
|
56
|
+
'relay-set': { usage: 'relay-set <url1> <url2> ... [--confirm]', description: 'Publish a kind 10002 relay list. Warns if one already exists — use --confirm to overwrite.', examples: ['nostr-bray relay-set wss://relay.damus.io wss://nos.lol', 'nostr-bray relay-set wss://relay.damus.io --confirm'] },
|
|
57
|
+
'relay-add': { usage: 'relay-add <url> [read|write]', description: 'Add a relay to the active identity\'s relay set (in-memory only — does not publish kind 10002).', examples: ['nostr-bray relay-add wss://new-relay.com', 'nostr-bray relay-add wss://read-only.com read'] },
|
|
58
|
+
'relay-info': { usage: 'relay-info <wss://url>', description: 'Fetch the NIP-11 relay information document (name, description, supported NIPs, limits).', examples: ['nostr-bray relay-info wss://relay.damus.io'] },
|
|
59
|
+
// Zap
|
|
60
|
+
'zap-send': { usage: 'zap-send <bolt11>', description: 'Pay a Lightning invoice via Nostr Wallet Connect (NIP-47). Requires NWC_URI configured.', examples: ['nostr-bray zap-send lnbc10u1...'] },
|
|
61
|
+
'zap-balance': { usage: 'zap-balance', description: 'Request wallet balance via NWC.', examples: ['nostr-bray zap-balance'] },
|
|
62
|
+
'zap-invoice': { usage: 'zap-invoice <msats> [description]', description: 'Generate a Lightning invoice via NWC to receive payments.', examples: ['nostr-bray zap-invoice 100000 "Coffee payment"'] },
|
|
63
|
+
'zap-lookup': { usage: 'zap-lookup <payment-hash>', description: 'Look up a Lightning invoice payment status via NWC.', examples: ['nostr-bray zap-lookup abc123...'] },
|
|
64
|
+
'zap-transactions': { usage: 'zap-transactions [--limit N]', description: 'List recent Lightning transactions via NWC.', examples: ['nostr-bray zap-transactions', 'nostr-bray zap-transactions --limit 5'] },
|
|
65
|
+
'zap-receipts': { usage: 'zap-receipts [--limit N]', description: 'Fetch zap receipts (kind 9735) for the active identity. Returns sender, amount in msats, and message.', examples: ['nostr-bray zap-receipts', 'nostr-bray zap-receipts --limit 10'] },
|
|
66
|
+
'zap-decode': { usage: 'zap-decode <bolt11>', description: 'Decode basic fields from a bolt11 Lightning invoice string.', examples: ['nostr-bray zap-decode lnbc10u1...'] },
|
|
67
|
+
// Safety
|
|
68
|
+
'safety-configure': { usage: 'safety-configure [persona-name]', description: 'Configure an alternative identity persona for emergency use. Defaults to "anonymous".', examples: ['nostr-bray safety-configure', 'nostr-bray safety-configure emergency'] },
|
|
69
|
+
'safety-activate': { usage: 'safety-activate [persona-name]', description: 'Switch to an alternative identity. Response is structurally identical to identity switch — an observer cannot distinguish this from a normal switch.', examples: ['nostr-bray safety-activate', 'nostr-bray safety-activate emergency'] },
|
|
70
|
+
// Utility
|
|
71
|
+
decode: { usage: 'decode <nip19>', description: 'Decode any nip19 entity (npub, nsec, note, nevent, nprofile, naddr) or nostr: URI to its components. For nsec, returns the derived pubkey — never the private key.', examples: ['nostr-bray decode npub1abc...', 'nostr-bray decode nevent1...', 'nostr-bray decode nostr:npub1abc...'] },
|
|
72
|
+
'encode-npub': { usage: 'encode-npub <hex>', description: 'Encode a 64-character hex public key as a bech32 npub.', examples: ['nostr-bray encode-npub abc123...'] },
|
|
73
|
+
'encode-note': { usage: 'encode-note <hex>', description: 'Encode a 64-character hex event ID as a bech32 note.', examples: ['nostr-bray encode-note abc123...'] },
|
|
74
|
+
'encode-nprofile': { usage: 'encode-nprofile <hex> [relay1,relay2,...]', description: 'Encode a hex pubkey with optional relay hints as a bech32 nprofile.', examples: ['nostr-bray encode-nprofile abc123...', 'nostr-bray encode-nprofile abc123... wss://relay.example.com'] },
|
|
75
|
+
'encode-nevent': { usage: 'encode-nevent <hex> [relay1,relay2,...]', description: 'Encode a hex event ID with optional relay hints as a bech32 nevent.', examples: ['nostr-bray encode-nevent abc123... wss://relay.example.com'] },
|
|
76
|
+
'encode-nsec': { usage: 'encode-nsec <hex>', description: 'Encode a 64-character hex private key as a bech32 nsec.', examples: ['nostr-bray encode-nsec abc123...'], notes: 'WARNING: private key is passed as a CLI argument. Use only on trusted systems.' },
|
|
77
|
+
'key-public': { usage: 'key-public <nsec-or-hex>', description: 'Derive a public key (hex + npub) from a secret key.', examples: ['nostr-bray key-public nsec1...', 'nostr-bray key-public abc123...'], notes: 'WARNING: secret key is passed as a CLI argument. Use only on trusted systems.' },
|
|
78
|
+
filter: { usage: 'filter <event-json> <filter-json>', description: 'Test if a Nostr event matches a given filter. Returns true or false.', examples: ['nostr-bray filter \'{"kind":1,...}\' \'{"kinds":[1]}\''] },
|
|
79
|
+
nips: { usage: 'nips', description: 'List all official Nostr NIPs from the protocol repository.', examples: ['nostr-bray nips'] },
|
|
80
|
+
nip: { usage: 'nip <number>', description: 'Fetch and display the full content of an official NIP by number.', examples: ['nostr-bray nip 1', 'nostr-bray nip 17', 'nostr-bray nip 65'] },
|
|
81
|
+
verify: { usage: 'verify <event-json>', description: 'Verify a Nostr event\'s id hash and cryptographic signature.', examples: ['nostr-bray verify \'{"id":"...","pubkey":"...","sig":"...",...}\''] },
|
|
82
|
+
encrypt: { usage: 'encrypt <pubkey-hex> "plaintext"', description: 'Encrypt a string using NIP-44 for a recipient pubkey. Uses the active identity\'s private key.', examples: ['nostr-bray encrypt abc123... "secret message"'] },
|
|
83
|
+
decrypt: { usage: 'decrypt <pubkey-hex> <ciphertext>', description: 'Decrypt a NIP-44 ciphertext using the active identity\'s private key.', examples: ['nostr-bray decrypt abc123... AQBh7...'] },
|
|
84
|
+
count: { usage: 'count [--kinds N,N] [--authors X,X] [--since N]', description: 'Count events matching a filter on relays.', examples: ['nostr-bray count --kinds 1', 'nostr-bray count --kinds 1,7 --authors abc123...'] },
|
|
85
|
+
fetch: { usage: 'fetch <nip19>', description: 'Fetch events by nip19 code (note, nevent, nprofile, npub, naddr). Resolves the entity and queries relays.', examples: ['nostr-bray fetch note1...', 'nostr-bray fetch nevent1...', 'nostr-bray fetch npub1...'] },
|
|
86
|
+
shell: { usage: 'shell', description: 'Start an interactive REPL with a persistent relay connection. Supports tab autocomplete. Type "help" for commands, "exit" to quit.', examples: ['nostr-bray shell'] },
|
|
87
|
+
};
|
|
88
|
+
/** Get formatted help for a single command */
|
|
89
|
+
export function getCommandHelp(cmd) {
|
|
90
|
+
const h = COMMAND_HELP[cmd];
|
|
91
|
+
if (!h)
|
|
92
|
+
return null;
|
|
93
|
+
let out = `\nUsage: nostr-bray ${h.usage}\n\n${h.description}\n`;
|
|
94
|
+
if (h.notes)
|
|
95
|
+
out += `\n ${h.notes}\n`;
|
|
96
|
+
out += '\nExamples:\n';
|
|
97
|
+
for (const ex of h.examples) {
|
|
98
|
+
out += ` ${ex}\n`;
|
|
99
|
+
}
|
|
100
|
+
out += '\nLearn more: https://github.com/forgesworn/bray/blob/main/docs/guide.md';
|
|
101
|
+
return out;
|
|
102
|
+
}
|
package/dist/identity/tools.js
CHANGED
|
@@ -5,7 +5,7 @@ import { hexId } from '../validation.js';
|
|
|
5
5
|
import { handleIdentityBackup, handleIdentityRestore, handleIdentityMigrate } from './migration.js';
|
|
6
6
|
export function registerIdentityTools(server, deps) {
|
|
7
7
|
server.registerTool('identity_create', {
|
|
8
|
-
description: 'Generate a fresh Nostr identity with a BIP-39 mnemonic seed. Returns
|
|
8
|
+
description: 'Generate a fresh Nostr identity with a BIP-39 mnemonic seed. Returns { npub, mnemonic }. Store the mnemonic securely — it will not be shown again. Use this when the user needs a brand new identity unrelated to the current one.',
|
|
9
9
|
annotations: { readOnlyHint: false },
|
|
10
10
|
}, async () => {
|
|
11
11
|
const result = handleIdentityCreate();
|
|
@@ -14,7 +14,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
14
14
|
};
|
|
15
15
|
});
|
|
16
16
|
server.registerTool('identity_derive', {
|
|
17
|
-
description: 'Derive a child Nostr identity from the
|
|
17
|
+
description: 'Derive a child Nostr identity from the master key by purpose and index. Deterministic — same inputs always produce the same npub. Returns { npub, purpose, index }. Use identity_switch after deriving to operate as the new identity.',
|
|
18
18
|
inputSchema: {
|
|
19
19
|
purpose: z.string().describe('Purpose string for derivation (e.g. "messaging", "signing")'),
|
|
20
20
|
index: z.number().int().min(0).default(0).describe('Derivation index (default 0)'),
|
|
@@ -27,7 +27,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
27
27
|
};
|
|
28
28
|
});
|
|
29
29
|
server.registerTool('identity_derive_persona', {
|
|
30
|
-
description: 'Derive a named persona
|
|
30
|
+
description: 'Derive a named persona (e.g. "work", "personal", "anonymous"). Like identity_derive but uses a human-readable name. Returns { npub, personaName, index }. Follow with identity_switch to activate.',
|
|
31
31
|
inputSchema: {
|
|
32
32
|
name: z.string().describe('Persona name (e.g. "work", "personal", "anonymous")'),
|
|
33
33
|
index: z.number().int().min(0).default(0).describe('Derivation index (default 0)'),
|
|
@@ -40,7 +40,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
40
40
|
};
|
|
41
41
|
});
|
|
42
42
|
server.registerTool('identity_switch', {
|
|
43
|
-
description: 'Switch the active Nostr identity.
|
|
43
|
+
description: 'Switch the active Nostr identity. ALL subsequent tool calls will sign events and query relays as the new identity. Pass "master" to return to root. Returns { npub } of the now-active identity. This is the key tool for multi-persona workflows.',
|
|
44
44
|
inputSchema: {
|
|
45
45
|
target: z.string().describe('Purpose, persona name, or "master" to switch to'),
|
|
46
46
|
index: z.number().int().min(0).optional().describe('Derivation index (if switching by purpose)'),
|
|
@@ -53,7 +53,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
53
53
|
};
|
|
54
54
|
});
|
|
55
55
|
server.registerTool('identity_list', {
|
|
56
|
-
description: 'List all known
|
|
56
|
+
description: 'List all known identities (master + all derived). Returns array of { npub, purpose, index, personaName }. Never includes private keys. Use this to see what identities are available before switching.',
|
|
57
57
|
annotations: { readOnlyHint: true },
|
|
58
58
|
}, async () => {
|
|
59
59
|
const result = handleIdentityList(deps.ctx);
|
|
@@ -62,7 +62,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
62
62
|
};
|
|
63
63
|
});
|
|
64
64
|
server.registerTool('identity_prove', {
|
|
65
|
-
description: 'Create a cryptographic linkage proof between the master key and the active identity.
|
|
65
|
+
description: 'Create a cryptographic linkage proof between the master key and the active identity. "blind" (default) proves they share a master without revealing how the child was derived. "full" also reveals the purpose and index. Returns a LinkageProof object that can be verified by anyone with nsec-tree. Use trust_proof_publish to make it permanent on relays.',
|
|
66
66
|
inputSchema: {
|
|
67
67
|
mode: z.enum(['blind', 'full']).default('blind').describe('Proof mode: "blind" hides derivation path, "full" reveals purpose and index'),
|
|
68
68
|
},
|
|
@@ -74,7 +74,7 @@ export function registerIdentityTools(server, deps) {
|
|
|
74
74
|
};
|
|
75
75
|
});
|
|
76
76
|
server.registerTool('identity_backup_shamir', {
|
|
77
|
-
description: 'Split the
|
|
77
|
+
description: 'Split the active identity\'s private key into Shamir shard files using threshold secret sharing. Any "threshold" shards can reconstruct the key. Files written with 0600 permissions via atomic rename. Returns file paths only — shard content never appears in the response.',
|
|
78
78
|
inputSchema: {
|
|
79
79
|
threshold: z.number().int().min(2).describe('Minimum shards needed to reconstruct'),
|
|
80
80
|
shares: z.number().int().min(2).describe('Total number of shards to create'),
|
package/dist/social/tools.js
CHANGED
|
@@ -8,7 +8,7 @@ import { handleBlossomUpload, handleBlossomList, handleBlossomDelete } from './b
|
|
|
8
8
|
import { handleGroupInfo, handleGroupChat, handleGroupSend, handleGroupMembers } from './groups.js';
|
|
9
9
|
export function registerSocialTools(server, deps) {
|
|
10
10
|
server.registerTool('social_post', {
|
|
11
|
-
description: 'Post a text note (kind 1)
|
|
11
|
+
description: 'Post a text note (kind 1) signed by the active identity and publish to relays. Returns { id, pubkey, publish: { success, accepted, rejected } }. The most common social action.',
|
|
12
12
|
inputSchema: {
|
|
13
13
|
content: z.string().describe('Text content of the note'),
|
|
14
14
|
},
|
|
@@ -24,7 +24,7 @@ export function registerSocialTools(server, deps) {
|
|
|
24
24
|
};
|
|
25
25
|
});
|
|
26
26
|
server.registerTool('social_reply', {
|
|
27
|
-
description: 'Reply to a Nostr event (kind 1 with
|
|
27
|
+
description: 'Reply to a Nostr event (kind 1) with correct threading tags. You need the event ID and the author\'s pubkey — get these from social_feed or social_notifications.',
|
|
28
28
|
inputSchema: {
|
|
29
29
|
content: z.string().describe('Reply text'),
|
|
30
30
|
replyTo: hexId.describe('Event ID being replied to (hex)'),
|
|
@@ -42,7 +42,7 @@ export function registerSocialTools(server, deps) {
|
|
|
42
42
|
};
|
|
43
43
|
});
|
|
44
44
|
server.registerTool('social_react', {
|
|
45
|
-
description: 'React to a Nostr event (kind 7)
|
|
45
|
+
description: 'React to a Nostr event (kind 7). Pass "+" for like, or any emoji (🤙, ❤️, 🔥). You need the event ID and author pubkey.',
|
|
46
46
|
inputSchema: {
|
|
47
47
|
eventId: hexId.describe('Event ID to react to (hex)'),
|
|
48
48
|
eventPubkey: hexId.describe('Pubkey of the event author (hex)'),
|
|
@@ -135,7 +135,7 @@ export function registerSocialTools(server, deps) {
|
|
|
135
135
|
};
|
|
136
136
|
});
|
|
137
137
|
server.registerTool('dm_send', {
|
|
138
|
-
description: 'Send
|
|
138
|
+
description: 'Send an encrypted direct message. Default: NIP-17 gift wrap (most private — sender identity hidden behind ephemeral key). Set nip04: true for legacy NIP-04 (only if NIP04_ENABLED=1). Returns { protocol, id, publish }.',
|
|
139
139
|
inputSchema: {
|
|
140
140
|
recipientPubkeyHex: hexId.describe('Recipient hex pubkey'),
|
|
141
141
|
message: z.string().describe('Message text'),
|
|
@@ -160,7 +160,7 @@ export function registerSocialTools(server, deps) {
|
|
|
160
160
|
};
|
|
161
161
|
});
|
|
162
162
|
server.registerTool('dm_read', {
|
|
163
|
-
description: 'Read direct messages addressed to the active identity. Decrypts NIP-17 and NIP-04
|
|
163
|
+
description: 'Read direct messages addressed to the active identity. Decrypts both NIP-17 (gift wrap) and NIP-04 (legacy). Each message includes { from, content, protocol, decrypted }. Gracefully handles decryption failures without crashing.',
|
|
164
164
|
annotations: { readOnlyHint: true },
|
|
165
165
|
}, async () => {
|
|
166
166
|
const messages = await handleDmRead(deps.ctx, deps.pool);
|
package/dist/trust/tools.js
CHANGED
|
@@ -5,7 +5,7 @@ import { handleTrustRingProve, handleTrustRingVerify } from './ring.js';
|
|
|
5
5
|
import { handleTrustSpokenChallenge, handleTrustSpokenVerify } from './spoken.js';
|
|
6
6
|
export function registerTrustTools(server, deps) {
|
|
7
7
|
server.registerTool('trust_attest', {
|
|
8
|
-
description: 'Create and publish a kind 31000 verifiable attestation as the active identity.',
|
|
8
|
+
description: 'Create and publish a kind 31000 verifiable attestation (NIP-VA) as the active identity. An attestation is a signed statement about a subject (e.g. "I verify this pubkey belongs to Alice"). Warns if attesting from a derived persona instead of master. Use trust_read to find existing attestations, trust_revoke to revoke them.',
|
|
9
9
|
inputSchema: {
|
|
10
10
|
type: z.string().describe('Attestation type (e.g. "identity-verification", "endorsement")'),
|
|
11
11
|
identifier: z.string().optional().describe('D-tag identifier (hex pubkey or context string)'),
|
|
@@ -124,7 +124,7 @@ export function registerTrustTools(server, deps) {
|
|
|
124
124
|
};
|
|
125
125
|
});
|
|
126
126
|
server.registerTool('trust_ring_prove', {
|
|
127
|
-
description: 'Create a ring signature proving anonymous membership in
|
|
127
|
+
description: 'Create a ring signature proving anonymous group membership. A verifier can confirm "someone in this ring signed this" but cannot determine who. The active identity must be one of the pubkeys in the ring. Returns kind 30078 event with the signature.',
|
|
128
128
|
inputSchema: {
|
|
129
129
|
ring: z.array(hexId).describe('Hex x-only public keys of ring members (must include active identity)'),
|
|
130
130
|
attestationType: z.string().describe('Attestation type context for the canonical message'),
|
package/package.json
CHANGED