--- id: 660e8400-e29b-41d4-a716-446655440001 type: decision title: Use Nickel for Configuration created: 2026-01-15T09:00:00Z modified: 2026-01-15T09:30:00Z tags: ["architecture", "configuration", "nickel"] status: accepted relates_to: - pattern-config-driven-design supersedes: - decision-use-toml-only project: knowledge-base context: | We need a configuration system for the knowledge base that is: - Type-safe at definition time - Composable and reusable - Validated before reaching Rust code - Easy to understand and maintain decision: | Use Nickel (.ncl) as the primary configuration format, with TOML and JSON as fallbacks. Pattern: Nickel → JSON → serde → Rust structs This provides double validation: Nickel type checker + Rust serde. consequences: - Adds Nickel CLI as a dependency for config export - Provides compile-time type safety for configurations - Enables schema composition and inheritance - Clear error messages with line numbers - Users can still use TOML/JSON if Nickel not available --- # Use Nickel for Configuration ## Status Accepted Supersedes: [[decision-use-toml-only]] ## Context We need a configuration system for the knowledge base that is: - Type-safe at definition time - Composable and reusable - Validated before reaching Rust code - Easy to understand and maintain Previous approach used TOML-only, which lacked compile-time validation and composition features. ## Decision Use Nickel (.ncl) as the primary configuration format, with TOML and JSON as fallbacks. **Pattern:** Nickel → JSON → serde → Rust structs This provides double validation: Nickel type checker validates .ncl files, then Rust serde validates JSON. **Implementation:** - Define schemas in `schemas/*.ncl` - Export via `nickel export --format json` - Load JSON in Rust via serde - Fall back to TOML/JSON if Nickel CLI unavailable ## Consequences **Positive:** - Type safety at configuration definition time - Compile errors show exact line numbers in config files - Schema composition enables inheritance and overrides - Documentation built into schema (via `| doc "..."`) - IDE support via Nickel LSP - Still supports TOML/JSON for users without Nickel **Negative:** - Adds Nickel CLI as a build-time dependency - Users need to learn Nickel syntax (though TOML/JSON still work) - Extra build step (ncl → json) for Nickel users **Neutral:** - Config loading code needs to handle multiple formats - Schemas must be maintained in Nickel (but provide documentation) ## Alternatives Considered ### Alternative 1: TOML Only **Pros:** - Simple, widely known format - No additional dependencies - Direct serde deserialization **Cons:** - No compile-time type checking - No schema composition - Errors only at runtime - Limited validation ### Alternative 2: JSON Schema **Pros:** - Widely supported - Validation before Rust code - JSON Schema ecosystem **Cons:** - JSON Schema is verbose and complex - Lacks composition features of Nickel - Error messages not as clear - Requires separate validation step ## References - [[pattern-config-driven-design]] - [Nickel Language](https://nickel-lang.org/) - Implementation: `crates/kogral-core/src/config/`