# Spec: restructure README.md around a pitch → features → install → per-command usage shape Status: done -- current README **Origin.** Modeled on the structure of [`dsplce-co/supabase-plus`'s README](https://raw.githubusercontent.com/dsplce-co/supabase-plus/refs/heads/master/README.md) — its section shape and pacing, not its content or voice. `supabase-plus` is a Rust CLI tool with crates.io badges, install-method sub-sections, and punchy, jokey per-command usage blurbs; none of that is this project. What's being borrowed is purely structural: a short pitch up front, a scannable features list, a Table of Contents for a doc long enough to need one, installation broken into named sub-methods, and — the part worth the most — usage organized **per command**, each with its own short "why you'd want this" motivation before the command itself, rather than one long undifferentiated block of curl examples. This project's own voice stays: dry, evidence-first, "measured live on [date]" citations, numbers with dates on them. Nothing here asks for new jokes, new claims, or new numbers — only reorganizing what's already true in the current 1039-line `README.md` into a shape a first-time reader can actually navigate. No README changes accompany this document — this is the spec opencode builds from. --- ## What's being borrowed, what's being skipped, and why | Reference element | Verdict | Reasoning | |---|---|---| | Org attribution banner (top link) | **Skip** | No org; this is a personal project. | | Badges row (crates.io, license, version) | **Skip, or minimal** | Nothing here is published to a package registry. A license badge only makes sense once a license exists (see Open Decisions below) — don't badge something that isn't true yet. | | One-line pitch + short elaboration paragraph | **Adopt** | The current README already has this content (see §1 below) — it's just buried under a heading instead of leading the file. | | Italic disclaimer right after the pitch | **Adopt, re-aimed** | The reference's is a trademark disclaimer. This project's real analog already exists and is more load-bearing: *"Numbers in this README are measurements, not specifications"* (current README, "What This Is"). Same structural slot — a caveat before anyone trusts a number — different content. | | Demo GIF | **Optional, not this pass** | `tui.py`'s live dashboard is the natural candidate, but capturing one is a manual terminal recording step, not something a text plan can produce. Leave a placeholder comment (``) rather than skip the idea entirely. | | `## Features` — punchy bulleted list | **Adopt, own voice** | See §2. The existing "At a Glance" table already IS a features summary, just in dry-table form instead of scannable bullets. | | `---` / Table of Contents | **Adopt, straightforwardly** | The current README has **no TOC at all** across ~25 major sections and 1039 lines. This is the single highest-value, lowest-risk item in this whole plan — pure navigation, no content decisions required. | | `## Installation` with named sub-methods | **Adopt, honestly scoped** | The reference has 6 real install methods (nix/cargo/homebrew/deb/apt/aur). This project has exactly one (`venv` + `pip`) plus a systemd deployment path. Structure as two sub-sections — "Local" and "As a systemd service" — not six fake ones. Do not invent install methods that don't exist to mimic the reference's breadth. | | `## Usage` — one sub-heading per command, motivation → command → bullets | **Adopt — the main point of this plan** | See §3. This is the biggest actual improvement available: the current "Quick Usage" section is 9 curl commands in one code block with almost no narrative, while the *reasons* for each one are already written elsewhere in the doc, disconnected from the command they justify. | | `## Requirements` | **Adopt** | Already exists as a sentence in "Setup" ("You need: a Neuralwatt API key, Python 3.10+...") — promote it to its own short section, matching the reference's terse bulleted form. | | `## Repo & Contributions` | **Needs a decision, see below** | The reference is a public GitHub project soliciting PRs. This repo's remote is a private, self-hosted Gitea instance (`git.adlee.work`) — "PRs welcome" isn't true here. | | `## License` | **Needs a decision, see below** | No `LICENSE` file exists in this repo (checked directly). The reference names MIT/Apache-2.0 because those are real, chosen licenses. Do not write a license section that names something that isn't actually true. | ## Open decisions (yours, not opencode's to invent) Two sections in the reference structure map to facts that don't exist yet in this repo. Both should be **explicit decisions**, not filled in by guessing during implementation: 1. **License.** Pick one (or explicitly decide "unlicensed / private, not for redistribution") before a `## License` section gets written. Whatever is decided, add the matching `LICENSE` file at the same time — a README section naming a license with no `LICENSE` file in the repo would be the exact "documented but not actually true" failure mode this project's own `config.yaml` strictness rules exist to prevent elsewhere. 2. **Repo & Contributions.** Given the remote is a private Gitea instance rather than a public GitHub project, decide whether this section exists at all, and if so what it actually says — a link to the internal remote for your own reference, not an open invitation for outside contributions that can't reasonably arrive here. If no decision is made, the plan's default is: **omit both sections** rather than have opencode fabricate a license or a contribution policy that isn't real. ## Section-by-section mechanism ### §1. Pitch + elaboration (replaces the top of "What This Is") Move the existing lead paragraph up to immediately follow the `# Local LLM Model Router` title, ahead of any subheading — this is exactly what the reference does (pitch line, then one elaborating paragraph, before any `##`). Source material already exists verbatim in the current README's opening paragraph and the "Numbers in this README are measurements, not specifications" caveat — this section is a move-and-reflow, not a rewrite. ### §2. `## Features` Reference pattern: one bullet per capability, phrased as a real situation the reader has been in, followed by the command that fixes it. This project's own voice should replace "clever/jokey" with "concrete/measured" — the through-line of the whole existing document. Candidate bullets, pulled directly from existing content rather than invented: - `POST /route` — "Want to know what a task would cost before you spend anything on it?" *(current README: "no provider call, no cost")* - Per-request energy/cost pricing — "List price ranks models backwards for this workload; billing is per-kWh, and this router prices per request from what's actually shaped like your traffic." *(current: "Weighted Scoring" section)* - Local vision fallback — "Your cheapest coding model doesn't support images. This one falls back to a local model instead of 422ing." *(current: "Local Vision Fallback")* - Live TUI — "`python tui.py`, a live routing feed with no polling delay." *(current: "Monitoring")* - Structural + local-LLM verification — "Every response gets checked for free before routing ever learns from it." *(current: "Verification Pipeline")* Five bullets, matching the reference's scope (3 headline + "and others like"), not an exhaustive re-listing of every feature — the full detail still lives in its own section further down, same as the reference's `## Usage` expands on its `## Features` teasers. ### §3. `## Usage` — the main restructuring work Current "Quick Usage" is one code block, 9 `curl` commands, minimal narrative. Reference pattern is one `###` sub-heading per command: a short paragraph on *why* (often phrased as the problem the reader already has), then the command, then a bullet list of what it actually does. This project already has the "why" prose for nearly every command — it's just located in a different section than the command itself. Concrete mapping (existing source section → new usage sub-heading): | New `### ` sub-heading | Command | Source prose already written | |---|---|---| | Route without spending anything | `POST /route` | API Endpoints table: "no provider call, no cost" | | Skip the classifier when you already know the shape | `/route` with overrides | "Input to `/route` and `/dispatch` can include... overrides — these skip the classifier" | | Actually dispatch and log energy | `POST /dispatch` | API Endpoints table | | Point any OpenAI-compatible client at it | `/v1/chat/completions`, `/v1/models` | "Pointing a Coding Agent at It" | | Route overnight/batch work through flex rows | `latency_tolerance: batch` | "auto:batch admits flex rows for async work" | | Ask an image question | image_url request | "Local Vision Fallback" | | Force JSON output | `response_format` | Weighted Scoring, hard filter #6 | | Watch it live | `python tui.py`, `/metrics`, `/events/decisions` | "Monitoring" section, mostly verbatim | | Probe routing without spending | `router_cli.py` | "Monitoring" section | This is reorganization, not new writing: every cell in the right column already exists in the current README. The work is moving each explanation next to the command it explains, and adding a one-line "why" lead-in where the existing text is purely descriptive rather than motivating. ### §4. `## Installation` Two named sub-sections, matching what's actually true: - **Local (`venv`)** — the existing "Setup" code block, unchanged. - **As a systemd service** — the existing "Scheduled Jobs (systemd)" table and its install pointer to `deploy/README.md`. Do not add a third method. The reference's breadth (6 install paths) exists because that project targets a general audience installing a CLI tool from multiple ecosystems; this one has an owner, a GPU, and a fixed deployment shape. ### §5. `## Requirements` Pull the existing "Setup" opening sentence — "a Neuralwatt API key, Python 3.10+ (suite verified on 3.10 and 3.14), and an Ollama reachable from wherever this runs with a classifier model pulled" — into its own short bulleted section, ahead of Installation, matching the reference's `requirements`-before-`installation` ordering. ### §6. Table of Contents Auto-derivable from the final heading structure once the above moves are made. Every existing `##`/`###` heading gets an entry; nest sub-headings (Usage's per-command sections, Installation's two methods) the way the reference nests its own. ## What must NOT change This is a restructuring of entry points and navigation, not a rewrite of substance. Everything below stays exactly as it is, moved but not rewritten: - The architecture diagram, the module table, the full schema documentation (`models`/`proficiency`/`energy_observations`/`verifications`/ `route_decisions`), the weighted-scoring mechanism, the classifier reliability notes, and Known Limitations & Open Items — none of this has a reference-README equivalent because `supabase-plus` doesn't carry this much operational depth. It stays as reference material past the new Usage/Installation front matter, in its current form. - No new measurements, dates, or claims. Every fact placed into a new section must already exist verbatim (or near-verbatim, for reflow) somewhere in the current `README.md`. - No jokes or voice imported from the reference. "Had buckets locally once, never found them in prod" works for a Supabase CLI's audience; this project's own established register — measured numbers, dated observations, named caveats — is what every other document in this repo already uses, and the README should not be the one place that departs from it. ## Recommendation Build it. The highest-value pieces (a Table of Contents for a 1039-line document that currently has none, and moving existing "why" prose next to the commands it explains) require no new facts and no voice risk — they're pure reorganization. The two sections that need a real answer (License, Repo & Contributions) should get one from you before opencode touches them; absent that, the plan's default is to leave them out rather than invent them.