Просмотр исходного кода

docs: reorganize contributor and agent guidance

xcad 1 день назад
Родитель
Сommit
9b5f7fd484
7 измененных файлов с 650 добавлено и 702 удалено
  1. 40 702
      AGENTS.md
  2. 64 0
      CONTRIBUTING.md
  3. 131 0
      RELEASE.md
  4. 93 0
      docs/architecture.md
  5. 56 0
      docs/display.md
  6. 109 0
      docs/libraries.md
  7. 157 0
      docs/templates.md

+ 40 - 702
AGENTS.md

@@ -1,725 +1,63 @@
 # AGENTS.md
 
-Guidance for AI Agents working with this repository.
+Guidance for AI coding agents working in this repository.
 
-## Project Overview
+## Project
 
-A Python CLI for managing infrastructure boilerplates, plus archetypes and template-loading logic. Built with Typer (CLI) and Jinja2 (templating).
+Project name: Boilerplates CLI
 
-**Important library location note:**
-- The canonical template library does **not** live in this repository for modern development.
-- The checked-in `library/` directory here is **legacy/backward-compatibility content for versions older than `0.2.0`**.
-- For `0.2.0+`, the active template library lives in the separate GitHub repository `boilerplates-library`.
+A Python CLI for managing infrastructure boilerplates, template libraries, template rendering, and validation. Built with Typer and Jinja2.
 
-## Development Setup
+## Scope and precedence
 
-### Running and Testing
+- This file applies to the repository tree rooted at the directory containing this `AGENTS.md` file.
+- More deeply nested `AGENTS.md` files may add or override instructions for their subtrees.
+- Before GitHub-facing work such as issues, branches, PRs, merges, tags, or releases, read this file and the relevant docs listed below.
+- For release-related work, always read `RELEASE.md` first.
 
-```bash
-# Create and activate a local virtual environment first
-python3 -m venv .venv
-source .venv/bin/activate
-python3 -m pip install --upgrade pip
-python3 -m pip install -e ".[test]"
-
-# Run the CLI application
-python3 -m cli
-# Debugging and Testing commands
-python3 -m cli --log-level DEBUG compose list
-# Run tests
-python3 -m pytest
-```
-
-### Production-Ready Testing
-
-For detailed information about testing boilerplates in a production-like environment before release, see **WARP-LOCAL.md** (local file, not in git). This document covers:
-- Test server infrastructure and Docker contexts
-- Step-by-step testing procedures for Docker Compose, Swarm, and Kubernetes
-- Comprehensive testing checklists
-- Production release criteria
-
-### Linting and Formatting
-
-Should **always** happen before pushing anything to the repository and before making a release.
-
-- Use `ruff` for Python code:
-  - `ruff check --fix .` - Check and auto-fix linting errors (including unused imports)
-  - `ruff format .` - Format code according to style guidelines
-  - Both commands must be run before committing
-- Minimum pre-release verification:
-  - `ruff check --fix .`
-  - `ruff format .`
-  - `python3 -m pytest`
-- Agents should treat these as release gates, not optional cleanup.
-
-### Project Management and Git
-
-The project is stored in a public GitHub Repository, use issues, and branches for features/bugfixes and open PRs for merging.
-
-**Naming Conventions and Best-Practices:**
-- Branches, PRs: `feature/2314-add-feature`, `problem/1249-fix-bug`
-- Issues should have clear titles and descriptions, link related issues/PRs, and have appropriate labels like (problem, feature, discussion, question).
-- Commit messages should be clear and concise, following the format: `type(scope): subject` (e.g., `fix(compose): correct variable parsing`).
-
-## Architecture
-
-### File Structure
-
-- `cli/` - Python CLI application source code
-  - `cli/core/` - Core Components of the CLI application
-  - `cli/modules/` - Modules implementing technology-specific functions
-  - `cli/__main__.py` - CLI entry point, auto-discovers modules and registers commands
-- `library/` - Legacy in-repo template content kept only for backward compatibility with versions older than `0.2.0`
-  - Do not treat this directory as the canonical source for new template work
-  - The active `0.2.0+` library is maintained in the separate GitHub repository `boilerplates-library`
-- `archetypes/` - Testing tool for template snippets (archetype development)
-  - `archetypes/__init__.py` - Package initialization
-  - `archetypes/__main__.py` - CLI tool entry point
-  - `archetypes/<module>/` - Module-specific archetype snippets (e.g., `archetypes/compose/`)
-
-### Core Components
-
-- `cli/core/collection.py` - VariableCollection class (manages sections and variables)
-  - **Key Attributes**: `_sections` (dict of VariableSection objects), `_variable_map` (flat lookup dict)
-  - **Key Methods**: `get_satisfied_values()` (returns enabled variables), `apply_defaults()`, `sort_sections()`
-- `cli/core/config.py` - Configuration management (loading, saving, validation)
-- `cli/core/display/` - Centralized CLI output rendering package (**Always use DisplayManager - never print directly**)
-  - `__init__.py` - Package exports (DisplayManager, DisplaySettings, IconManager)
-  - `display_manager.py` - Main DisplayManager facade
-  - `display_settings.py` - DisplaySettings configuration class
-  - `icon_manager.py` - IconManager for Nerd Font icons
-  - `variable_display.py` - VariableDisplayManager for variable rendering
-  - `template_display.py` - TemplateDisplayManager for template display
-  - `status_display.py` - StatusDisplayManager for status messages
-  - `table_display.py` - TableDisplayManager for table rendering
-- `cli/core/exceptions.py` - Custom exceptions for error handling (**Always use this for raising errors**)
-- `cli/core/library.py` - LibraryManager for template discovery from git-synced libraries and static file paths
-- `cli/core/module.py` - Abstract base class for modules (defines standard commands)
-- `cli/core/prompt.py` - Interactive CLI prompts using rich library
-- `cli/core/registry.py` - Central registry for module classes (auto-discovers modules)
-- `cli/core/repo.py` - Repository management for syncing git-based template libraries
-- `cli/core/section.py` - VariableSection class (stores section metadata and variables)
-  - **Key Attributes**: `key`, `title`, `toggle`, `needs`, `variables` (dict of Variable objects)
-- `cli/core/template.py` - Template Class for parsing, managing and rendering templates
-- `cli/core/variable.py` - Variable class (stores variable metadata and values)
-  - **Key Attributes**: `name`, `type`, `value` (stores default or current value), `description`, `sensitive`, `needs`
-  - **Note**: Default values are stored in `value` attribute, NOT in a separate `default` attribute
-- `cli/core/validators.py` - Semantic validators for template content (Docker Compose, YAML, etc.)
-- `cli/core/version.py` - Version comparison utilities for semantic versioning
-
-### Modules
-
-**Currently supported kinds in code:**
-- `ansible`
-- `compose`
-- `helm`
-- `kubernetes`
-- `packer`
-- `static`
-- `swarm`
-- `terraform`
-
-These are the kinds supported by the registered CLI modules in `cli/modules/`. When answering "what kinds do we support?", prefer this code-level list over whatever legacy content happens to exist under `library/`.
+## Repository map
 
