https://github.com/lnrdll/ymr
Lightweight, spec-driven YAML template tool
https://github.com/lnrdll/ymr
cli go go-cli golang template template-engine yaml yaml-configuration
Last synced: about 1 month ago
JSON representation
Lightweight, spec-driven YAML template tool
- Host: GitHub
- URL: https://github.com/lnrdll/ymr
- Owner: lnrdll
- License: mit
- Created: 2025-11-06T20:00:31.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-02-21T22:02:16.000Z (about 2 months ago)
- Last Synced: 2026-02-22T01:22:50.074Z (about 2 months ago)
- Topics: cli, go, go-cli, golang, template, template-engine, yaml, yaml-configuration
- Language: Go
- Homepage:
- Size: 4.62 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
ymr (pronounced ya·mr) is a lightweight, spec-driven command-line tool to generate YAML files from templates. It’s ideal for managing configuration across multiple environments or targets by replacing placeholders in your YAML templates with values defined in a central spec file.
---
**TOC**
- [Why?](#why)
- [How it Works](#how-it-works)
- [Agent Notes](#agent-notes)
- [Spec-less Mode](#spec-less-mode)
- [Installation](#installation)
- [Development](#development)
- [Usage](#usage)
- [Template Syntax](#template-syntax)
- [Examples](#examples)
- [Contributing](#contributing)
- [License](#license)
---
Existing YAML templating tools — such as `jtt`, `Helm`, `Kustomize`, or `Kluctl` — are powerful and versatile, but they often come with a steep learning curve and impose specific formatting or structural requirements on your YAML files.
`ymr` takes a simpler, more flexible approach. You simply add comments to your existing YAML configuration, and if they match your defined specifications, `ymr` performs the substitutions keeping the integrity of the YAML file. This means you can use `ymr` with any YAML file, including those already managed by other tools, without modifying your current workflow or file structure, and use any YAML linter you want.
`ymr` processes YAML templates by substituting placeholders with values from your spec.yaml. It supports two main types of placeholders:
- `from-param: {{ .var }}` — replaces the entire value with the parameter `{{ .var }}`.
- `from-param-merge: {{ .var }}` — merges the parameter `{{ .var }}` into the existing YAML structure.
This allows for dynamic, reusable configuration generation — letting you define shared values once and selectively override them for specific environments or targets.
In addition, you can pipe the variables to the following functions:
- `lower`: to set all characters to lower case. Example: `from-param: {{ .var | lower }}`
- `upper`: to set all characters to upper case. Example: `from-param: {{ .var | upper }}`
- `replace`: to do string substitution. Example: `from-param: {{ .var | replace "." "-" }}`
Validations are also available if there is a need to enforce requirements. The policy engine uses the Common Expression Language ([CEL](https://cel.dev/)) and it validates every parameter passed.
If you're using `ymr` from an AI agent / coding assistant, read these first:
- `AGENTS.md`: repo map, architecture, invariants, and quick commands
- `SKILL.md`: agent-oriented usage rules and reliable invocation patterns
`ymr` can be run **without** a `--spec` (`-s`) flag (spec-less mode), which is useful for simple, one-off template rendering. In this mode, you must provide:
- A template file/URL via the `--template` (`-T`) flag.
- At least one parameter source via `--param` (`-p`), `--param-file`, or `--param-yaml`.
This mode is ideal for CI/CD pipelines or simple scripts where a full `spec.yaml` is unnecessary.
#### `go install`
You can install `ymr` using `go install`:
```bash
go install github.com/lnrdll/ymr@latest
```
#### `Mise`
You can install 'ymr' using `Mise`:
```bash
[tools]
"github:lnrdll/ymr" = "latest"
```
Alternatively, you can download the binary from the [releases page](https://github.com/lnrdll/ymr/releases).
#### Build from source
Build for your current platform:
```bash
mkdir -p dist
go build -trimpath -o dist/ymr .
```
Build release-style artifacts for linux/windows/darwin on amd64 and arm64:
```bash
bash scripts/build-all.sh
```
Artifacts are written to `dist/`.
Useful commands when working on `ymr` itself:
```bash
go test ./...
go build -trimpath -o dist/ymr .
# If you use mise (optional)
mise run test
mise run lint
```
Note: `mise` task definitions live in `mise.toml`.
`ymr` provides four commands: `init`, `run`, `validate`, and `version`.
#### `ymr init`
Generates a boilerplate `spec.yaml` file in your current directory. This is a great starting point for new projects.
```bash
ymr init
# Overwrite an existing spec.yaml
ymr init --force
```
Example `spec.yaml` generated by `init`:
```yaml
# A list of templates to process.
# Paths are relative to the location of this spec.yaml.
templates:
- base/service.yaml
- base/configmap.yaml
# A simple list of target environments.
targetIds:
- dev
- prd
# A list of parameter sets.
parameters:
# --- Shared values ---
- targetId: ["dev", "prd"] # Which targets this value set applies to
values:
name: "myapp-name"
# --- Dev-specific values ---
- targetId: ["dev"]
values:
minScale: 1
# --- Prod-specific values ---
- targetId: ["prd"]
values:
minScale: 3
maxScale: 10
```
In addition to the default boilerplate, the `init` command also accepts parameters so the boilerplate can be customized.
```bash
ymr init --templates service.yaml --target dev --target stg -p 'maxScale: 10' -p 'minScale: 1'
```
Custom `spec.yaml` example:
```yaml
# A list of templates to process.
# Paths are relative to the location of this spec.yaml.
templates:
- service.yaml
# A simple list of target environments.
targetIds:
- dev
- stg
# A list of parameter sets.
parameters:
# --- Shared values for all provided targets ---
- targetId:
- dev
- stg
values:
maxScale: 10
minScale: 1
# --- Specific values for target 'dev' ---
- targetId: ["dev"]
values:
foo: bar
# --- Specific values for target 'stg' ---
- targetId: ["stg"]
values:
foo: bar
```
#### `ymr run`
Processes templates based on a `spec.yaml` file and generates output files.
```bash
ymr run [flags]
```
**Flags:**
* `-s`, `--spec `: Source path for `spec.yaml` (local dir/file, http(s) URL, or GitHub). When omitted, `ymr` runs in spec-less mode.
* `-T`, `--template `: A single template file/URL to override the `templates` list in the spec.
* `-o`, `--output `: Output directory for rendered files. Use `-` for stdout.
* `-p`, `--param `: Override a parameter (e.g., `key=value`). Can be used multiple times.
* `--param-file `: Override parameters from a YAML/JSON mapping file (local path or URL). Can be used multiple times.
* `--param-yaml `: Override parameters from an inline YAML/JSON mapping. Can be used multiple times.
* `-t`, `--target `: Override which targets to render. Can be used multiple times.
* `--token `: GitHub token for accessing private repositories (or use `GITHUB_TOKEN` environment variable).
* `--validation `: Path to a policy file. If provided, this will override any validations in the spec file.
* `--strict`: Fail the run if any template/target render step errors. By default, `ymr` runs in best-effort mode and skips failed templates/targets.
* `--debug`: Enable debug logging.
**Example `ymr run` usage:**
```bash
# Spec-less mode
ymr run --template ./example/gcp-cloud-run/service.yaml -p version=111 -o -
# Spec-less mode with a YAML params file
ymr run -T ./example/k8s/deployment.yaml -t dev --param-file ./params.yaml -o -
# Strict mode (fail on any render error)
ymr run -s example/k8s --strict -o -
# Process spec.yaml and output to the 'rendered' directory
ymr run -s spec.yaml -o rendered
# Override a parameter for a specific run
ymr run -s example/gcp-cloud-run -p minScale=5 -o -
# Render only the 'prd' target
ymr run -s example/gcp-cloud-run -t prd -o -
# Use a GitHub repo directly (requires --token or GITHUB_TOKEN env for private repos)
ymr run -s https://github.com/lnrdll/ymr/example/k8s@main -o -
# Run in spec-less mode
ymr run -T https://github.com/lnrdll/ymr/blob/main/example/k8s/deployment.yaml -t dev -p name=example -o -
# Run in spec-less strict mode
ymr run -T ./example/k8s/deployment.yaml -t dev -p name=example --strict -o -
```
Note: In spec-less mode, if you write to files (i.e. `-o rendered/`), you typically want to pass at least one `--target` so output filenames are stable.
#### `ymr validate`
Validates a spec (or a single template in spec-less mode) without writing output files.
```bash
# Validate a spec directory
ymr validate -s example/k8s
# Validate with strict mode (fail on any template load/parse error)
ymr validate -s example/k8s --strict
```
#### `ymr version`
Print the current version (and commit/date when available):
```bash
ymr version
```
`ymr` uses special comments within your YAML templates to identify where parameters should be injected.
Templates may contain multiple YAML documents separated by `---`; `ymr` processes each document.
* `# from-param: {{ .var }}`: Replaces the entire value with the value of the parameter `{{ .var }}`.
**Template:**
```yaml
replicas: 1 # from-param: {{ .replicas }}
```
**`spec.yaml` parameter:**
```yaml
replicas: 3
```
**Output:**
```yaml
replicas: 3
```
* `# from-param-merge: {{ .var }}`: Merges the YAML structure defined by the parameter `{{ .var }}` into the current location. This is useful for injecting complex objects or lists.
**Template:**
```yaml
metadata:
labels: # from-param-merge: {{ .commonLabels }}
app: my-app
```
**`spec.yaml` parameter:**
```yaml
commonLabels:
environment: production
version: v1.0.0
```
**Output:**
```yaml
metadata:
labels:
app: my-app
environment: production
version: v1.0.0
```
The [`example`](./example) directory contains a few examples of how to use `ymr`.
- [`simple`](./example/simple): A simple example of how to use `ymr` with a single template and a single target.
- [`k8s`](./example/k8s): A more complex example of how to use `ymr` to generate Kubernetes manifests for multiple targets.
- [`gcp-cloud-run`](./example/gcp-cloud-run): An example of how to use `ymr` to generate a GCP Cloud Run service definition for multiple targets.
- [`docker-composer`](./example/docker-composer): An example of how to use `ymr` to generate a Docker Compose file for multiple targets.
To run the examples, `cd` into the example directory and run `ymr run -o -`:
```bash
cd example/simple
ymr run -s . -o -
```
You're welcome to open issues or submit pull requests, though responses may take some time.
This project is licensed under the MIT License. See the `LICENSE` file for details.