---
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/`