-**Module Structure:**
-Modules can be either single files or packages:
-- **Single file**: `cli/modules/modulename.py` (for simple modules)
+- Source: `cli/` - main CLI application and core runtime code.
+- Tests: `tests/` - automated tests, fixtures, and test utilities.
+- Contribution guide: `CONTRIBUTING.md` - setup, validation, GitHub workflow, and command overview.
+- Docs: `docs/` - developer documentation and architecture notes.
+- Release process: `RELEASE.md` - release PR, version, changelog, tag, and publish workflow.
+- Scripts: `scripts/` - installer and helper scripts.
+- GitHub automation: `.github/` - workflows, issue/PR templates, and repository scripts.
+- Legacy library: `library/` - backward-compatibility template content for versions older than `0.2.0`; not the canonical modern template library.
 
-**Creating Modules:**
-- Subclass `Module` from `cli/core/module.py`
-- Call `registry.register(YourModule)` at module bottom
-- Auto-discovered and registered at CLI startup
-
-**Module Discovery and Registration:**
-
-The system automatically discovers and registers modules at startup:
-
-1. **Discovery**: CLI `__main__.py` imports all Python files in `cli/modules/` directory
-2. **Registration**: Each module file calls `registry.register(ModuleClass)` at module level
-3. **Storage**: Registry stores module classes in a central dictionary by module name
-4. **Command Generation**: CLI framework auto-generates subcommands for each registered module
-5. **Instantiation**: Modules are instantiated on-demand when commands are invoked
-
-**Benefits:**
-- No manual registration needed - just add a file to `cli/modules/`
-- Modules are self-contained - can be added/removed without modifying core code
-- Type-safe - registry validates module interfaces at registration time
-
-
-
-
-```
-  compose/
-    v1.0.json
-    v1.1.json
-    v1.2.json
-  terraform/
-    v1.0.json
-  ansible/
-    v1.0.json
-  ...other modules...
-```
-
-
-
-```json
-[
-  {
-    "key": "section_key",
-    "title": "Section Title",
-    "description": "Optional section description",
-    "toggle": "optional_toggle_variable_name",
-    "needs": "optional_dependency",
-    "required": true,
-    "vars": [
-      {
-        "name": "variable_name",
-        "type": "str",
-        "description": "Variable description",
-        "default": "default_value",
-        "required": true,
-        "sensitive": false,
-        "autogenerated": false,
-        "options": ["option1", "option2"],
-        "needs": "other_var=value",
-        "extra": "Additional help text"
-      }
-    ]
-  }
-]
-```
-
-
-
-```python
-
-class MyModule(Module):
-    name = "mymodule"
-    
-        # Convert JSON array to OrderedDict format
-        return self._convert_json_to_dict(json_spec)
-```
-
-- **Auto-created toggle variables**: Sections with `toggle` automatically create boolean variables
-- **Conditional visibility**: Variables use `needs` constraints to show/hide based on other variable values
-- **Mode-based organization**: Related settings grouped by operational mode (e.g., network_mode, volume_mode)
-
-
-
-Older Python-based `spec_v*.py` files have been migrated to JSON. The module `__init__.py` now:
-2. Converts JSON array format to OrderedDict for backward compatibility
-
-**Existing Modules:**
-- Other modules (ansible, terraform, kubernetes, helm, packer) - Work in Progress
-
-**(Work in Progress):** terraform, docker, ansible, kubernetes, packer modules
-
-### LibraryManager
-
-- Loads libraries from config file
-- Stores Git Libraries under: `~/.config/boilerplates/libraries/{name}/`
-- Uses sparse-checkout to clone only template directories for git-based libraries (avoiding unnecessary files)
-- Supports two library types: **git** (synced from repos) and **static** (local directories)
-- Priority determined by config order (first = highest)
-- In this repository, the checked-in `library/` directory is legacy compatibility data only and should not be treated as the primary source for current template development
-- For current `0.2.0+` template work, use the external GitHub repository `boilerplates-library`
-
-**Library Types:**
-- `git`: Requires `url`, `branch`, `directory` fields
-- `static`: Requires `path` field (absolute or relative to config)
-
-**Duplicate Handling:**
-- Within same library: Raises `DuplicateTemplateError`
-- Across libraries: Uses qualified IDs (e.g., `alloy.default`, `alloy.local`)
-- Simple IDs use priority: `compose show alloy` loads from first library
-- Qualified IDs target specific library: `compose show alloy.local`
-
-**Config Example:**
-```yaml
-libraries:
-  - name: default       # Highest priority (checked first)
-    type: git
-    url: https://github.com/user/templates.git
-    branch: main
-    directory: library
-  - name: local         # Lower priority
-    type: static
-    path: ~/my-templates
-    url: ''             # Backward compatibility fields
-    branch: main
-    directory: .
-```
-
-**Note:** Static libraries include dummy `url`/`branch`/`directory` fields for backward compatibility with older CLI versions.
-
-### ConfigManager
-
-- User Config stored in `~/.config/boilerplates/config.yaml`
-
-### DisplayManager and IconManager
-
-**CRITICAL RULE - NEVER violate this:**
-- NEVER use `console.print()` outside of display manager classes (`cli/core/display/` directory)
-- NEVER import `Console` from `rich.console` except in display manager classes or `cli/__main__.py`
-- ALWAYS use `module_instance.display.display_*()` or `display.display_*()` methods for ALL output
-- Display managers (`cli/core/display/*.py`) are the ONLY exception - they implement console output
-
-**Rationale:**
-- `DisplayManager` provides a **centralized interface** for ALL CLI output rendering
-- Direct console usage bypasses formatting standards, icon management, and output consistency
-- `IconManager` provides **Nerd Font icons** internally for DisplayManager - never use emojis or direct icons
-
-**DisplayManager Architecture** (Refactored for Single Responsibility Principle):
-
-`DisplayManager` acts as a facade that delegates to specialized manager classes:
-
-1. **VariableDisplayManager** - Handles all variable-related rendering
-   - `render_variable_value()` - Variable value formatting with context awareness
-   - `render_section()` - Section header display
-   - `render_variables_table()` - Complete variables table with dependencies
-
-2. **TemplateDisplayManager** - Handles all template-related rendering
-   - `render_template()` - Main template display coordinator
-   - `render_template_header()` - Template metadata display
-   - `render_file_tree()` - Template file structure visualization
-   - `render_file_generation_confirmation()` - Files preview before generation
-
-3. **StatusDisplayManager** - Handles status messages and error display
-   - `display_message()` - Core message formatting with level-based routing
-   - `display_error()`, `display_warning()`, `display_success()`, `display_info()` - Convenience methods
-   - `display_template_render_error()` - Detailed render error display
-   - `display_warning_with_confirmation()` - Interactive warning prompts
-
-4. **TableDisplayManager** - Handles table rendering
-   - `render_templates_table()` - Templates list with library indicators
-   - `render_status_table()` - Status tables with success/error indicators
-   - `render_config_tree()` - Configuration tree visualization
-
-**Usage Pattern:**
-```python
-# External code uses DisplayManager methods (backward compatible)
-display = DisplayManager()
-display.display_template(template, template_id)
-
-# Internally, DisplayManager delegates to specialized managers
-# display.templates.render_template(template, template_id)
-```
-
-**Design Principles:**
-- External code calls `DisplayManager` methods only
-- `DisplayManager` delegates to specialized managers internally
-- Each specialized manager has a single, focused responsibility
-- Backward compatibility maintained through delegation methods
-- All managers can access parent DisplayManager via `self.parent`
-
-## Templates
-
-Templates are directory-based. Each template is a directory containing all the necessary files and subdirectories for the boilerplate.
-
-### Template Rendering Flow
-
-**How templates are loaded and rendered:**
-
-1. **Discovery**: LibraryManager finds template directories containing `template.json`
-2. **Parsing**: Template class loads and parses the template metadata and spec
-5. **Variable Merging**: Template spec overrides are merged with module spec (precedence: module < template < user config < CLI)
-6. **Collection Building**: VariableCollection is constructed with merged variables and sections
-7. **Dependency Resolution**: Sections are topologically sorted based on `needs` constraints
-8. **Variable Resolution**: Variables with `needs` constraints are evaluated for visibility
-9. **Jinja2 Rendering**: Template files (`.j2`) are rendered with final variable values
-10. **Sanitization**: Rendered output is cleaned (whitespace, blank lines, trailing newline)
-11. **Validation**: Optional semantic validation (YAML structure, Docker Compose config, etc.)
-
-**Key Architecture Points:**
-- Variable visibility is dynamic based on `needs` constraints (evaluated at prompt/render time)
-- Jinja2 templates support `{% include %}` and `{% import %}` for composition
-- Template loading can read configured libraries from disk, but the checked-in `library/` tree in this repo is legacy compatibility data, not the canonical `0.2.0+` library source
-
-### Template Structure
-
-Requires `template.json` with metadata and variables:
-
-```json
-{
-  "slug": "my-service",
-  "kind": "compose",
-  "metadata": {
-    "name": "My Service Template",
-    "description": "A template for a service.",
-    "author": "Your Name",
-    "date": "2024-01-01",
-    "version": {
-      "name": "v1.0.0"
-    }
-  },
-  "variables": [
-    {
-      "name": "general",
-      "title": "General",
-      "items": [
-        {
-          "name": "service_name",
-          "type": "str",
-          "title": "Service name"
-        }
-      ]
-    }
-  ]
-}
-```
+## Documentation
 
