Fill all 31 stub pages scaffolded in Phase 1 with content migrated and verified from the root docs, crate READMEs, and source code: - getting-started/ (3): installation, quickstart, local relay (TESTING.md) - architecture/ (8): ARCHITECTURE.md §1–§8, one page per section - guides/ (9): development, testing, agents, workflows, self-hosting, nostr-clients (operational half of NOSTR.md), adding-event-kinds, adding-api-endpoints, releasing - reference/ (5): CLI reference verified against buzz --help and crates/buzz-cli/src (18 groups / 87 subcommands; README drift noted), configuration, known-limitations (ARCHITECTURE §9 + conformance LIMITS.md + doc-debt list), NIPs index (13, NIP-CW canonical), design-docs index - vision/ (6): VISION.md + 5 VISION_*.md migrated with aspirational banners and rewritten links Root originals (ARCHITECTURE, NOSTR, TESTING, RELEASING, VISION*) get pointer notes marking docs/ as canonical; deletion is a follow-up. All relative links in the new tree verified to resolve. Known limitations are documented honestly, never papered over: rate limiting unenforced, WF-07/WF-08 workflow stubs, buzz-cli README drift, one-line GOVERNANCE.md. Note: pre-commit sadscan findings reviewed as false positives (dev-default postgres URI and NIP-OA test vectors, both already on origin/main). Co-authored-by: npub1pejagjwzjh7y36gq97hxf62ry75u3s6c6grr0rumx2p4c5qsms9s7jdtgl <0e65d449c295fc48e9002fae64e94327a9c8c358d206378f9b32835c5010dc0b@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub1pejagjwzjh7y36gq97hxf62ry75u3s6c6grr0rumx2p4c5qsms9s7jdtgl <0e65d449c295fc48e9002fae64e94327a9c8c358d206378f9b32835c5010dc0b@sprout-oss.stage.blox.sqprod.co>
7.1 KiB
Development Guide
Setting up a dev environment, code style, and the PR workflow. The root
CONTRIBUTING.md is the canonical contributor entry
point (code of conduct, CLA); this page is the day-to-day engineering detail.
Environment setup
Prerequisites
| Tool | Version | Notes |
|---|---|---|
| Rust | 1.88+ | Install via rustup |
| Node.js | 24+ | Required for desktop app commands and just ci |
| pnpm | 10+ | Required for desktop app commands and just ci |
| Flutter | 3.41+ | Required for mobile app — install via flutter.dev |
| Docker | 24+ | For Postgres, Redis, MinIO |
just |
latest | Task runner — cargo install just |
lefthook |
latest | Optional; run lefthook install for local Git hooks |
sqlx migrations |
workspace crate | just migrate applies embedded migrations from migrations/ |
This repo uses Hermit for toolchain pinning. Activate it once per shell session:
. ./bin/activate-hermit
Hermit pins Rust, just, Node, pnpm, and other tools to the versions in
bin/. Each tool is downloaded on first use. You can also run just bootstrap
(which just setup calls automatically) to pre-download all required tools
upfront. If you don't use Hermit, ensure your toolchain meets the minimum
versions in the table above.
First-Time Setup
# 1. Clone the repo
git clone https://github.com/block/buzz.git
cd buzz
# 2. Activate Hermit (optional but recommended)
. ./bin/activate-hermit
# 3. Bootstrap tools + infrastructure
just setup
# 4. Install Git hooks (optional, recommended)
just hooks
just setup runs just bootstrap first — it copies .env.example to .env
if it doesn't already exist, and invokes cargo, node, and pnpm to trigger
Hermit's lazy tool download (each tool is fetched once on first invocation and
cached thereafter). You can also run just bootstrap independently at any time;
it is safe to re-run.
just setup then starts Docker services (Postgres on :5432, Redis on :6379,
Adminer on :8082, Keycloak on :8180 for local OAuth/OIDC testing, MinIO on
:9000 for media storage, and Prometheus on :9090 for metrics) and runs all
pending database migrations.
Running the Relay and Desktop App
just dev # starts the relay + desktop app in one command
just dev builds all agent tools, starts the relay (ws://localhost:3000) in
the background, and launches the Tauri desktop app. The relay process is
automatically killed when you quit the app or press Ctrl+C.
For a split-terminal workflow (relay logs visible separately from Vite output):
just relay # terminal 1 — relay on ws://localhost:3000
just desktop-dev # terminal 2 — Vite dev server only (no Tauri shell)
Stopping / Resetting
just down # Stop Docker services, keep data
just reset # ⚠️ Wipe all data and recreate the environment
Repo layout
A Rust workspace of focused crates (see the
Crate Reference), plus desktop/ (Tauri + React),
web/, mobile/ (Flutter), deploy/ (Compose bundle + Helm chart),
migrations/, and examples/. Task automation lives in the
Justfile; Git hooks in lefthook.yml;
TS lint/format in biome.json.
Code style
Formatting
We use rustfmt with default settings. Format your code before committing:
cargo fmt --all
To check without modifying:
cargo fmt --all -- --check
Linting
We use clippy with warnings-as-errors:
cargo clippy --all-targets --all-features -- -D warnings
Fix all clippy warnings before submitting a PR. If you believe a warning is
a false positive, add a targeted #[allow(...)] with a comment explaining
why.
No Unsafe Code
All crates enforce #![deny(unsafe_code)]. Do not add unsafe blocks. If you
believe unsafe is genuinely necessary, open an issue first to discuss the
approach.
Error Handling
- Use
thiserrorfor library error types. - Use
anyhowfor binary / application-level error propagation. - Do not use
unwrap()orexpect()in production code paths. Use?or explicit error handling.unwrap()is acceptable in tests.
Logging and Tracing
Use the tracing crate for all instrumentation. Prefer structured fields
over string interpolation:
// Good
tracing::info!(channel_id = %id, event_kind = kind, "Event ingested");
// Avoid
tracing::info!("Event ingested: channel={id} kind={kind}");
Commit Messages
Follow Conventional Commits:
feat(mcp): add get_feed_actions tool
fix(auth): reject expired NIP-42 challenges
docs(agents): document workflow MCP tools
refactor(db): extract channel queries into channel.rs
test(workflow): add approval gate integration test
The type prefix (feat, fix, docs, refactor, test, chore) is
required. The scope (in parentheses) is optional but encouraged.
Making a pull request
Before You Start
- Check open issues and PRs to avoid duplicate work.
- For significant changes, open an issue first to discuss the approach.
- For small fixes (typos, doc improvements, obvious bugs), go ahead and open a PR directly.
What a Good PR Looks Like
-
Focused — one logical change per PR. If you're fixing a bug and refactoring a module, split them into two PRs.
-
Tested — new behavior has tests. Bug fixes include a regression test. If a test is impractical, explain why in the PR description.
-
Documented — public APIs, new event kinds, new MCP tools, and new config variables are documented. Update
README.md,AGENTS.md, orVISION.mdas appropriate. -
CI passing —
just cipasses locally before you push. -
Clear description — the PR description explains:
- What problem this solves (or what feature it adds)
- How it was implemented (key decisions, trade-offs)
- How to test it manually (if applicable)
- Any follow-up work deferred to a future PR
PR Checklist
- [ ] `just ci` passes (fmt + clippy + unit tests + mobile)
- [ ] Integration tests pass (`just test`)
- [ ] New public APIs / tools / endpoints are documented
- [ ] No new `unwrap()` in production code paths
- [ ] No new `unsafe` blocks
Review Process
- A maintainer will review your PR within a few business days.
- Address review comments by pushing new commits (don't force-push during review; it makes it hard to see what changed).
- Once approved, a maintainer will squash-merge your PR.
License and CLA
Buzz is licensed under the Apache License, Version 2.0. See LICENSE for the full text.
By submitting a pull request, you agree that your contribution is licensed under the Apache 2.0 license and that you have the right to submit it.
If your employer has rights to intellectual property you create, you may need their sign-off. When in doubt, check with your legal team.
Thank you for contributing to Buzz. Every bug report, documentation fix, and code contribution makes the project better for everyone. 🐝