2026-05-09 09:53:33 -04:00
2026-05-09 09:53:33 -04:00

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:

  1. Connect to the relays needed for the operation
  2. Do the thing (publish an event, fetch a profile, query notes…)
  3. 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 vipe editor 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 host:

  • Docker (required)

Runtime Dependencies

nt is built as a fully static binary. Host runtime package dependencies are not required.

TUI runtime note: nt uses the ncurses alternate screen buffer with a footer-log status line for latest action results; use the View log main menu entry to open the full scrollable action history.

TUI Features

  • Arrow-key navigation + shortcut keys in all menus
  • Scrollable tables with PgUp/PgDn
  • Footer status bar showing latest action result
  • View log menu entry to scroll through full action history
  • Full-screen pager for long content (event JSON, blog posts, relay info)
  • Modal dialogs for errors and confirmations

Libraries (vendored in resources/nostr_core_lib):

  • nostr_core_lib — Nostr protocol, NIPs, crypto, relay pool, websocket
  • cJSON — JSON parsing

External tools (optional, runtime):

  • vipe (from moreutils) — for editor-based note composition
  • brave-browser — for the optional web UI launcher

Building

git clone <this-repo>
cd nostr_terminal
./build.sh
./nt

This project is static-only. The only supported build path is build.sh, which builds inside Docker (Alpine/musl), verifies static linkage, and emits a single binary at ./nt.


Project Layout

nostr_terminal/
├── README.md             ← you are here
├── planning.md           ← detailed feature/menu breakdown
├── build.sh              ← only supported build entrypoint (static-only)
├── 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

Description
A fast, no-nonsense terminal client for Nostr, written in C99.
Readme 1.1 MiB
v0.0.9 Latest
2026-05-04 00:34:38 +00:00
Languages
C 95.7%
Shell 4.2%