-### Template Metadata Versioning
+Project documentation lives in `docs/`.
 
-**Template Version Field:**
-The `metadata.version` field in `template.json` is a structured object and may be partial:
-- `name`
-- `source_dep_name`
-- `source_dep_version`
-- `source_dep_digest`
-- `upstream_ref`
-- `notes`
+Agents should read the relevant docs before making changes and update docs when behavior, configuration, or workflows change.
 
-**Rationale:** This separates the user-facing template version label from the tracked upstream dependency metadata used by the template snapshot.
+### Documentation map
 
-**Application Version Variables:**
-- **IMPORTANT**: Application/image versions should be **hardcoded** in template files (e.g., `image: nginx:1.25.3`)
-- Do NOT create template variables for application versions (e.g., no `nginx_version` variable)
-- Users should update the template file directly when they need a different version
-- This prevents version mismatches and ensures templates are tested with specific, known versions
-- Exception: Only create version variables if there's a strong technical reason (e.g., multi-component version pinning)
-
-
-
-
-```json
-{
-  "slug": "my-template",
-  "kind": "compose",
-  "metadata": {
-    "name": "My Template",
-    "version": {
-      "name": "v1.0.0"
-    }
-  },
-  "variables": [
-    {
-      "name": "general",
-      "title": "General",
-      "items": []
-    }
-  ]
-}
-```
-
-**How It Works:**
-
-**Behavior:**
-- Older templates work with newer module versions (backward compatibility)
-- Version comparison uses MAJOR.MINOR format (e.g., "1.0" < "1.2" < "2.0")
-
-**When to Use:**
-
-**Single-File Module Example:**
-```python
-class SimpleModule(Module):
-  name = "simple"
-  description = "Simple module"
-  spec = VariableCollection.from_dict({...})  # Single spec
-```
-
-```python
-# cli/modules/modulename/__init__.py
-class ExampleModule(Module):
-  name = "modulename"
-  description = "Module description"
-  
-    # Dynamically load the appropriate spec version
-    spec_module = importlib.import_module(f".{version_file}", package=__package__)
-    return spec_module.get_spec()
-```
-
-**Version Management:**
-- CLI version is defined in `cli/__init__.py` as `__version__`
-- pyproject.toml version must match `__version__` for releases
-- GitHub release workflow validates version consistency
-
-### Template Files
-
-- **Jinja2 Templates (`.j2`)**: Rendered by Jinja2, `.j2` extension removed in output. Support `{% include %}` and `{% import %}`.
-- **Static Files**: Non-`.j2` files copied as-is.
-- **Sanitization**: Auto-sanitized (single blank lines, no leading blanks, trimmed whitespace, single trailing newline).
-- **Shortcodes**: Template descriptions support emoji-style shortcodes (e.g., `:warning:`, `:info:`, `:docker:`) which are automatically replaced with Nerd Font icons during display. Add new shortcodes to `IconManager.SHORTCODES` dict.
-
-### Docker Compose Best Practices
-
-**Traefik Integration:**
-
-When using Traefik with Docker Compose, the `traefik.docker.network` label is **CRITICAL** for stacks with multiple networks. When containers are connected to multiple networks, Traefik must know which network to use for routing.
-
-**Implementation:**
-- Review `archetypes/compose/` directory for reference implementations of Traefik integration patterns
-- The `traefik.docker.network={{ traefik_network }}` label must be present in both standard `labels:` and `deploy.labels:` sections
-- Standard mode and Swarm mode require different label configurations - check archetypes for examples
-
-### Variables
-
-**How Templates Inherit Variables:**
-
-
-**When to Define Template Variables:**
-
-You only need to define variables in your template's `spec` section when:
-1. **Overriding defaults**: Change default values for module variables (e.g., hardcode `service_name` for your specific app)
-
-**Variable Precedence** (lowest to highest):
-1. Module `spec` (defaults for all templates of that kind)
-2. Template `spec` (overrides module defaults)
-3. User `config.yaml` (overrides template and module defaults)
-4. CLI `--var` (highest priority)
-
-**Template Variable Override Rules:**
-- **Override module defaults**: Only specify properties that differ from module spec (e.g., change `default` value)
-- **Create new variables**: Define template-specific variables not in module spec
-- **Minimize duplication**: Do NOT re-specify `type`, `description`, or other properties if they remain unchanged from module spec
-
-**Example:**
-```yaml
-# Template spec ONLY needs to override specific defaults:
-spec:
-  general:
-    vars:
-      service_name:
-        default: whoami  # Only override the default, type already defined in module
-```
-
-**Variable Types:**
-- `str` (default), `int`, `float`, `bool`
-- `email` - Email validation with regex
-- `url` - URL validation (requires scheme and host)
-- `hostname` - Hostname/domain validation
-- `enum` - Choice from `options` list
-
-**Variable Properties:**
-- `sensitive: true` - Masked in prompts/display (e.g., passwords)
-- `autogenerated: true` - Auto-generates value if empty (shows `*auto` placeholder)
-- `default` - Default value
-- `description` - Variable description
-- `prompt` - Custom prompt text (overrides description)
-- `extra` - Additional help text
-- `options` - List of valid values (for enum type)
-
-**Section Features:**
-- **Toggle Settings**: Conditional sections via `toggle: "bool_var_name"`. If false, section is skipped.
-  - **IMPORTANT**: When a section has `toggle: "var_name"`, that boolean variable is AUTO-CREATED by the system
-  - Example: `ports` section with `toggle: "ports_enabled"` automatically provides `ports_enabled` boolean
-- **Dependencies**: Use `needs: "section_name"` or `needs: ["sec1", "sec2"]`. Dependent sections only shown when dependencies are enabled.
-
-**Dependency Resolution Architecture:**
-
-Sections and variables support `needs` constraints to control visibility based on other variables.
-
-**Section-Level Dependencies:**
-- Format: `needs: "section_name"` or `needs: ["sec1", "sec2"]`
-- Section only appears when all required sections are enabled (their toggle variables are true)
-- Automatically validated: detects circular, missing, and self-dependencies
-- Topologically sorted: ensures dependencies are prompted/processed before dependents
-
-**Variable-Level Dependencies:**
-- Format: `needs: "var_name=value"` or `needs: "var1=val1;var2=val2"` (semicolon-separated)
-- Variable only visible when constraint is satisfied (e.g., `needs: "network_mode=bridge"`)
-- Supports multiple values: `needs: "network_mode=bridge,macvlan"` (comma = OR)
-- Evaluated dynamically at prompt and render time
-
-**Validation:**
-- Circular dependencies: Raises error if A needs B and B needs A
-- Missing dependencies: Raises error if referencing non-existent sections/variables
-- Self-dependencies: Raises error if section depends on itself
-
-**Example Section with Dependencies:**
-
-```yaml
-spec:
-  traefik:
-    title: Traefik
-    required: false
-    toggle: traefik_enabled
-    vars:
-      traefik_enabled:
-        type: bool
-        default: false
-      traefik_host:
-        type: hostname
-  
-  traefik_tls:
-    title: Traefik TLS/SSL
-    needs: traefik
-    toggle: traefik_tls_enabled
-    vars:
-      traefik_tls_enabled:
-        type: bool
-        default: true
-      traefik_tls_certresolver:
-        type: str
-        sensitive: false
-        default: myresolver
-```
+- `docs/architecture.md` - repository layout, module system, and core runtime components
+- `docs/templates.md` - template format, variables, rendering, and validation behavior
+- `docs/libraries.md` - library configuration and canonical external template library guidance
+- `docs/display.md` - DisplayManager and CLI output rules
 
 ## Validation
 
