Skip to content

ADR-0004: Four repos rather than a monorepo

Status: Accepted Date: 2026-07-24

The project produces four artifacts: a specification, a Rust binary, a set of Compose/config files, and Homebrew formulae. These could live in one repo with directories, or in separate repos under the lemonfiber org.

Two facts constrain the choice:

  1. Homebrew formulae must live in their own repo. A tap is a repo named homebrew-<name>. This isn’t a preference; it’s how brew tap works. So the floor is two repos regardless.
  2. The artifacts have genuinely different change rates and review styles. The spec changes on decisions. The stack changes when a service is added or a pinned image bumps — reviewed by reading YAML. lemonfiber changes constantly during development — reviewed by reading Rust, with tests and a CI matrix.

Four repos:

Repo Contents Changes when Reviewed by
spec This specification A decision is made Reading prose
lemonfiber Rust CLI/TUI (the lemonfiber binary) Feature work Reading Rust + CI
lemonfiber-media-stack compose.yml, stack.toml, service configs, overlays A service changes Reading YAML
homebrew-tap Formulae (generated) Every release Nothing — it’s generated

lemonfiber-media-stack enters lemonfiber as a git submodule, embedded at build time — see ADR-0005.

Option Why it lost
Monorepo + separate tap The most defensible alternative, and normally I’d favour it. Lost on a specific product goal: lemonfiber-media-stack must be independently forkable and usable without lemonfiber (see ADR-0001). A directory inside a Rust repo signals “implementation detail”; a repo signals “artifact you can use.”
Two repos (lemonfiber incl. stack, + tap) Loses the independent-fork property entirely.
Five+ (splitting docs from spec, etc.) No benefit; more coordination overhead.
  • lemonfiber-media-stack can be cloned and run with plain docker compose by someone who has never heard of lemonfiber. This is a real hedge: if lemonfiber stagnates, the stack still works.
  • Each repo gets CI proportionate to its risk. lemonfiber-media-stack needs docker compose config validation and a lint; lemonfiber needs a three-platform build matrix. Merged, everything pays the expensive cost.
  • Issues land in the right place without triage.
  • The spec is citable and versioned independently of any implementation.
  • Version skew is now possible — the central risk this split introduces. A change spanning lemonfiber and lemonfiber-media-stack requires two PRs, and a user could pair incompatible versions. Mitigated by the schema_version contract in stack.toml (versioning) and, because the stack is embedded at build time, largely converted into a compile-time error rather than a runtime one.
  • Cross-repo changes need coordination. Real cost, accepted.
  • Four sets of CI config, licence files, and issue templates to keep aligned.
  • The submodule pin makes “which stack version does lemonfiber v0.4 ship?” precisely answerable — arguably better than a monorepo, where the answer is implicit.
  • Cross-repo coordination overhead visibly slows development.
  • The independent-usability property of lemonfiber-media-stack turns out not to matter to anyone in practice.

The split held; the count did not. The same reasoning — an artifact with its own change rate, review style and release clock earns its own repo — has since been applied three more times, by ADR-0011 for the web surface and ADR-0013 for the API clients. This ADR records why the project is not a monorepo, which is still true; it is not the current inventory of repositories. That lives in 30-repos.

This page lives in another repository Rendered from lemonfiber/spec at 1d10402, 2026-09-09. Read the source of this page