Nickel Roundtrip Example
Complete example demonstrating the roundtrip workflow: load existing configuration, edit via interactive form, and regenerate with diff viewer.
Scenario
CI configuration management - edit GitHub Actions settings through a form interface while preserving the Nickel structure.
Files
- config.ncl - Input/output Nickel configuration
- ci-form.toml - Form definition with
nickel_pathmappings - config.ncl.j2 - Tera template for generating output
- 01-generate-initial-config.sh - Create initial config
- 02-roundtrip-cli.sh - Edit via CLI backend
- 03-roundtrip-tui.sh - Edit via TUI backend
- 04-roundtrip-web.sh - Edit via Web backend
Quick Start
# 1. Generate initial configuration
./01-generate-initial-config.sh
# 2. Edit with your preferred backend:
# CLI (command-line prompts)
./02-roundtrip-cli.sh
# TUI (full-screen terminal UI)
./03-roundtrip-tui.sh
# Web (browser-based form)
./04-roundtrip-web.sh
Key Features
nickel_path Mapping
Every field in ci-form.toml has a nickel_path attribute mapping to the Nickel structure:
[[elements]]
name = "parallel_jobs"
type = "text"
prompt = "Parallel Jobs"
default = "4"
nickel_path = ["ci", "github_actions", "parallel_jobs"]
Maps to:
{
ci = {
github_actions = {
parallel_jobs = 4
}
}
}
Template Rendering
The config.ncl.j2 template uses form values to generate valid Nickel:
{
project = {
name = "{{ project_name }}",
description = "{{ project_description }}",
},
ci = {
github_actions = {
enabled = {{ enable_github_actions }},
parallel_jobs = {{ parallel_jobs }},
timeout_minutes = {{ timeout_minutes }},
}
}
}
Summary with Diff
After editing, see what changed:
╔════════════════════════════════════════════════════════════╗
║ ✅ Configuration Saved Successfully! ║
╠════════════════════════════════════════════════════════════╣
║ 📄 File: config.ncl ║
║ ✓ Validation: ✓ PASSED ║
║ 📊 Fields: 3/12 changed, 9 unchanged ║
╠════════════════════════════════════════════════════════════╣
║ 📋 What Changed: ║
║ ├─ parallel_jobs: 4 → 8 ║
║ ├─ timeout_minutes: 60 → 120 ║
║ ├─ enable_cache: false → true ║
╠════════════════════════════════════════════════════════════╣
║ 💡 Next Steps: ║
║ • Review: cat config.ncl ║
║ • Apply CI tools: ./setup-ci.sh ║
║ • Re-configure: ./ci-configure.sh ║
╚════════════════════════════════════════════════════════════╝
Workflow Details
1. Load Defaults
Roundtrip reads config.ncl and extracts values using nickel_path:
// Internally:
nickel export config.ncl // → JSON
extract_value_by_path(json, ["ci", "github_actions", "parallel_jobs"]) // → 4
2. Populate Form
Form fields get pre-filled with current values:
- Text fields show current text
- Numbers show current numbers
- Booleans show current true/false
- Select fields pre-select current option
3. Edit Interactively
User edits via chosen backend (CLI/TUI/Web).
4. Generate Output
Template renders with new values:
parallel_jobs = {{ parallel_jobs }}, // User changed 4 → 8
5. Validate
Automatic validation:
nickel typecheck config.ncl
6. Show Summary
Terminal summary (all backends) + HTML summary (web only).
Backend Comparison
| Feature | CLI | TUI | Web |
|---|---|---|---|
| Terminal UI | ✓ | ✓ | ✓ (summary only) |
| Browser UI | ✗ | ✗ | ✓ |
| Pre-populated values | ✓ | ✓ | ✓ |
| Real-time validation | ✗ | ✓ | ✓ |
| HTML diff viewer | ✗ | ✗ | ✓ |
| Download button | ✗ | ✗ | ✓ |
Customization
Add More Fields
-
Update form:
[[elements]] name = "rust_version" type = "select" prompt = "Rust Version" options = [ { value = "stable", label = "Stable" }, { value = "nightly", label = "Nightly" } ] nickel_path = ["ci", "rust", "version"] -
Update template:
ci = { rust = { version = "{{ rust_version }}", } } -
Update initial config:
{ ci = { rust = { version = "stable" } } }
Change Template Logic
Add conditionals:
{% if enable_cache %}
cache = {
enabled = true,
paths = {{ cache_paths | json }},
},
{% endif %}
Disable Validation
typedialog nickel-roundtrip \
--input config.ncl \
--form ci-form.toml \
--output config.ncl \
--ncl-template config.ncl.j2 \
--no-validate # ← Skip nickel typecheck
Troubleshooting
No defaults loaded:
# Check nickel export works
nickel export config.ncl
# Verify all fields have nickel_path
grep "nickel_path" ci-form.toml | wc -l
Template errors:
# Test template separately
echo '{"project_name": "test"}' | \
tera --template config.ncl.j2
Validation fails:
# Check manually
nickel typecheck config.ncl
Learn More
- nickel.md - Full roundtrip documentation
- Nickel Language - Nickel reference
- Tera Templates - Template syntax