-**Jinja2 Validation:**
-- Templates validated for Jinja2 syntax errors during load
-- Checks for undefined variables (variables used but not declared in spec)
-- Built into Template class
-
-**Semantic Validation:**
-- Validator registry system in `cli/core/validators.py`
-- Extensible: `ContentValidator` abstract base class
-- Built-in validators: `DockerComposeValidator`, `YAMLValidator`
-- Validates rendered output (YAML structure, Docker Compose config, etc.)
-- Triggered via `compose validate` command with `--semantic` flag (enabled by default)
-
-## Prompt
-
-Uses `rich` library for interactive prompts. Supports:
-- Text input
-- Password input (masked, for `sensitive: true` variables)
-- Selection from list (single/multiple)
-- Confirmation (yes/no)
-- Default values
-- Autogenerated variables (show `*auto` placeholder, generate on render)
-
-To skip the prompt use the `--no-interactive` flag, which will use defaults or empty values.
-
-## Commands
-
-**Standard Module Commands** (auto-registered for all modules):
-- `list` - List all templates
-- `search <query>` - Search templates by ID
-- `show <id>` - Show template details
-- `generate <id> -o <directory>` - Generate from template (supports `--dry-run`, `--var`, `--no-interactive`)
-- `validate [template_id]` - Validate template(s) (Jinja2 + semantic). Omit template_id to validate all templates
-- `defaults` - Manage config defaults (`get`, `set`, `rm`, `clear`, `list`)
-
-**Core Commands:**
-- `repo sync` - Sync git-based libraries
-- `repo list` - List configured libraries
-
-## Archetypes
-
-The `archetypes` package provides reusable, standardized template building blocks for creating boilerplates. Archetypes are modular Jinja2 snippets that represent specific configuration sections.
-
-### Purpose
-
-1. **Template Development**: Provide standardized, tested building blocks for creating new templates
-2. **Testing & Validation**: Enable testing of specific configuration sections in isolation with different variable combinations
-
-### Usage
-
-```bash
-# List available archetypes for a module
-python3 -m archetypes compose list
-
-# Preview an archetype component
-python3 -m archetypes compose generate <archetype-name>
-
-# Test with variable overrides
-python3 -m archetypes compose generate <archetype-name> \
-  --var traefik_enabled=true \
-  --var swarm_enabled=true
-
-# Validate templates against archetypes
-python3 -m archetypes compose validate            # All templates
-python3 -m archetypes compose validate <template> # Single template
-```
-
-### Archetype Validation
-
-The `validate` command compares templates against archetypes to measure coverage and identify which archetype patterns are being used.
-
-**What it does:**
-- Compares each template file against all available archetypes using **structural pattern matching**
-- Abstracts away specific values to focus on:
-  - **Jinja2 control flow**: `{% if %}`, `{% elif %}`, `{% else %}`, `{% for %}` structures
-  - **YAML structure**: Key names, indentation, and nesting patterns
-  - **Variable usage patterns**: Presence of `{{ }}` placeholders (not specific names)
-  - **Wildcard placeholders**: `__ANY__`, `__ANYSTR__`, `__ANYINT__`, `__ANYBOOL__`
-  - **Repeat markers**: `{# @repeat-start #}` / `{# @repeat-end #}`
-  - **Optional markers**: `{# @optional-start #}` / `{# @optional-end #}`
-- This allows detection of archetypes even when specific values differ (e.g., `grafana_data` vs `alloy_data`)
-- Calculates **containment ratio**: what percentage of each archetype structure is found within the template
-- Reports usage status: **exact** (≥95%), **high** (≥70%), **partial** (≥30%), or **none** (<30%)
-- Provides coverage metrics: (exact + high matches) / total archetypes
-
-### Advanced Pattern Matching in Archetypes
-
-Archetypes support special annotations for flexible pattern matching:
-
-**Wildcard Placeholders** (match any value):
-- `__ANY__` - Matches anything
-- `__ANYSTR__` - Matches any string
-- `__ANYINT__` - Matches any integer
-- `__ANYBOOL__` - Matches any boolean
-
-**Repeat Markers** (pattern can appear 1+ times):
-```yaml
-{# @repeat-start #}
-  pattern
-{# @repeat-end #}
-```
-
-**Optional Markers** (section may or may not exist):
-```yaml
-{# @optional-start #}
-  pattern
-{# @optional-end #}
-```
+Default checks before finishing code changes:
 
