Repo: lemonfiber
Rendered from spec at76d46f3 (2026-10-25) · its source · Edit this page
Status: Accepted
The lemonfiber binary — CLI, TUI and web UI over one core. Rust, Hippocratic 3.0.
Implements: the operator-facing half of 10-functional, under the structure fixed in 20-architecture/component-model.
What this repo is
One binary, three surfaces, one core. It sets the stack up, runs it, and proves it’s working. It is not a general Docker manager (vision non-goals) — its value is that it knows about this stack.
Layout
lemonfiber/
├── Cargo.toml workspace
├── crates/
│ ├── lemonfiber/ bin — chooses a surface and runs it
│ │ ├── build.rs validates submodule schema_version
│ │ ├── src/cli.rs clap: subcommands, flags
│ │ ├── src/dashboard.rs ratatui: the dashboard and the log viewer
│ │ ├── src/ui.rs binds the socket the web surface is served on
│ │ ├── src/main.rs surface selection
│ │ └── tests/ integration tests
│ ├── lemonfiber-api/ lib — axum: the JSON endpoints, and the frontend served
│ ├── lemonfiber-core/ lib — all logic, no UI
│ ├── lemonfiber-ports/ lib — the boundary and its vocabulary
│ ├── lemonfiber-adapters/ lib — the ports' implementations that reach outside the process
│ ├── lemonfiber-fixtures/ lib — the fakes for those traits
│ ├── lemonfiber-manifest/ lib — stack.toml
│ └── lemonfiber-plugin/ lib — plugin.toml, and the vocabularies a plugin names things from
├── assets/media-stack/ git submodule, embedded at build
├── assets/web/ git submodule — the built web surface, embedded at build
├── contract/ generated contracts: the web API, the plugin schema and vocabularies
├── reference/ the generated command reference, error codes and release record
└── .docs/ repo-local technical docs
Crate responsibilities are fixed in component-model; this doc covers what’s specific to building the repo.
.docs/ — repo-local documentation
Per the three-layer model,
lemonfiber carries its own .docs/ tree for Rust-specific technical detail that is
not a product decision (those live in this spec) and not a code comment.
lemonfiber/.docs/
├── 00-index.md
├── architecture/ how subsystems are built — the ports boundary, dispatch,
│ the engine API, the embedded stack, the error model
└── conventions/ an index pointing at the comment policy, which is canonical in the spec
Code links here (Q-R5); these pages cite spec requirement IDs. This is the
middle layer that keeps requirement IDs out of code comments (GOV-R6) while
still connecting code to the spec.
Surface selection
flowchart TD
start[lemonfiber invoked] --> args{subcommand?}
args -->|"up/down/doctor/…"| cli[CLI path]
args -->|"ui"| web[Start web server]
args -->|none| tty{stdout a TTY?}
tty -->|yes| conf{configured?}
tty -->|no| help[Print help, exit]
conf -->|yes| dash[TUI dashboard]
conf -->|no| wiz[Offer setup]
This realises G1-R3 and G1-R4: bare invocation opens the TUI at a terminal and prints help when piped, never blocking on stdin.
Key dependencies
| Crate | Role | Why |
|---|---|---|
clap |
CLI parsing | Derive; generates help and completions |
ratatui + crossterm |
TUI | ADR-0003; crossterm for real Windows support |
axum |
Web server | Minimal, tokio-native; lemonfiber-api, and the socket the lemonfiber crate binds |
bollard |
Docker API | Reads only; only in lemonfiber-adapters |
tokio |
Async | Shallow — component-model |
reqwest |
Service HTTP | Seed clients |
serde + toml |
Manifest, config | |
etcetera |
Platform paths | XDG / AppData / ~/Library; permissive dependencies throughout |
include_dir |
Embed stack + web assets | ADR-0005 |
thiserror |
Library errors | lemonfiber-core |
color-eyre |
Binary errors | The lemonfiber crate only |
unsafe is denied crate-wide (see code-standards).
The submodule
assets/media-stack is a git submodule pinned to a lemonfiber-media-stack commit.
crates/lemonfiber/build.rs:
- Fails clearly if the submodule is empty (
git submodule update --init). - Parses
stack.tomland fails the build ifschema_versionis unsupported (ARCH-R6).
So an incompatible stack/binary pairing cannot compile, let alone ship.
Build-time work
| Step | Produces |
|---|---|
build.rs |
Schema validation; embedded stack |
cargo build |
The binary |
The app is built in lemonfiber-web’s own CI and tagged
there; this repo carries the result as a pinned submodule and embeds it with
include_dir! (ADR-0012).
No Node toolchain enters the Rust build or the operator’s machine (ARCH-R19).
Configuration on disk
| Path (Linux shown) | Holds |
|---|---|
~/.config/lemonfiber/ |
.env, expected-state baseline, journal |
~/.local/share/lemonfiber/stack/ |
Materialised stack files |
~/.local/share/lemonfiber/config/ |
Per-service config (the /config mounts) |
~/.local/share/lemonfiber/backups/ |
Backup archives |
Resolved via etcetera, so macOS and Windows get their conventional
locations. --stack-dir overrides the stack path (F1-R3).
Testing posture
Most of lemonfiber-core is testable without Docker or a terminal, by design
(ARCH-R11). Detail in testing-strategy; the
load-bearing point:
- Command construction is pure → golden-file tested across every form × every platform, no daemon.
- Docker access is behind a trait → mockable.
- Platform is one component → faked, so all four environments run from one
machine (
ARCH-R35).
What lives here vs. in the spec
Here (lemonfiber) |
Spec |
|---|---|
| How the render loop is built | That it must not block (B3-R4) |
| Which crate parses TOML | The manifest contract |
| The exact port-push shell mechanism | That the port must be re-pushed (C2-R5) |
| Rust module structure | That core cannot render (ARCH-R11) |
Rule of thumb: what and why are the spec’s; how, in Rust is this
repo’s .docs/.
Related
- lemonfiber-tui.md — screen-by-screen TUI spec
- lemonfiber-reference.md — every subcommand and flag
- component-model · platform-matrix
- 40-quality — how the code is written