One template.
Every runtime. Zero drift.

sc-compose renders Jinja2 templates with declared variables, shared fragments, and runtime-aware profile resolution — one engine across Claude Code, Codex, Gemini, and OpenCode.

$ brew install randlee/tap/sc-compose

What people build with it

Five jobs. One engine. Each is a real workflow running in production today.

“I ship agent workflows across every runtime”

Author one profile, resolve it anywhere. Claude Code, Codex, Gemini, and OpenCode each find your profile through their native search chain. Shared @-include fragments keep house style and review checklists consistent — override only the runtimes that genuinely need it.

$ sc-compose render \
    --mode profile --kind agent \
    --agent rust-dev --runtime claude
── powers ── codex-orchestration in atm-core · 9 templates · 4 runtimes

“I turn sprint data into reports”

Feed a JSON file into a Jinja2 template and get a deterministic HTML report. Loops, conditionals, and filters are declared up front, so missing data fails loudly instead of rendering half-finished.

$ sc-compose render report.md.j2 \
    --var-file sprint-data.json \
    --output sprint-report.html
── powers ── sprint-report in atm-core · detailed + summary template families

“I keep architecture docs from drifting”

ADRs, boundary docs, and crate diagrams live as versioned .j2 fragments. @-include shared sections, and let frontmatter-init discover the variables an existing document already uses.

$ sc-compose frontmatter-init adr-0019.md.j2

@<_includes/boundary-record.md>
Decision: {{ decision }}
── powers ── docs/templates in atm-core · ADR, boundary, sprint-plan

“My CI pipeline composes deterministically”

Every command speaks --json. validate before you render, verify to catch drift between a deployed file and its template, and publish-manifest to hand report artifacts to CI.

$ sc-compose render --json \
    --file task.xml.j2 \
    --var-file sprint.json
# → {"command_id":"render","outcome":"pass",…}
── powers ── CI/CD integration in atm-core release workflows

“I build Python tooling on top of it”

pip install sc-compose — a native extension, no shelling out. render_template() for one-offs, Renderer for repeated renders, and render_all() with verify() for full multi-pass from Python.

from sc_compose import render_template

render_template("Hello {{ name }}",
                {"name": "world"})
# → "Hello world"
── powers ── PyPI · pre-built wheels for macOS, Linux, Windows

Three steps, no magic

1 · Author

  • Jinja2 + YAML frontmatter
  • @-include shared fragments
  • {{ variables }}

2 · Declare

  • --var key=val
  • --var-file data.json
  • --env-prefix TASK_

3 · Render

  • stdout or --output
  • deterministic
  • byte-identical every run

Get it in one command

brew install randlee/tap/sc-compose

Bundled examples included — sc-compose examples list works out of the box.

winget install randlee.sc-compose

Bundled examples included in the package.

cargo install sc-compose

Binary only. Set SC_COMPOSE_DATA_DIR to use the bundled examples.

pip install sc-compose

Native extension. Pre-built wheels for macOS, Linux, Windows (Python 3.11+).