-**Example:**
-```yaml
-volumes:
-  {# @repeat-start #}
-  __ANY__:
-    driver: local
-  {# @repeat-end #}
-```
-Matches any number of volumes with `driver: local`
-
-**Usage:**
 ```bash
-# Validate all templates in library - shows summary table
-python3 -m archetypes compose validate
-
-# Validate specific template - shows detailed archetype breakdown
-python3 -m archetypes compose validate whoami
-
-# Validate templates in custom location
-python3 -m archetypes compose validate --library /path/to/templates
+ruff check --fix .
+ruff format .
+python3 -m pytest
 ```
 
-**Output:**
-- **Summary mode** (all templates): Table showing exact/high/partial/none counts and coverage % per template
-- **Detail mode** (single template): Table showing each archetype's status, similarity %, and matching file
-
-**Use cases:**
-- **Quality assurance**: Ensure templates follow established patterns
-- **Refactoring**: Identify templates that could benefit from archetype alignment
-- **Documentation**: Track which archetypes are most/least used across templates
-
-### Template Development Workflow
-
-1. **Discover**: Use `list` command to see available archetype components for your module
-2. **Review**: Preview archetypes to understand implementation patterns
-3. **Copy**: Copy relevant archetype components to your template directory
-4. **Customize**: Modify as needed (hardcode image, add custom labels, etc.)
-5. **Validate**: Use `compose validate` to check Jinja2 syntax and semantic correctness
-
-### Architecture
+See `CONTRIBUTING.md` for setup and workflow details.
 
-**Key Concepts:**
-- Each module can have its own `archetypes/<module>/` directory with reusable components
-- Components are modular Jinja2 files that can be tested in isolation or composition
-- **Testing only**: The `generate` command NEVER writes files - always shows preview output
+## Project conventions
 
