ADR-001: Single-crate vs Cargo workspace
Why jackin❯ started as a single crate and when it transitioned to a Cargo workspace.
Status: Accepted
Current state: Cargo workspace — 24 member crates under crates/, root jackin binary crate at crates/jackin/. Total ~170 K lines of Rust.
Date: 2026-05-30
Deciders: Operator + agent
Context
Rust projects can live in one crate (src/ only) or in a Cargo workspace (workspace.members = [...]). The initial choice was to stay single-crate and delay workspace adoption until the cost was justified. The threshold was set at 150 K lines of Rust source.
Reference projects that stay single-crate at comparable scale: starship (~120 K LOC at the time of this decision), fd-find. Neither uses a workspace despite large codebases.
Decision
Phase 1 — stay single-crate while total Rust LOC < 150 K. All code lived in one crate. No crates/ directory. Fast cargo build, minimal Cargo.toml overhead, no intra-workspace dependency graph to maintain.
Trigger for workspace adoption: either (a) total Rust LOC exceeds 150 K, or (b) a type from the core codebase is needed by external tooling (an jackin-core use case). Whichever comes first.
Phase 2 — workspace adopted (current state). The codebase crossed ~170 K lines as surface-specific and subsystem crates were extracted. Product-neutral TUI components later moved to exact-revision TermRock; the jackin binary crate at crates/jackin/ remains the primary binary.
Consequences
- Incremental builds are faster per-crate: changing
jackin-capsuledoes not rebuild unrelated product crates. - The root
jackincrate is still the entry point forcargo build --bin jackin; operators and CI do not change their build commands. - Cross-crate
pubboundaries enforce the TUI architecture boundary rule:jackin-consolecannot accidentally calljackin-capsuleinternals. - New code that serves only one surface starts in that surface's crate; neutral TUI code shared across consumers belongs in TermRock, while product protocol code belongs in
jackin-protocol.