# Templates & Authoring `repospec init` seeds a repository's `.repospec/` from the bundled templates in `@repospec/templates`. Templates are shipped in the package (not fetched at runtime) so `init` is deterministic and offline (ADR-0006). This page explains what they produce and how to author or customize them. ## What templates produce Templates render only the **human-owned source** under `.repospec/` — the constitution, architecture, workflow, and the starter agents and rules. They do **not** render tool entrypoints like `CLAUDE.md` or `AGENTS.md`; those are generated from `.repospec/` by adapters in the engine and carry a managed header (ADR-0004). Keep the line clear: templates seed what a human then owns and edits; adapters generate what the tool regenerates. `getSeedDocuments(project)` returns the seed files for a validated project: ```ts import { getSeedDocuments } from '@repospec/templates'; for (const { path, contents } of getSeedDocuments(project)) { // path is relative to .repospec/, e.g. "constitution.md", "agents/reviewer.md" } ``` `project.yaml` itself is not a template — the engine serializes it from the validated configuration. ## Interpolation Seed content is filled from the init answers with a small substitution engine. `interpolate` replaces {{ dotted.path }} placeholders from a variable tree and **throws on a missing variable** — a loud failure beats a silent blank in a generated document. ```ts import { interpolate, partials } from '@repospec/templates'; const TEMPLATE = `# Architecture — {{ project.name }} ${partials.seededNote} This is a **{{ project.type }}**. `; const md = interpolate(TEMPLATE, { project: project.project }); ``` - Whitespace inside the braces is ignored: {{project.name}} and {{ project.name }} are equivalent. - Paths resolve into nested objects ({{ project.name }} reads `vars.project.name`). - A referenced variable that is missing or `null`/`undefined` throws. ### Partials `partials` holds reusable snippets shared across documents, so common prose lives in one place. Today it exports `seededNote` (the notice at the top of every seeded document). Compose partials into templates with a normal template literal, as shown above. ## Customizing the seed content The seed content lives in `@repospec/templates/src/content/`. To change what new repositories start with, edit those modules — each is a small function returning Markdown, using `interpolate` + `partials` for anything derived from the project. Keep two rules in mind: 1. **Deterministic and offline.** No network, no clock, no randomness — the same project must always produce the same seed (ADR-0006). 2. **Human-owned output only.** Never emit a managed header or anything a human shouldn't own; generated entrypoints are the adapters' job. ## Adapters vs. templates | | Templates (`@repospec/templates`) | Adapters (`@repospec/engine`) | | --- | --- | --- | | Produce | human-owned `.repospec/` source | generated tool entrypoints | | When | once, at `init` | every `generate` / `sync` | | Ownership | human edits freely afterward | managed header; regenerated | | Add one by | editing `content/` | implementing the `Adapter` interface | To target a new assistant, add an **adapter** (see `packages/engine/src/adapters/`), not a template. Templates are for what the human authors; adapters are for what the tool keeps in sync.