-**How it works:**
-- Merges variable sources: module spec → archetypes.yaml → CLI --var
-- Renders using Jinja2 with support for `{% include %}` directives
+- Follow existing project structure, naming, and patterns before introducing new ones.
+- Keep changes focused on the requested task; avoid unrelated refactors or broad rewrites.
+- When adding or changing behavior, update relevant docs and tests where practical.
+- Do not commit secrets, tokens, private keys, or environment-specific credentials.
+- Use custom exceptions from `cli/core/exceptions.py` for user-facing errors where applicable.
+- Use `DisplayManager` for user-facing command output; never print directly from command, module, config, repository, validation, or template-rendering code. See `docs/display.md`.
+- Do not treat `library/` as the canonical source for current template work. For `0.2.0+`, active templates live in the separate `boilerplates-library` repository. See `docs/libraries.md`.
+- When answering which template kinds are supported, prefer registered modules in `cli/modules/` over legacy library contents.

+ 64 - 0
CONTRIBUTING.md

@@ -0,0 +1,64 @@
+# Contributing
+
+## Local setup
+
+```bash
+python3 -m venv .venv
+source .venv/bin/activate
+python3 -m pip install --upgrade pip
+python3 -m pip install -e ".[test]" ruff
+```
+
+## Running the CLI
+
+```bash
+python3 -m cli
+python3 -m cli --log-level DEBUG compose list
+```
+
+## Validation gates
+
+Run the relevant checks before finishing changes. These are release gates, not optional cleanup.
+
+```bash
+ruff check --fix .
+ruff format .
+python3 -m pytest
+```
+
+If `ruff` is not installed in the active environment, install it before running the gates.
+
+For production-like boilerplate testing before a release, see `WARP-LOCAL.md` if it exists locally. It is intentionally not tracked in git and may describe local Docker contexts, test servers, and release-readiness checklists.
+
+## GitHub workflow
+
+This repository uses GitHub issues, branches, pull requests, and releases.
+
+Before GitHub-facing work such as issues, branches, PRs, merges, tags, or releases, read:
+
+- `AGENTS.md`
+- this contribution guide
+- `RELEASE.md` for release-related work
+
+## Naming conventions
+
+- Branches and PRs: `feature/2314-add-feature`, `problem/1249-fix-bug`, `release/x.x.x`
+- Commit messages: `type(scope): subject`, for example `fix(compose): correct variable parsing`
+- Issues should have clear titles and descriptions, link related issues/PRs, and use appropriate labels such as `problem`, `feature`, `discussion`, or `question`.
+
+## Standard commands
+
+Standard module commands are auto-registered for all modules:
+
+- `list` - list templates
+- `search <query>` - search templates by ID
+- `show <id>` - show template details
+- `generate <id>` - generate from a template; supports `--dry-run`, `--var`, `--var-file`, `--no-interactive`, and destination options
+- `validate [template_id]` - validate one or all templates
+- `defaults` - manage config defaults with `get`, `set`, `rm`, `clear`, and `list`
+
+Core repository commands include:
+
+- `repo update` - sync git-based libraries
+- `repo list` - list configured libraries
+- `repo add` / `repo remove` - manage configured libraries

+ 131 - 0
RELEASE.md

@@ -0,0 +1,131 @@
+# Release Process
+
+## Overview
+
+Releases are prepared through a release PR and published by pushing a version tag. The GitHub Actions release workflow runs on tags matching `v*.*.*`.
+
+The release PR should be limited to release preparation changes whenever possible: version files and changelog updates.
+
+## Version files
+
+The release version must match in all of these places:
+
+- `pyproject.toml`
+- `cli/__init__.py`
+- Git tag, e.g. `vx.x.x`
+
+The release workflow validates this and fails if they differ.
+
+## Prepare a release
+
+1. Start from an updated `main` branch.
+
+   ```bash
+   git checkout main
+   git pull origin main
+   git checkout -b release/x.x.x
+   ```
+
+2. Update version files if needed.
+
+   ```toml
+   # pyproject.toml
+   version = "x.x.x"
+   ```
+
+   ```python
+   # cli/__init__.py
+   __version__ = "x.x.x"
+   ```
+
+3. Finalize `CHANGELOG.md`.
+
+   Move entries from:
+
+   ```md
+   ## [Unreleased]
+   ```
+
+   to:
+
+   ```md
+   ## [x.x.x] - YYYY-MM-DD
+   ```
+
+   Then add a fresh empty section above it:
+
+   ```md
+   ## [Unreleased]
+   ```
+
+4. Run release gates.
+
+   ```bash
+   ruff check --fix .
+   ruff format .
+   python3 -m pytest
+   cubic review -j
+   ```
+
+5. Commit and push.
+
+   ```bash
+   git add pyproject.toml cli/__init__.py CHANGELOG.md
+   git commit -m "release: prepare vx.x.x"
+   git push -u origin release/x.x.x
+   ```
+
+6. Open a PR into `main`.
+
+   PR title:
+
+   ```text
+   release: prepare vx.x.x
+   ```
+
+7. Merge the release PR after checks and review pass.
+
+## Publish the release
+
+After the release PR is merged:
+
+```bash
+git checkout main
+git pull origin main
+git tag vx.x.x
+git push origin vx.x.x
+```
+
+Pushing the tag triggers `.github/workflows/release-create-cli-release.yaml`.
+
+The workflow will:
+
+- validate version consistency
+- build the Python package
+- run package checks
+- create the GitHub Release
+- attach `.whl` and `.tar.gz` assets
+- use the matching changelog section as release notes
+
+## Hotfix releases
+
+For hotfix/post releases, use the repository's existing tag format:
+
+```text
+vx.x.x-n
+```
+
+The release workflow creates package-compatible asset aliases for these versions.
+
+## After release
+
+Verify that:
+
+- the GitHub Release exists
+- release assets are attached
+- the installer can install the release
+
+```bash
+curl -fsSL https://raw.githubusercontent.com/christianlempa/boilerplates/main/scripts/install.sh |
+  bash -s -- --version vx.x.x
+```

