Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,24 @@ coding agents at the conventions, build system, and structure used here.
`nostr` is a [Nostr](https://nostr.com) protocol library for Zig: keys and
encoding, event construction and signing, relay transport, encrypted
messaging, and a local-first event store. It has no runtime dependency on
any specific application — it is consumed as a library by other repos in
any specific application: it is consumed as a library by other repos in
the `zig-nostr` org (a signer, a DM client, a read-only client).

## Repository layout

```
src/
root.zig — public module entry point (@import("nostr"))
build.zig — build graph: module + test step
build.zig.zon — package manifest, dependencies
.zigversion — pinned Zig compiler version
root.zig # public module entry point (@import("nostr"))
keys.zig # secp256k1 keys and BIP-340 signatures
event.zig # the NIP-01 event model and canonical serialization
relay.zig # the live dialer and the relay connection
websocket.zig # RFC 6455 framing, hand-written
store.zig # the local-first LMDB event store
liveness.zig # when a relay connection has gone quiet
... # one file per NIP, plus filter/message/json/hex/bech32
build.zig # build graph: module + test step
build.zig.zon # package manifest, dependencies
.zigversion # pinned Zig compiler version
```

As modules are added (keys, encoding, events, transport, store, crypto),
Expand All @@ -39,14 +46,17 @@ Use the Zig version pinned in `.zigversion`. CI runs on Linux and macOS.

Current:

- `bitcoin-core/secp256k1` — BIP-340 Schnorr signing/verification. Compiled
- `bitcoin-core/secp256k1`: BIP-340 Schnorr signing/verification. Compiled
from source and exposed to Zig via translate-c in `build.zig`; wrapped by
`src/keys.zig`. Pinned by exact commit in `build.zig.zon`.

Planned, added as each milestone needs them:
- `LMDB/lmdb`: the local event store's backing. Compiled from source and
pinned the same way.
- `atman/zg`: Unicode normalization, for NIP-49 passphrases.

- `karlseguin/websocket.zig` — relay transport.
- `allyourcodebase/lmdb` — local event store backing.
The websocket transport is not a dependency. `src/websocket.zig` implements
RFC 6455 framing directly, because the relay connection needs control over when
a frame surfaces and no client library exposed that.

Dependencies are pinned in `build.zig.zon`; never vendor or hand-roll crypto
primitives that have an audited upstream implementation.
Expand All @@ -61,13 +71,13 @@ primitives that have an audited upstream implementation.
- Never push directly to `main`; all changes land via reviewed PRs from
short-lived branches.
- Update `CHANGELOG.md` (Unreleased section) and `CURRENT_STATE.md` inside
the same PR that introduces the change — not as a follow-up.
the same PR that introduces the change, not as a follow-up.

## Code style

- `zig fmt` is the formatter; CI fails on unformatted code.
- Prefer explicit error sets over `anyerror`.
- No hand-rolled cryptography for signing/verification — bind to audited
- No hand-rolled cryptography for signing/verification: bind to audited
upstream implementations (see Dependency graph).
- Validate all externally-sourced data (relay messages, parsed events) at
the boundary; don't assume well-formed input.
Expand All @@ -81,9 +91,9 @@ must pass its official test vectors, before either ships.

## Orientation

- [`CURRENT_STATE.md`](CURRENT_STATE.md) — what's built, in progress, and
- [`CURRENT_STATE.md`](CURRENT_STATE.md): what's built, in progress, and
next, updated on every merge.
- [`CONTRIBUTING.md`](CONTRIBUTING.md) — full contribution workflow.
- [`CONTRIBUTING.md`](CONTRIBUTING.md): full contribution workflow.
- [GitHub milestones](https://github.com/zig-nostr/nostr/milestones) and the
[org project board](https://github.com/orgs/zig-nostr/projects) — the
[org project board](https://github.com/orgs/zig-nostr/projects): the
full roadmap.
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ workflow used for all changes to this repository.
## Workflow

1. **Open or claim an issue** describing the change, with acceptance
criteria. Every PR links back to an issue — even small fixes.
criteria. Every PR links back to an issue, even small fixes.
2. **Branch from `main`**, named after the change
(`feat/nip19-encoding`, `fix/event-id-hash`, `chore/ci-macos`).
3. **Implement** the change with tests. Update `CHANGELOG.md` (Unreleased
Expand Down Expand Up @@ -53,5 +53,5 @@ for what's built so far and what's next.

## Security

Do not open public issues for security vulnerabilities — see
Do not open public issues for security vulnerabilities; see
[`SECURITY.md`](SECURITY.md).
35 changes: 22 additions & 13 deletions CURRENT_STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ A snapshot for somebody reading this repo. The
[milestones](https://github.com/zig-nostr/plaza/milestones) are the tracker; this
file only says where things stand today.

Version numbers are deliberately not repeated here. This file went nine releases
out of date saying them, and a stale number is worse than no number: it is
readable, specific and wrong. Each project's own releases page is the answer.

## The library

`v0.5.0`. Shipped and covered by tests:
[Latest release](https://github.com/zig-nostr/nostr/releases). Shipped and
covered by tests:

- **Core**: secp256k1 keys, BIP-340 Schnorr signatures against the official
vectors, the NIP-01 event model, NIP-19/21 encoding, NIP-06 derivation, NIP-49
encrypted keys.
- **Transport**: RFC 6455 WebSocket, a relay connection state machine, a live
TCP/TLS dialer, NIP-42 authentication, and the NIP-65 outbox model with no
hardcoded relays.
hardcoded relays. A read can carry a deadline, so a thread serving a quiet
relay can still notice that its pool changed.
- **Store**: a memory-mapped LMDB event store with a bounded, newest-first query
planner. A 500-note feed query is 0.28 ms at 100,000 stored events, and a
profile read is 8 microseconds.
Expand All @@ -27,22 +33,25 @@ on the roadmap while groups, messages, media and payments are still landing.

## The apps

- **[Notary](https://github.com/zig-nostr/notary)** `v0.3.0`: a native macOS
NIP-46 signer. Your key lives in a local daemon, nothing signs without your
approval, and the `nsec` never enters a client.
- **[Plaza](https://github.com/zig-nostr/plaza)** `v0.2.0`: the flagship client.
Read without an account, post in four clicks, with the feed rendered from
disk. Reads
every account you follow, with no cap on how far you can scroll.
- **[Notary](https://github.com/zig-nostr/notary)**: a native NIP-46 signer.
Your key lives in a local daemon, nothing signs without your approval, and the
`nsec` never enters a client.
- **[Plaza](https://github.com/zig-nostr/plaza)**: the flagship client. Read
without an account, post in four clicks, with the feed rendered from disk.
Reads every account you follow, with no cap on how far you can scroll.

Both are downloadable. What comes next lands inside them rather than as new apps.
Both are downloadable for macOS (Apple Silicon) and Linux (x86_64 and aarch64).
Off macOS there is no platform text layer, so both draw every glyph from faces
they carry: emoji are drawn in colour, and scripts those faces do not cover are
not drawn at all. What comes next lands inside these two rather than as new apps.

## What is next

The ten milestones, in order, are on the
[roadmap](https://zignostr.com/roadmap). The first is notifications: who acted,
what they did, and the note it was about, which the current one-line row does not
say.
[roadmap](https://zignostr.com/roadmap). The first is everything you do on the
first day: the four things already built that do not work (reposts by people you
follow, relay hints, hashtags, bookmarks), then pictures, a full profile, zaps
you can send, and search.

That page also lists what is deliberately **not** being built, and why. Reading
the second half is the faster way to understand the first.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Methodology and the full write-up are on the
Add the library to your `build.zig.zon`:

```sh
zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.12.0.tar.gz
zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.14.1.tar.gz
```

Wire the module in `build.zig`:
Expand Down Expand Up @@ -169,12 +169,13 @@ do.
The library is proven by native apps built on it, the ecosystem forming around
one core:

- **[Notary](https://github.com/zig-nostr/notary)**: *shipped.* A native macOS
remote signer (NIP-46 bunker): your key lives in a local daemon, every signing
- **[Notary](https://github.com/zig-nostr/notary)**: *shipped.* A native remote
signer (NIP-46 bunker): your key lives in a local daemon, every signing
request waits for your approval, and the `nsec` never enters a client.
Downloadable for macOS (Apple Silicon) and Linux (x86_64 and aarch64).
- **[Plaza](https://github.com/zig-nostr/plaza)**: *shipped.* The flagship: a
fast, local-first client where you read without an account, post in four
clicks, and the feed renders from disk. A downloadable macOS app.
clicks, and the feed renders from disk. Downloadable for the same two.

Private messages, zaps and groups land inside Plaza rather than as separate apps.
A messenger you have to switch to is one you stop using.
Expand Down
Loading