Personal draft DB (CLI)
Set up your own local nostr event DB. Drafts are real signed events with an ephemeral key that are ingested with the client flag (processEvent(json, { client: 1 }) — Notedeck's IngestMetadata::new().client(true)) and never sent to any relay. See docs/notedeck-usage.md (use-case 9) and packages/bunostrdb/src/drafts.ts.
All commands accept --db <path> (defaults to ./data). A missing directory is created for you — first run just works.
1. Draft a note
bun run cli -- draft-note --db ./data.drafts --content "my first local draft"Output is the stored event JSON plus its id. Re-run with --kind 30023 (or any kind) for longform/other kinds.
2. Draft a reaction to an event id
bun run cli -- draft-reaction --db ./data.drafts --target <64-char-hex-event-id>
# custom emoji / content:
bun run cli -- draft-reaction --db ./data.drafts --target <hex> --content "🤙"This builds a kind-7 event with an #e tag pointing at the target — stored locally only.
3. Draft a profile (kind 0)
bun run cli -- draft-profile --db ./data.drafts --name "alice" --about "local drafts only"4. Query it back
Existing commands work unchanged against the same --db:
# kind-1 notes, latest 10
bun run cli -- query --db ./data.drafts --filter '{"kinds":[1],"limit":10}' --limit 10
# the reaction you just drafted
bun run cli -- query --db ./data.drafts --filter '{"kinds":[7]}' --limit 10
# fetch one note by id
bun run cli -- get-note --db ./data.drafts --id <hex>5. Full-text search for anything
bun run cli -- search --db ./data.drafts --query "local draft" --limit 20Ranked standalone search (BunNdb.textSearch(), limit capped at 128). For filter-scoped search, use FilterBuilder.search() + query() instead.
Notes
- Ingestion is asynchronous: the CLI waits with
waitForNoteById()(default 10s, override with--timeout <ms>) before reporting success — it never reports "stored" from queue acceptance alone. - Draft identity: each draft mints a fresh ephemeral secret by default. To keep one identity across drafts, use the library (
createDraftEvent({ secret })) instead of the CLI. - Programmatic use:
// @ts-nocheck
import { BunNdb } from "bunostrdb";
import { buildDraftNote, ingestDraft, searchDrafts } from "bunostrdb";
{
using ndb = new BunNdb("./data.drafts");
const draft = buildDraftNote("hello local world");
const id = await ingestDraft(ndb, draft.eventJson);
console.log("stored draft", id);
console.log(searchDrafts(ndb, "hello"));
}Run from the repo root (after
bun install, which links thebunostrdbworkspace). Against an installedbunostrdbpackage, the same"bunostrdb"import works unchanged.