+ 93 - 0
docs/architecture.md

@@ -0,0 +1,93 @@
+# Architecture Notes
+
+## Repository layout
+
+- `cli/` - Python CLI application source code
+  - `cli/core/` - core runtime packages
+  - `cli/modules/` - technology-specific module registrations
+  - `cli/__main__.py` - CLI entry point; discovers modules and registers commands
+- `tests/` - automated tests
+- `docs/` - developer documentation
+- `scripts/` - helper scripts, including installer tooling
+- `library/` - legacy in-repo template content for versions older than `0.2.0`; do not treat it as the canonical template library for modern work
+- `.github/` - workflows, templates, and repository automation
+
+## Supported kinds
+
+The supported kinds are the registered modules in `cli/modules/`. Prefer this code-level list over legacy content in `library/`.
+
+Current kinds:
+
+- `ansible`
+- `bash`
+- `compose`
+- `helm`
+- `kubernetes`
+- `packer`
+- `python`
+- `static`
+- `swarm`
+- `terraform`
+
+## Module system
+
+Modules subclass `Module` from `cli/core/module/` and register themselves with the central registry.
+
+Minimal module example:
+
+```python
+from ...core.module import Module
+from ...core.registry import registry
+
+
+class ExampleModule(Module):
+    name = "example"
+    description = "Manage example templates"
+
+
+registry.register(ExampleModule)
+```
+
+Discovery and registration flow:
+
+1. `cli/__main__.py` imports module packages/files from `cli/modules/`.
+2. Each module calls `registry.register(ModuleClass)` at import time.
+3. The registry stores module classes by module name.
+4. The CLI framework creates standard commands for every registered module.
+5. Modules are instantiated on demand when commands run.
+
+Benefits:
+
+- No central manual registration for new kinds
+- Modules are self-contained
+- Registry validation catches invalid module classes early
+
+## Core components
+
+Important packages/files:
+
+- `cli/core/module/` - base module class and standard command implementations
+- `cli/core/template/` - template manifest parsing, variable normalization, rendering, and validation
+- `cli/core/config/` - user configuration loading, saving, validation, and migration
+- `cli/core/library.py` - template discovery across git/static libraries
+- `cli/core/repo.py` - repository/library management commands
+- `cli/core/registry.py` - module registry
+- `cli/core/display/` - centralized CLI output rendering; see `docs/display.md`
+- `cli/core/validation/` - dependency matrix and kind-specific rendered-file validators
+- `cli/core/validators.py` - generic content validators such as YAML and Docker Compose validation
+- `cli/core/exceptions.py` - custom exceptions; prefer these for user-facing errors
+
+## Prompt/input flow
+
+Interactive prompting is implemented with Rich-based input helpers under `cli/core/input/`.
+
+Prompt support includes:
+
+- text input
+- password/secret input
+- yes/no confirmation
+- numbered choice selection
+- defaults from template/config/CLI sources
+- autogenerated secret placeholders
+
+Use `--no-interactive` to skip prompts and use defaults, config values, CLI overrides, or empty values as appropriate.

+ 56 - 0
docs/display.md

@@ -0,0 +1,56 @@
+# Display and Output Rules
+
+## Critical rule
+
+User-facing command output should go through `DisplayManager` or one of the display classes under `cli/core/display/`.
+
+Do not:
+
+- call `console.print()` from command, module, config, repository, validation, or template-rendering code
+- import `Console` from `rich.console` for general command output outside display classes or `cli/__main__.py`
+- use direct emojis or icons in feature code
+- bypass display helpers for status, errors, warnings, tables, or template output
+
+Do:
+
+- use `module_instance.display` in module/command code
+- use `DisplayManager()` when standalone core command code needs output
+- add or adjust display helpers in `cli/core/display/` when new output patterns are needed
+- add shortcode/icon mappings in the display/icon layer
+
+## Rationale
+
+Centralized display handling keeps CLI output consistent and makes it easier to manage:
+
+- formatting standards
+- quiet/verbose behavior
+- stderr/stdout routing
+- icon and Nerd Font usage
+- table rendering
+- error/warning/success styles
+
+## Display architecture
+
+`DisplayManager` acts as a facade over focused display components.
+
+Current responsibilities include:
+
+- variable rendering and variable tables
+- template metadata and file-tree rendering
+- status, error, warning, success, and info messages
+- data/status/config tables
+- markdown/description rendering
+
+External code should call facade methods on `DisplayManager`. Internally, the facade delegates to specialized display classes.
+
+Example:
+
+```python
+display = DisplayManager()
+display.success("Template generated")
+display.error("Validation failed", details="Missing variable")
+```
+
+If a needed display method does not exist, add one to the display layer instead of printing directly from feature code.
+
+Prompt/input internals under `cli/core/input/` may use Rich prompt primitives directly when implementing interactive input behavior. Keep regular command output in the display layer.

+ 109 - 0
docs/libraries.md

