Appearance
ADR-0002: Zero Runtime Dependencies
- Status: Accepted
- Date: 2026-04-14
- Supersedes: None
- Amendment: ADR-0006 permits
yaml@^2.8as a narrowly-scoped runtime dependency (2026-04-15). - Amendment: ADR-0014 permits
@huggingface/transformersandusearchunderoptionalDependenciesfor the opt-in Vector-Memory layer (2026-05-08).
Context and Problem Statement
package.json's dependencies block is the only way nubos-pilot can ship transitive complexity to end users through npx. Every runtime dependency carries three costs: a supply-chain surface, a version-compatibility constraint, and an install-failure mode (Windows path quirks, corporate proxies, air-gapped networks, peer-dep conflicts, abandoned maintainers). The question: should nubos-pilot ever declare runtime dependencies?
Scope
This ADR is about package.json.dependencies specifically: the subset of package.json that ships to end users via npm install / npx.
- "Zero runtime deps" means:
package.json.dependencies === {}(empty object, not absent). No library is pulled down at install time on an end-user machine. devDependenciesare explicitly permitted. Test runners, optional hook bundlers, and similar authoring-time tooling live there. They are never shipped to end users.- Environment assumptions are not dependencies.
git,node >=22, and the host agent CLI are assumed to exist on the user's machine. They are prerequisites, not thingsnubos-pilotships.
Decision Drivers
- Sufficiency of Node builtins: the full markdown-workflow surface (frontmatter parsing, readline prompts, file locking, ANSI output, child-process spawn) is reachable through
fs,path,os,child_process,readline,crypto, andutilalone. npxinstall reliability: zero deps ≈ zero failure modes on Windows, corporate networks, and air-gapped environments.- Patchability (Core Value): users copy
.cjsfiles verbatim into.claude/nubos-pilot/and sometimes patch them locally; there is nonode_modules/tree to keep in sync. - Security: zero runtime deps ≈ zero supply-chain surface.
Considered Options
- Zero runtime dependencies: Node builtins + hand-rolled helpers. (CHOSEN)
- Rich dependency tree: adopt a broad runtime surface (coding-agent SDK,
playwright,sharp,chokidar,@modelcontextprotocol/sdk,chalk/picocolors). - Native Rust N-API engine: publish per-platform prebuilt binaries as
optionalDependencies. - Accept a single narrow dependency pragmatically: e.g.
yamlfor frontmatter parsing.
Decision Outcome
Chosen: "Zero runtime dependencies", because it is the only option that reinforces the Core-Value patchability story and minimizes install-failure modes on the weakest user environments simultaneously. The devDependencies escape hatch covers authoring-time needs without leaking into end-user installs.
Escape hatch for future exceptions: if a concrete future feature genuinely requires a runtime dep that builtins cannot satisfy, the exception is introduced by a new ADR that either supersedes ADR-0002 wholesale or amends it narrowly with a name-scoped exemption. The escape is deliberately bureaucratic so that "just add a dep" never becomes the reflex answer. (See ADR-0006 for the first exercise of this hatch.)
Consequences
- Good:
npm installis effectively a no-op for end users. - Good: supply-chain audits are trivial.
- Good: users can copy-patch
.cjsfiles without module-resolution confusion. - Good: the install-payload tree contains only
.cjsfiles and Markdown. - Bad: we reimplement small utilities (YAML frontmatter via hand-rolled parser, readline prompts, raw ANSI escapes). Accepted cost.
- Neutral:
devDependenciesare permitted and do not ship to users. - Neutral:
optionalDependenciesfor native prebuilt binaries is rejected as a general escape hatch by this ADR, so there is no accidental backdoor. The narrow exemption permitted by ADR-0014 is opt-in (config-gated,memory.enabled=true), lazy-loaded, and only resolves at install time when explicitly requested vianpm install --include=optional.
Pros and Cons of the Options
Zero runtime dependencies — chosen
- Good: Node builtins cover the entire markdown-workflow surface.
- Good: preserves the Core Value "markdown-only, multi-runtime, ohne eigenes Daemon".
- Bad: every small utility must be hand-rolled. Accepted.
Rich dependency tree — rejected
- Good:
chalk/picocolorsproduce nicer output;@clack/promptsproduces nicer Q&A flows. - Bad:
playwright,sharp,sql.js,chokidar, image addons target features we do not implement. - Bad:
@modelcontextprotocol/sdkas a runtime dep contradictsREQUIREMENTS.md§"Out of Scope". - Bad:
@anthropic-ai/claude-agent-sdkimplies we spawn agents, which is the daemon pattern ADR-0001 forbids. - Bad: every transitive node_module is an install-failure risk on the environments that most need
nubos-pilotto "just work".
Native Rust N-API engine — rejected
- Good: native binaries offer raw-speed
grep/ast-grep/syntax-highlighting. - Bad: requires per-platform prebuilt binaries with the associated CI/release plumbing.
- Bad: we have no TUI, no image pipeline, no watcher.
- Bad: Claude Code already exposes
Grep,Read,Bashas first-class tools. - Bad: introducing a binary-ship story violates patchability.
Accept a single narrow dependency pragmatically — rejected (for now)
- Good: one dep would make frontmatter parsing handle multiline sequences and anchors.
- Bad: "just one dep" is a slippery slope.
- Bad: the escape-hatch route exists for exactly this situation.
(Update: see ADR-0006; yaml@^2.8 was eventually accepted under the escape-hatch route.)
More Information
- Related ADR: ADR-0005. The install-payload tree contains only
.cjs+ Markdown. - CLAUDE.md: §"Technology Stack" → "Installation"; §"External runtime dependencies"; §"Alternatives Considered".
- REQUIREMENTS.md: §"Out of Scope" → "Nubos-MCP als First-Class-Dependency".
This ADR does not describe CI enforcement. CI-gate enforcement of the zero-deps rule is deferred to a later deploy/CI phase per ROADMAP.md; current enforcement consists of human PR review and this ADR as the authoritative reference.
