skills/docs/adr/006-nim-worker-cli.md
dan daec0f3b85 docs: ADR-006 Nim language choice for worker CLI
Documents rationale for using Nim with ORC for the worker coordination
CLI: fast startup, single binary, Python-like syntax, excellent SQLite
support via tiny_sqlite, CLI generation via cligen.

Closes skills-q40

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 23:27:32 -08:00

165 lines
4.6 KiB
Markdown

# ADR-006: Nim for Worker Coordination CLI
## Status
Accepted
## Context
The multi-agent orchestration system needs a CLI tool (`worker`) for:
- Spawning worker workspaces with git worktrees
- State machine transitions (ASSIGNED → WORKING → IN_REVIEW → APPROVED → COMPLETED)
- Heartbeat monitoring for stuck agent detection
- SQLite-based message bus for coordination
- Review-gate integration for quality enforcement
Requirements:
- Fast startup (<10ms) for CLI commands run frequently
- Single static binary for deployment simplicity
- SQLite with WAL mode for concurrent access
- Background thread for heartbeat without shared state complexity
- Easy iteration during development
## Decision
Use **Nim** with ORC memory management for the worker CLI.
### Core Dependencies
| Package | Purpose |
|---------|---------|
| `tiny_sqlite` | SQLite wrapper with RAII, statement caching |
| `cligen` | Auto-generates CLI from proc signatures |
| `std/json` | JSON parsing for context files |
### Why Nim
**Performance:**
- ~1ms startup time (vs ~50ms Python, ~20ms Go)
- Compiles to native binary via C backend
- No runtime initialization overhead
**Developer Experience:**
- Python-like syntax, low learning curve
- REPL available for prototyping (`nim secret`)
- Compile-time checks catch errors early
- Excellent error messages
**Memory Management:**
- ORC (Ownership + Reference Counting) handles cycles automatically
- No manual memory management needed
- Deterministic cleanup via destructors
- Thread-safe without shared state via channels
**SQLite Integration:**
- `tiny_sqlite` provides clean RAII semantics
- Statement caching for performance
- Proper NULL handling via Option types
- WAL mode works correctly with multiple connections
**CLI Generation:**
- `cligen` generates CLI from proc signatures
- Help text from doc comments
- Type-safe argument parsing
- Subcommands via `dispatchMulti`
Example:
```nim
proc spawn(taskId: string, description = "", fromBranch = "origin/integration") =
## Create a new worker workspace
...
when isMainModule:
dispatchMulti(
[spawn, help = {"taskId": "Task identifier"}]
)
```
### Alternatives Considered
**Python:**
- Slow startup (~50ms) unacceptable for frequent CLI calls
- Packaging complexity (venv, dependencies)
- Would work for prototype but not production
**Go:**
- Faster startup than Python (~20ms) but still slower than Nim
- More verbose syntax
- Good SQLite support via mattn/go-sqlite3
- Reasonable choice but Nim is more pleasant to write
**Rust:**
- Excellent performance and safety
- Steep learning curve slows iteration
- Borrow checker friction for exploratory code
- Good for later rewrite if needed
**Bash:**
- Used for review-gate (simpler requirements)
- Inadequate for state machine and SQLite operations
- Error handling is painful
### Build Configuration
```nim
# config.nims
switch("mm", "orc") # Memory management
switch("threads", "on") # Background heartbeat thread
switch("d", "release") # Optimizations
switch("opt", "size") # Smaller binary
switch("passL", "-lsqlite3") # Link SQLite
```
Build command:
```bash
nim c -d:release src/worker.nim
```
### Architecture
```
src/
├── worker.nim # CLI dispatch, command implementations
└── worker/
├── types.nim # Shared types, constants, error types
├── db.nim # SQLite operations, message bus
├── state.nim # State machine transitions
├── git.nim # Worktree operations
├── context.nim # Worker context file handling
├── heartbeat.nim # Background heartbeat thread
├── review.nim # Review-gate integration
└── utils.nim # Common helpers
```
## Consequences
### Positive
- Sub-millisecond startup enables responsive CLI
- Single binary simplifies deployment
- ORC eliminates memory management burden
- `cligen` reduces CLI boilerplate to near-zero
- Python-like syntax enables fast iteration
- Type safety catches bugs at compile time
### Negative
- Smaller ecosystem than Python/Go/Rust
- Fewer developers familiar with Nim
- Some library quality variance
- Compiler occasionally has edge case bugs
### Mitigations
- Pin Nim version (2.2.x) for stability
- Use well-maintained libraries (tiny_sqlite, cligen)
- Keep modules small and focused for maintainability
- Document patterns for future contributors
## References
- [Nim Manual](https://nim-lang.org/docs/manual.html)
- [tiny_sqlite](https://github.com/GULPF/tiny_sqlite)
- [cligen](https://github.com/c-blake/cligen)
- [ORC Memory Management](https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc-in-nim.html)