diff --git a/CLAUDE.md b/CLAUDE.md
index 5f25a70..bef8c76 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1,8 +1,14 @@
# CLAUDE.md — Vibed Mono-Repo
+
+**Always run commands from the root of the project you are working on** — not from the repository root. Each project is self-contained and its commands (`cargo`, `mdbook`, `trunk`, `tofu`, etc.) must be run from within that project's directory.
+
+
+
+
## Repository Structure
-This is a mono-repo of self-contained HTTP web services. Each service lives in its own top-level folder and is an independent Rust crate (no Cargo workspace). There is no cross-service communication — each service is a standalone application.
+This is a mono-repo of independent projects. Each project lives in its own top-level folder. Projects may be Rust HTTP services, CLI tools, static sites, frontends, or anything else — there is no single template. Projects do not communicate with each other.
```
vibed/
@@ -10,37 +16,57 @@ vibed/
├── README.md # repo-wide overview with descriptions of each project
├── LICENSE-APACHE
├── LICENSE-MIT
-├── flake.nix # base Nix flake — all services inherit or extend this
+├── flake.nix # base Nix flake — projects may inherit or extend this
├── flake.lock
├── common/ # shared library crate (types, utilities, etc.)
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
-├── /
-│ ├── Cargo.toml
-│ ├── src/
-│ │ ├── main.rs
-│ │ └── tests.rs # unit tests module
-│ ├── tests/ # integration tests
+├── /
+│ ├── CLAUDE.md # project-specific instructions (starts with @../CLAUDE.md)
│ ├── docs/
│ │ ├── PLANNING.md # development phases and work logs
│ │ └── ARCHITECTURE.md # component overview and interactions
-│ ├── infra/ # OpenTofu infrastructure
-│ │ └── main.tf
-│ ├── flake.nix # service-specific flake (inherits base)
-│ └── README.md # what, how, run, test, license, disclaimer
+│ ├── README.md # what, how, run, test, license, disclaimer
+│ └── ... # project-specific files
└── ...
```
-## Tech Stack
+
+
+
+
+## Project CLAUDE.md Inheritance
+
+Each project-level `CLAUDE.md` should begin with:
+
+```
+@../CLAUDE.md
+```
+
+This imports the root conventions (validation, git, code style, license, task tracking) so they don't need to be duplicated. Project files should only contain project-specific overrides or additions.
+
+
+
+
+
+## Common Patterns
+
+These are defaults that apply **when relevant** — not every project uses all of them. Rust CLI tools don't need Axum; static sites don't need SQLx. Apply the patterns that fit the project.
+
+
### Language & Tooling
-- **Language:** Rust (all software)
+- **Language:** Rust (preferred; exceptions are documented per-project)
- **Local development:** Nix with Nix Flakes for dependency management
-- **Infrastructure:** OpenTofu with the Cloudflare provider (stored in each service's `infra/` subfolder)
+- **Infrastructure:** OpenTofu with the Cloudflare provider (stored in each project's `infra/` subfolder)
- **Formatting:** Default `rustfmt` conventions (no custom `rustfmt.toml`)
+
+
+
+
### Backend
- **Framework:** Tower + Axum
@@ -50,6 +76,10 @@ vibed/
- **API format:** JSON-encoded request and response payloads
- **API spec:** Each backend service must have an auto-generated OpenAPI spec. _TODO: choose tooling crate._
+
+
+
+
### Frontend
- **Framework:** Yew (Rust compiled to Wasm)
@@ -57,24 +87,32 @@ vibed/
- **Compile target:** `wasm32-unknown-unknown` (included in the Nix dev shell via rust-overlay)
- **Hosting:** Cloudflare Pages
+
+
+
+
+### Infrastructure
+
+- **Provider:** OpenTofu with the Cloudflare provider
+- **Location:** `infra/` subfolder in each project
+
+
+
+
+
### Data
- **Production database:** Cloudflare D1 (SQLite-compatible)
- **Local database:** Turso (file-backed SQLite)
- **Query layer:** SQLx
-## Shared Code
-
-The `common/` crate is a shared library for types, utilities, and definitions reused across services. Individual services depend on it via a path dependency in their `Cargo.toml`:
+
-```toml
-[dependencies]
-common = { path = "../common" }
-```
+
-## Chosen Crates
+### Chosen Crates
-When a crate is chosen to solve a problem, it becomes the standard for that purpose across all services. Add new entries here as decisions are made.
+When a crate is chosen to solve a problem, it becomes the standard for that purpose across all projects. Add new entries here as decisions are made.
| Purpose | Crate | Notes |
|---|---|---|
@@ -82,25 +120,44 @@ When a crate is chosen to solve a problem, it becomes the standard for that purp
_This table is intentionally empty. Populate it as crate decisions are made during development._
+
+
+
+
+
+
## Secrets & Configuration
- **Local:** `.env` files for local secrets. **Never commit `.env` files to the repository.**
- **Production:** Wrangler secrets (`wrangler secret put `).
-- Add `.env` to `.gitignore` at both the repo root and service level.
+- Add `.env` to `.gitignore` at both the repo root and project level.
+
+
-## Running Services Locally
+
+
+## Running Projects Locally
+
+Commands vary by project type. Run all commands from within the project directory.
```sh
-# Backend service (from the service directory)
+# Rust backend
cargo run
-# Frontend service (from the service directory)
+# Rust frontend
trunk serve
+
+# Static site (mdBook)
+mdbook serve
```
+
+
+
+
## Validation
-Run these commands **in order** from the service directory before committing changes:
+Run these commands **in order** from the **project directory** before committing changes:
```sh
cargo fmt # 1. consistent formatting
@@ -109,6 +166,12 @@ cargo clippy # 3. code follows best practices
cargo test # 4. code is logically valid
```
+Projects that are not Rust crates have their own validation steps documented in their `CLAUDE.md`.
+
+
+
+
+
## Git Conventions
This repository follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary).
@@ -125,7 +188,11 @@ Commit messages must use the format:
Common types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `ci`, `build`.
-Use the service name as the scope when the change is scoped to a single service (e.g., `feat(my-service): add user endpoint`).
+Use the project name as the scope when the change is scoped to a single project (e.g., `feat(my-project): add user endpoint`).
+
+
+
+
## License
@@ -134,24 +201,30 @@ All code in this repository is dual-licensed under:
- [Apache License, Version 2.0](LICENSE-APACHE)
- [MIT License](LICENSE-MIT)
-This follows standard Rust ecosystem convention. Each service README should reference this dual license.
+This follows standard Rust ecosystem convention. Each project README should reference this dual license.
+
+
+
+
## Code Style & Documentation
+
+
### Rust
- All public functions, structs, enums, and modules must have rustdoc comments describing how they work.
- Include doc-examples where applicable — these double as doctests.
- Unit tests live in a `tests` module (`tests.rs` file) within the crate's root module or relevant submodules.
-- Each service has a `tests/` directory for integration-style tests.
+- Each project has a `tests/` directory for integration-style tests.
-### Infrastructure
+
-- Every OpenTofu `resource` and `data` block must have a comment explaining its purpose.
+
### Release Builds
-Release builds must be compiled with settings to minimize binary size. Add this to each service's `Cargo.toml`:
+Release builds must be compiled with settings to minimize binary size. Add this to each project's `Cargo.toml`:
```toml
[profile.release]
@@ -161,21 +234,39 @@ strip = true
codegen-units = 1
```
+
+
+
+
+### Infrastructure
+
+- Every OpenTofu `resource` and `data` block must have a comment explaining its purpose.
+
+
+
+
+
+
+
## Testing
### Structure
- **Unit tests:** `src/tests.rs` module (or submodule-local `tests` modules)
-- **Integration tests:** `tests/` directory at the service root
+- **Integration tests:** `tests/` directory at the project root
### Coverage
- Target 80%+ code coverage; higher is better.
- _TODO: determine coverage tooling (e.g., `cargo-tarpaulin`, `cargo-llvm-cov`)._
+
+
+
+
## Project Documentation
-Each service must maintain the following:
+Each project must maintain the following:
### README.md
@@ -198,26 +289,35 @@ Covers:
- Component overview
- How components interact
-### Task Tracking
+
-Tasks are tracked with **Beads**. The markdown docs (PLANNING, ARCHITECTURE) are for human-readable documentation only — not task management.
+
## Repo-Wide Files
| File | Purpose |
|---|---|
| `CLAUDE.md` | This file — conventions and instructions for Claude Code |
-| `README.md` | Repo overview with a description of each service |
+| `README.md` | Repo overview with a description of each project |
| `LICENSE-APACHE` | Apache 2.0 license text |
| `LICENSE-MIT` | MIT license text |
-| `flake.nix` | Base Nix flake — all service flakes inherit or extend this |
-| `common/` | Shared library crate for cross-service types and utilities |
+| `flake.nix` | Base Nix flake — projects may inherit or extend this |
+| `common/` | Shared library crate for cross-project types and utilities |
+
+
+
+
## Nix
- All local development uses Nix.
- Dependencies are managed with Nix Flakes.
-- The repo root has a base `flake.nix` that services should either use directly or inherit and extend with their own `flake.nix`.
+- The repo root has a base `flake.nix` that projects should either use directly or inherit and extend with their own `flake.nix`.
+
+
+
+
+
## Task Tracking with nbd
`nbd` is a CLI tool for managing work tickets, designed for agent workflows.
@@ -272,3 +372,5 @@ nbd next --json
- `--type` choices: `project`, `feature`, `task`, `bug`.
- Use `--deps id1,id2` to express blockers — tickets that must be done first.
- Create tickets *before* starting non-trivial tasks, not after.
+
+
diff --git a/edu/CLAUDE.md b/edu/CLAUDE.md
index 4a25882..8165289 100644
--- a/edu/CLAUDE.md
+++ b/edu/CLAUDE.md
@@ -1,11 +1,21 @@
-# CLAUDE.md
+@../CLAUDE.md
-This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+# CLAUDE.md — edu
+
+
+All commands in this file are run from the `edu/` directory.
+
+
+
## What This Project Is
`edu` is an [mdbook](https://rust-lang.github.io/mdBook/)-based static site called **Vibed Learning** — a collection of self-guided courses and technical references. There is no Rust code here; all content is Markdown. The generated `book/` directory is gitignored.
+
+
+
+
## Commands
```sh
@@ -20,6 +30,10 @@ nix develop
# or automatically via direnv: cd into the directory
```
+
+
+
+
## Content Structure
- `src/SUMMARY.md` — mdbook table of contents; controls site navigation. **Every new page must be listed here.**
@@ -28,67 +42,16 @@ nix develop
To add a new page: create `src/.md`, then add it to `src/SUMMARY.md` under the appropriate section heading.
-## Task Tracking with nbd
-
-`nbd` is a CLI tool for managing work tickets, designed for agent workflows.
+
-### Initialisation
-
-```sh
-nbd init
-```
-
-Run once in the project root. Creates `.nbd/tickets/`. Safe to run multiple times.
-
-### Core commands
-
-```sh
-# Create a new ticket (use --ftype md for a human-readable body)
-nbd create --title "Add OAuth login" --type feature --priority 7 --ftype md --json
-
-# List all open tickets (sorted by priority)
-nbd list --json
-
-# Read a specific ticket
-nbd read --json
-
-# Update a ticket
-nbd update --status in_progress --json
-nbd update --status done --json
-```
-
-### Finding what to work on
-
-```sh
-# All tickets that are unblocked and ready to start
-nbd ready --json
-
-# The single highest-priority unblocked ticket
-nbd next --json
-```
-
-### Workflow
-
-1. **Before starting** — create a ticket: `nbd create --title "..." --ftype md --json`
-2. **When starting** — mark it in progress: `nbd update --status in_progress --json`
-3. **When done** — mark it complete: `nbd update --status done --json`
-
-### Guidelines
-
-- **Always pass `--json`** to every command for structured, unambiguous output.
-- **Always pass `--ftype md`** when creating tickets — markdown format keeps the body human-readable.
-- Use `jq` to parse and transform JSON output when needed.
-- Priority scale 0–10: use **7–9** for bugs, **5** for normal tasks, **3** for nice-to-haves.
-- `--type` choices: `project`, `feature`, `task`, `bug`.
-- Use `--deps id1,id2` to express blockers — tickets that must be done first.
-- Create tickets *before* starting non-trivial tasks, not after.
-
-Ticket IDs appear in commit messages in `[]` format.
+
## Conventions
-Inherits all Git and general conventions from the parent [`../CLAUDE.md`](../CLAUDE.md) (Conventional Commits, dual Apache-2.0/MIT license, Nix for dev, etc.).
-
Scope for commit messages: `edu` (e.g., `docs(edu): write §3 transition matrices`).
+Ticket IDs appear in commit messages in `[]` format.
+
Stub sections in content are marked with 🚧 and reference an nbd ticket — fill in content and close the ticket when complete.
+
+
diff --git a/nbd/CLAUDE.md b/nbd/CLAUDE.md
index de00b89..58c1d29 100644
--- a/nbd/CLAUDE.md
+++ b/nbd/CLAUDE.md
@@ -1,7 +1,19 @@
+@../CLAUDE.md
+
# CLAUDE.md — nbd
+
+All commands in this file are run from the `nbd/` directory.
+
+
+
+
`nbd` is a CLI tool for managing work tickets, primarily targeted at agent workflows. It is an independent Rust crate within the `vibed` mono-repo.
+
+
+
+
## Project Structure
```
@@ -24,6 +36,10 @@ nbd/
└── README.md
```
+
+
+
+
## Tech Stack
- **Language:** Rust (edition 2021)
@@ -32,6 +48,10 @@ nbd/
- **Serialization:** `serde` + `serde_json`
- **Test utilities:** `tempfile` (dev-dependency)
+
+
+
+
## Data Model
Tickets are stored as `.json` files in `.nbd/tickets/{id}.json`, where `id` is a 6-character hex string (e.g. `a3f9c2`). The `.nbd/` root is found by traversing up from cwd, like `git` finds `.git/`.
@@ -48,6 +68,10 @@ Ticket {
}
```
+
+
+
+
## CLI Interface
```sh
@@ -70,6 +94,10 @@ nbd graph [] [--filter KEY=VALUE ...] [--json]
`--json` is available on all commands for machine-readable output.
+
+
+
+
## Module Responsibilities
| Module | Responsibility |
@@ -82,6 +110,10 @@ nbd graph [] [--filter KEY=VALUE ...] [--json]
| `filter.rs` | glob-pattern ticket filtering |
| `tests.rs` | unit tests for all modules |
+
+
+
+
## Task Tracking with nbd
Use `nbd` to track tasks for work on this project. Since the binary is not
@@ -154,18 +186,9 @@ cargo run -- read --json
- `--priority` follows 0–10: use 7–9 for bugs, 5 for normal tasks, 3 for nice-to-haves.
- `--type` choices: `project`, `feature`, `task`, `bug`.
----
+
-## Validation
-
-Run in order from this directory before committing:
-
-```sh
-cargo fmt
-cargo check
-cargo clippy
-cargo test
-```
+
## Testing
@@ -174,32 +197,4 @@ cargo test
Target 80%+ code coverage.
-## Git Conventions
-
-Follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary). Use `nbd` as the scope:
-
-```
-feat(nbd): add list command
-fix(nbd): handle missing .nbd directory gracefully
-test(nbd): add roundtrip serialization test
-```
-
-## Code Style
-
-- All public functions, structs, enums, and modules must have rustdoc comments.
-- Include doc-examples where applicable — these double as doctests.
-- Default `rustfmt` conventions; no custom `rustfmt.toml`.
-
-## Release Builds
-
-```toml
-[profile.release]
-opt-level = "z"
-lto = true
-strip = true
-codegen-units = 1
-```
-
-## License
-
-Dual-licensed under Apache-2.0 and MIT, consistent with the rest of the `vibed` mono-repo.
+
diff --git a/quotesdb/CLAUDE.md b/quotesdb/CLAUDE.md
index 65343ba..c4503f5 100644
--- a/quotesdb/CLAUDE.md
+++ b/quotesdb/CLAUDE.md
@@ -1,8 +1,12 @@
+@../CLAUDE.md
+
# CLAUDE.md — quotesdb
-> Inherits all conventions from [@../CLAUDE.md](../CLAUDE.md). This file adds project-specific workflow, structure, and agent dispatch rules.
+
+Run all commands from the relevant sub-directory within `quotesdb/` (e.g., `api/`, `ui/`, `infra/`) — not from the repository root or the `quotesdb/` root.
+
----
+
## Project Overview
@@ -16,7 +20,9 @@
Design reference: `docs/plans/2026-02-27-quotesdb-design.md`
----
+
+
+
## Ticket Hierarchy
@@ -41,7 +47,9 @@ Rules:
- Each sub-project ticket must list the root project ticket (`ec118c`) as a dependency.
- **Only close a ticket after its work has been validated** (all `cargo fmt/check/clippy/test` pass, or equivalent for infra).
----
+
+
+
## Branch & Worktree Workflow
@@ -82,7 +90,9 @@ git merge quotesdb/api/
git worktree remove .claude/worktrees/quotesdb-api-
```
----
+
+
+
## Domain Expert Sub-Agents
@@ -102,10 +112,14 @@ Each sub-agent should receive:
3. The validation commands to run before closing the ticket
4. The conventional commit scope to use (e.g., `feat(quotesdb-api): ...`)
----
+
+
+
## Design Reference
+
+
### Database Schema
```sql
@@ -127,6 +141,10 @@ CREATE TABLE quote_tags (
);
```
+
+
+
+
### API Endpoints
| Method | Path | Description | Auth |
@@ -141,12 +159,20 @@ CREATE TABLE quote_tags (
> **Router order:** `GET /api/quotes/random` must be registered **before** `GET /api/quotes/:id`.
+
+
+
+
### Auth
- No user accounts. Each quote has an `auth_code` (4-word passphrase), stored plaintext.
- Provided via `X-Auth-Code` header for update/delete. On mismatch: `403 Forbidden`.
- Auth code is always returned in the create response.
+
+
+
+
### Frontend Routes (Yew)
| Route | Page |
@@ -157,39 +183,28 @@ CREATE TABLE quote_tags (
| `/author/:name` | All quotes by an author |
| `/submit` | New quote submission form |
----
+
+
+
+
+
## API Specification
The API spec lives at `api/openapi.yaml` (OpenAPI 3.1.0, YAML format).
- The spec is the source of truth for all endpoint contracts.
-- Validate with Redocly CLI after any changes:
+- Validate with Redocly CLI after any changes (from the `quotesdb/` directory):
```sh
redocly lint api/openapi.yaml
```
----
-
-## Validation
-
-Run in order from the relevant sub-directory before closing any ticket:
-
-```sh
-cargo fmt # 1. formatting
-cargo check # 2. syntax
-cargo clippy # 3. best practices
-cargo test # 4. correctness
-```
-
-For API spec changes:
-```sh
-redocly lint api/openapi.yaml
-```
+For infra changes, run from the `infra/` directory:
-For infra tickets:
```sh
tofu validate
tofu plan
```
+
+