# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Envoke is a CLI tool that resolves environment variables from a declarative YAML configuration file (`envoke.yaml`). It supports multiple value sources (literal, command execution, shell scripts, Jinja2 templates with variable interpolation), tag-based conditional inclusion, named overrides for per-variable source alternatives, topologically sorts variables to resolve dependencies, and outputs shell-safe `VAR='value'` lines.

## Build & Development Commands

This project uses `mise` as a task runner. Install mise first, then tools via `mise install`.

| Task | Command |
|------|---------|
| Build (release) | `mise run build` |
| Run tests | `mise run test` |
| Format code | `mise run fmt` |
| Format check | `mise run fmt:check` |
| Lint | `mise run clippy` |
| All CI checks | `mise run ci` |
| Install locally | `mise run install` |

Run a single test: `cargo nextest run -E 'test(test_name)'`

Formatting uses nightly features (`rustfmt.toml` has `style_edition = "2024"`). Use `mise run fmt:nightly` / `mise run fmt:check:nightly` when stable rustfmt doesn't support the options.

## Architecture

The codebase is a single Rust binary with four modules:

- **`main.rs`** -- CLI (clap), reads YAML config, orchestrates resolution, delegates output formatting to `render.rs`. Supports `--output` file writing, `--prepend-export`, `--template` (custom output template), `--tag` (conditional inclusion), `--override` (per-variable source overrides), `--schema` (JSON Schema output), and `--completions` (shell completions via `clap_complete`).
- **`config.rs`** -- Data model: `Config` (top-level), `Variable` (per-env sources + optional default/description/tags/overrides), `Override` (alternative default/envs sources), `Source` enum (literal/cmd/sh/template/skip). Derives `JsonSchema` via `schemars`.
- **`resolve.rs`** -- Core logic. `resolve_all()` picks per-environment sources (with default fallback and override 4-level fallback chain), topologically sorts via Kahn's algorithm, resolves values in dependency order. Template rendering uses `minijinja` with all built-in filters, `urlencode`, and `shell_escape` (imported from `render.rs`). A `TemplateMeta` struct provides a `meta` object (with `environment`, `tags`, `overrides`, `timestamp`) to value source templates. Contains the test suite (~46 tests).
- **`render.rs`** -- Output rendering via minijinja templates. Exposes `RenderContext`/`Meta` structs (Meta includes `timestamp`, `invocation`, `invocation_args`, `environment`, `config_file`, `tags`, `overrides`), built-in default and export templates (compiled via `include_str!`), custom template file support, and a `pub(crate) shell_escape` filter (shared with `resolve.rs`). All filters (built-ins, `urlencode`, `shell_escape`) are available in both variable and output templates. Built-in templates live in `src/templates/`.
- **`error.rs`** -- `ResolveError` with structured `ResolveErrorKind` variants (8 types including cycle detection with chain and conflicting overrides).

## Code Style

- Clippy pedantic lints are enabled as warnings (`[lints.clippy] pedantic = "warn"`)
- Rustfmt: `imports_granularity = "Item"`, `group_imports = "StdExternalCrate"`, Unix newlines
- Rust edition 2024
