docs: improve CLAUDE.md structure and clarity

- Add working-directory rule to root and all project docs
- Generalize root from "HTTP web services" to "independent projects"
- Add @../CLAUDE.md inheritance to nbd, edu, quotesdb project docs
- Remove sections duplicated from root in project-level docs
- Wrap all sections in semantic XML tags for clearer agent parsing
- Rename Tech Stack → Common Patterns (framed as defaults, not requirements)
- Rename Running Services Locally → Running Projects Locally
quotesdb
Elijah Voigt 3 months ago
parent c2c5fe923e
commit 7e0ba78240

@ -1,8 +1,14 @@
# CLAUDE.md — Vibed Mono-Repo
<working-directory-rule>
**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.
</working-directory-rule>
<repository-structure>
## 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
├── <service>/
│ ├── Cargo.toml
│ ├── src/
│ │ ├── main.rs
│ │ └── tests.rs # unit tests module
│ ├── tests/ # integration tests
├── <project>/
│ ├── 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
</repository-structure>
<inheritance>
## 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.
</inheritance>
<common-patterns>
## 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-and-tooling>
### 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`)
</language-and-tooling>
<backend-pattern>
### 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._
</backend-pattern>
<frontend-pattern>
### 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
</frontend-pattern>
<infrastructure-pattern>
### Infrastructure
- **Provider:** OpenTofu with the Cloudflare provider
- **Location:** `infra/` subfolder in each project
</infrastructure-pattern>
<data-pattern>
### 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`:
</data-pattern>
```toml
[dependencies]
common = { path = "../common" }
```
<chosen-crates>
## 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._
</chosen-crates>
</common-patterns>
<secrets-and-configuration>
## Secrets & Configuration
- **Local:** `.env` files for local secrets. **Never commit `.env` files to the repository.**
- **Production:** Wrangler secrets (`wrangler secret put <KEY>`).
- Add `.env` to `.gitignore` at both the repo root and service level.
- Add `.env` to `.gitignore` at both the repo root and project level.
</secrets-and-configuration>
## Running Services Locally
<running-projects>
## 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
```
</running-projects>
<validation>
## 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`.
</validation>
<git-conventions>
## 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`).
</git-conventions>
<license>
## 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.
</license>
<code-style>
## Code Style & Documentation
<rust-style>
### 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
</rust-style>
- Every OpenTofu `resource` and `data` block must have a comment explaining its purpose.
<release-builds>
### 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
```
</release-builds>
<infrastructure-style>
### Infrastructure
- Every OpenTofu `resource` and `data` block must have a comment explaining its purpose.
</infrastructure-style>
</code-style>
<testing>
## 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`)._
</testing>
<project-documentation>
## 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
</project-documentation>
Tasks are tracked with **Beads**. The markdown docs (PLANNING, ARCHITECTURE) are for human-readable documentation only — not task management.
<repo-wide-files>
## 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 |
</repo-wide-files>
<nix>
## 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`.
</nix>
<task-tracking>
## 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.
</task-tracking>

@ -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
<working-directory>
All commands in this file are run from the `edu/` directory.
</working-directory>
<project-overview>
## 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.
</project-overview>
<commands>
## Commands
```sh
@ -20,6 +30,10 @@ nix develop
# or automatically via direnv: cd into the directory
```
</commands>
<content-structure>
## 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/<name>.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.
</content-structure>
### 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 <id> --json
# Update a ticket
nbd update <id> --status in_progress --json
nbd update <id> --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 <id> --status in_progress --json`
3. **When done** — mark it complete: `nbd update <id> --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 010: use **79** 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 `[<id>]` format.
<conventions>
## 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 `[<id>]` format.
Stub sections in content are marked with 🚧 and reference an nbd ticket — fill in content and close the ticket when complete.
</conventions>

@ -1,7 +1,19 @@
@../CLAUDE.md
# CLAUDE.md — nbd
<working-directory>
All commands in this file are run from the `nbd/` directory.
</working-directory>
<project-overview>
`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-overview>
<project-structure>
## Project Structure
```
@ -24,6 +36,10 @@ nbd/
└── README.md
```
</project-structure>
<tech-stack>
## Tech Stack
- **Language:** Rust (edition 2021)
@ -32,6 +48,10 @@ nbd/
- **Serialization:** `serde` + `serde_json`
- **Test utilities:** `tempfile` (dev-dependency)
</tech-stack>
<data-model>
## 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 {
}
```
</data-model>
<cli-interface>
## CLI Interface
```sh
@ -70,6 +94,10 @@ nbd graph [<id>] [--filter KEY=VALUE ...] [--json]
`--json` is available on all commands for machine-readable output.
</cli-interface>
<module-responsibilities>
## Module Responsibilities
| Module | Responsibility |
@ -82,6 +110,10 @@ nbd graph [<id>] [--filter KEY=VALUE ...] [--json]
| `filter.rs` | glob-pattern ticket filtering |
| `tests.rs` | unit tests for all modules |
</module-responsibilities>
<task-tracking>
## 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 <id> --json
- `--priority` follows 010: use 79 for bugs, 5 for normal tasks, 3 for nice-to-haves.
- `--type` choices: `project`, `feature`, `task`, `bug`.
---
</task-tracking>
## Validation
Run in order from this directory before committing:
```sh
cargo fmt
cargo check
cargo clippy
cargo test
```
<testing>
## 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.
</testing>

@ -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.
<working-directory>
Run all commands from the relevant sub-directory within `quotesdb/` (e.g., `api/`, `ui/`, `infra/`) — not from the repository root or the `quotesdb/` root.
</working-directory>
---
<project-overview>
## Project Overview
@ -16,7 +20,9 @@
Design reference: `docs/plans/2026-02-27-quotesdb-design.md`
---
</project-overview>
<ticket-hierarchy>
## 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).
---
</ticket-hierarchy>
<branch-and-worktree-workflow>
## Branch & Worktree Workflow
@ -82,7 +90,9 @@ git merge quotesdb/api/<id>
git worktree remove .claude/worktrees/quotesdb-api-<id>
```
---
</branch-and-worktree-workflow>
<domain-expert-agents>
## 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): ...`)
---
</domain-expert-agents>
<design-reference>
## Design Reference
<database-schema>
### Database Schema
```sql
@ -127,6 +141,10 @@ CREATE TABLE quote_tags (
);
```
</database-schema>
<api-endpoints>
### 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`.
</api-endpoints>
<auth>
### 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.
</auth>
<frontend-routes>
### 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 |
---
</frontend-routes>
</design-reference>
<api-specification>
## 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
```
</api-specification>

Loading…
Cancel
Save