nt — Nostr Terminal (C99)
A fast, no-nonsense terminal client for Nostr, written in C99.
This is a from-scratch port of the original Node.js nt (NostrTerminal_5), built on top of nostr_core_lib for protocol, crypto, and NIP support.
Philosophy
Fast in, fast out. nt is designed to feel like a CLI utility, not a chat app.
There is no persistent relay pool. Every action follows the same pattern:
- Connect to the relays needed for the operation
- Do the thing (publish an event, fetch a profile, query notes…)
- Disconnect
This keeps the program lightweight, predictable, and easy to reason about:
- No background threads babysitting sockets
- No reconnection storms
- No hidden state between commands
- Memory and FDs return to zero between operations
- Trivial to script, embed in pipelines, or run on constrained hardware
When you want streaming behavior (e.g. a live feed), you explicitly enter that mode and explicitly leave it — at which point the sockets close.
Goals
- Fast startup, fast shutdown. Sub-second from launch to first prompt.
- Tiny footprint. Single static binary, minimal dependencies.
- Predictable. One screen, one job. Connect → act → disconnect.
- Hackable. C99, well-organized source, easy to fork.
- Self-contained. Local SQLite cache; no daemon, no server.
Non-Goals
- Maintaining long-lived relay connections in the background
- Acting as a relay yourself (the original Node version had a stub WSS — dropped here)
- Being a full-featured GUI client
- Push notifications
Features (planned)
See planning.md for the full breakdown by priority.
Core (P0)
- Login via seed phrase, nsec, npub, or NIP-46 bunker
- Profile view/edit (KIND 0)
- Relay management (KIND 10002)
- Quick tweet (KIND 1)
- Follows list (KIND 3)
Reading & Writing (P1)
- Live feeds (follows, mentions, notifications, firehose) — explicit subscribe mode
- Long-form posts (KIND 30023 / 30024) with
vipeeditor integration - Encrypted DMs (NIP-17 sealed, NIP-04 legacy)
- Notifications digest
Extras (P2)
- Encrypted todo list
- Daily diary
- Cashu eCash wallet (NIP-60 / NIP-61)
- AI prompts (Venice.ai / local Ollama)
Experimental (P3)
- Circus mode (AI persona swarm)
- Blossom media server management
- Bulk database maintenance
Architecture
┌─────────────────────────────────────────────┐
│ nt (this project) │
│ ┌──────────┐ ┌─────────┐ ┌──────────────┐ │
│ │ TUI │ │ Menus │ │ SQLite Cache│ │
│ │ (ncurses)│ │ (C99) │ │ (~/.nostr) │ │
│ └──────────┘ └─────────┘ └──────────────┘ │
│ │ │ │ │
│ └───────────┼────────────┘ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ Connect → Act → Close │ │
│ └────────────────────────┘ │
│ │ │
└─────────────────────┼────────────────────────┘
▼
┌─────────────────────────┐
│ nostr_core_lib │
│ (NIPs, crypto, pool, │
│ websocket, cashu, │
│ blossom, http) │
└─────────────────────────┘
│
▼
┌──────────────┐
│ Nostr Relays│
│ (transient) │
└──────────────┘
Local SQLite at ~/.nostr/nostr.db is the only persistent state between invocations. It caches:
- Events (regular / replaceable / addressable / ephemeral)
- Relay metadata (NIP-11 info, RTT, kind-1 acceptance tests)
- People (cached pubkeys, names)
- Publish history (
relay_posts) - Local key/value state
Dependencies
Build:
- C99 compiler (gcc / clang)
- CMake ≥ 3.10
Libraries (system):
ncurses— terminal UIsqlite3— local cachelibcurl— HTTP (NIP-11, AI APIs, nostr.watch)openssl— TLS for WebSockets
Libraries (vendored in resources/nostr_core_lib):
nostr_core_lib— Nostr protocol, NIPs, crypto, relay pool, websocketcJSON— JSON parsing
External tools (optional, runtime):
vipe(frommoreutils) — for editor-based note compositionbrave-browser— for the optional web UI launcher
Building
git clone <this-repo>
cd nostr_terminal
mkdir -p build && cd build
cmake ..
make
./nt
(Build instructions are tentative — to be finalized once the implementation lands.)
Project Layout
nostr_terminal/
├── README.md ← you are here
├── planning.md ← detailed feature/menu breakdown
├── CMakeLists.txt ← top-level build
├── src/ ← nt source code (C99)
├── include/ ← nt public headers
├── tests/ ← unit & integration tests
└── resources/
├── nostr_core_lib/ ← vendored protocol library
└── NostrTerminal_5/ ← reference Node.js implementation
Status
🚧 Early planning / scaffolding. See planning.md for the implementation roadmap and per-menu status.
License
TBD