@@ -0,0 +1,109 @@
+# Library and Configuration Notes
+
+## Canonical template library
+
+The canonical template library does **not** live in this repository for modern development.
+
+- The checked-in `library/` directory is legacy/backward-compatibility content for versions older than `0.2.0`.
+- For `0.2.0+`, active template work belongs in the separate GitHub repository `boilerplates-library`.
+
+When answering questions about supported kinds or current template behavior, prefer code under `cli/modules/` and runtime logic under `cli/core/` over legacy `library/` content.
+
+## LibraryManager
+
+`LibraryManager` loads configured libraries and discovers templates by kind.
+
+Responsibilities:
+
+- load library configuration
+- resolve git and static library paths
+- discover template directories containing `template.json`
+- normalize template IDs from manifest slugs
+- handle duplicate template IDs
+- preserve library priority order
+
+Git libraries are stored under:
+
+```text
+~/.config/boilerplates/libraries/{name}/
+```
+
+Git-based libraries use sparse checkout to avoid cloning unrelated repository content where possible.
+
+## Library types
+
+### Git libraries
+
+Git libraries require:
+
+- `name`
+- `type: git`
+- `url`
+- `branch`
+- `directory`
+
+### Static libraries
+
+Static libraries require:
+
+- `name`
+- `type: static`
+- `path`
+
+Static library paths may be absolute or relative to the config file location. Some config entries may include backward-compatible dummy `url`, `branch`, and `directory` fields.
+
+## Priority and duplicate handling
+
+Library priority is determined by config order. Earlier entries have higher priority.
+
+Duplicate behavior:
+
+- duplicate IDs within the same library raise a duplicate-template error
+- duplicate IDs across libraries can be addressed with qualified IDs
+- simple IDs resolve to the highest-priority library
+- qualified IDs target a specific library, for example `alloy.default` or `alloy.local`
+
+Example:
+
+```bash
+boilerplates compose show alloy
+boilerplates compose show alloy.local
+```
+
+## Config location
+
+User config is stored at:
+
+```text
+~/.config/boilerplates/config.yaml
+```
+
+Example library config:
+
+```yaml
+libraries:
+  - name: default
+    type: git
+    url: https://github.com/user/templates.git
+    branch: main
+    directory: library
+  - name: local
+    type: static
+    path: ~/my-templates
+    url: ''
+    branch: main
+    directory: .
+```
+
+## Repository commands
+
+Common library commands:
+
+```bash
+boilerplates repo list
+boilerplates repo update
+boilerplates repo add local --type static --path ~/my-templates
+boilerplates repo remove local
+```
+
+Use `DisplayManager` for all output in repository/config code. Do not print directly.

+ 157 - 0
docs/templates.md

@@ -0,0 +1,157 @@
+# Template Authoring Notes
+
+Templates are directory-based. Each template directory contains `template.json` plus a required `files/` directory with renderable content.
+
+## Template loading and rendering flow
+
+1. `LibraryManager` finds template directories containing `template.json`.
+2. `Template` loads and validates manifest metadata.
+3. Manifest variables are normalized into the runtime variable collection shape.
+4. Defaults are merged from template, user config, var-files, and CLI overrides.
+5. Sections are sorted and dependency constraints are validated.
+6. Variables are resolved dynamically according to `needs` constraints.
+7. Files under `files/` render through the custom-delimiter Jinja environment.
+8. Rendered output is sanitized.
+9. Optional semantic or kind-specific validation runs.
+
+## Template structure
+
+Minimal `template.json` shape:
+
+```json
+{
+  "slug": "my-template",
+  "kind": "compose",
+  "metadata": {
+    "name": "My Template",
+    "description": "A template description.",
+    "version": {
+      "name": "v1.0.0"
+    }
+  },
+  "variables": [
+    {
+      "name": "general",
+      "title": "General",
+      "items": [
+        {
+          "name": "service_name",
+          "type": "str",
+          "title": "Service name",
+          "default": "demo"
+        }
+      ]
+    }
+  ]
+}
+```
+
+## Template delimiters
+
+For `0.2.0+`, templates use custom Jinja-like delimiters:
+
+- Variables: `<< variable_name >>`
+- Blocks: `<% if condition %> ... <% endif %>`
+- Comments: `<# comment #>`
+
+Default Jinja delimiters such as `{{ variable }}` are intentionally left untouched so downstream tools like Ansible can use them literally.
+
+Legacy `.j2` behavior is no longer supported for new `template.json` templates. Renderable content lives under `files/`, and output paths match the relative paths under `files/`.
+
+## Metadata versioning
+
+`metadata.version` is a structured object and may be partial. Supported fields include:
+
+- `name`
+- `source_dep_name`
+- `source_dep_version`
+- `source_dep_digest`
+- `upstream_ref`
+- `notes`
+
+This separates the user-facing template version label from tracked upstream dependency metadata.
+
+## Application versions
+
+Application/image versions should generally be hardcoded in template files, for example:
+
+```yaml
+image: nginx:1.25.3
+```
+
+Do not create variables such as `nginx_version` unless there is a strong technical reason, such as multi-component version pinning. Hardcoding tested versions avoids mismatches between variables and validated template output.
+
+## Variables
+
+Variable precedence, lowest to highest:
+
+1. Template defaults from `template.json`
+2. User config defaults
+3. Var-file values
+4. CLI `--var` overrides
+
+Variable types:
+
+- `str`
+- `int`
+- `float`
+- `bool`
+- `email`
+- `url`
+- `hostname`
+- `enum`
+- `secret`
+
+Common variable properties:
+
+- `default` - default value
+- `title` - prompt/display title
+- `description` - description/help text
+- `required` - require non-empty value
+- `needs` - conditional visibility constraint
+- `config.options` - enum options
+- `config.placeholder` - input placeholder
+- `config.autogenerated` - secret autogeneration settings
+
+## Sections and dependencies
+
+Variable groups become sections. Sections can define:
+
+- `toggle` - auto-created boolean variable that enables/disables the section
+- `needs` - section dependency by section key
+
+Variable-level `needs` constraints use this format:
+
+- `var_name=value`
+- `var_name!=value`
+- `var1=value1;var2=value2`
+- `network_mode=bridge,macvlan` where comma means OR
+
+Dependency validation detects missing dependencies, circular dependencies, and self-dependencies.
+
+## Validation
+
+Template validation includes:
+
+- manifest shape validation
+- custom-delimiter Jinja syntax validation
+- undeclared variable detection
+- rendering validation
+
+Generic semantic validation is provided by `cli/core/validators.py`, including YAML and Docker Compose-oriented checks where applicable.
+
+Kind-specific validation lives under `cli/core/validation/` and can be enabled with module validation options such as `--kind` or matrix validation where supported.
+
+## Docker Compose notes
+
+When using Traefik with Docker Compose and multiple networks, include the Traefik network label so Traefik routes through the intended network:
+
+```yaml
+traefik.docker.network: << traefik_network >>
+```
+
+For Swarm/Compose-specific label placement, follow existing template patterns before introducing new ones.
+
+## Shortcodes
+
+Template descriptions may use emoji-style shortcodes such as `:warning:`, `:info:`, or `:docker:`. Display code maps these to Nerd Font icons. Add new shortcodes in the display/icon layer, not directly in template rendering code.