The brief and the manifest
Understand the two files stacks new writes, what each section of the brief tells the agent, and which parts of .stacks/ you commit.
# The brief and the manifest
> Understand the two files stacks new writes, what each section of the brief tells the agent, and which parts of .stacks/ you commit.
`stacks new` and `stacks add` write two files for your agent. `.stacks/BRIEF.md` is the agent's task for building the project. `.stacks/manifest.json` is the project's definition of done, which you commit and keep for the life of the project.
## How the brief and the manifest differ
The brief is prose for an agent: long, specific to this build, and no longer needed once the project is green. The manifest is data for `stacks verify`: short, exact, and still used a year later by someone who clones the repository. Keeping them in separate files lets the instructions run as long as they need to while the checks stay small and machine-readable.
## What new writes
Here is a sandboxed `go-cli` project straight after `new`. The rest of this page uses the same project.
```sh title="Terminal"
stacks new go-cli demo --sandbox --no-launch
```
```text title="demo/.stacks/"
.gitignore
BRIEF.md
manifest.json
NOTES.md
state/
```
| Path | What it holds | Committed |
| --- | --- | --- |
| `.stacks/manifest.json` | The stack, fragments, preset, agents, commands, environment defaults and verify steps, plus a digest of the steps | Yes |
| `.stacks/BRIEF.md` | The agent's task | No |
| `.stacks/NOTES.md` | The agent's notes: questions it asked under `## Asked`, problems with the brief under `## Findings` | No |
| `.stacks/state/runs.jsonl` | One line per verify run | No |
| `.stacks/incoming/` | Files `add` couldn't write because the project already had them | No |
`.stacks/.gitignore` ignores the brief, the notes, `state/` and `incoming/`, so a normal `git add .` commits only the manifest.
One more record lives outside the project: a state record under `~/.local/state/stacks/projects/<projectId>.json` (or `$STACKS_STATE_DIR/projects/`). It holds a second copy of the verify digest and the project's timings. [Verify](https://stacks.steamfield.io/docs/concepts/verify.md#tamper-evidence) explains why it exists.
## The brief
The brief is assembled from fixed CLI text and the composed entries, in this order:
| Section | What it says |
| --- | --- |
| Header | Stack, fragments, preset, target agents, the project root and the files stacks wrote |
| `## Your job` | Done means `stacks verify` exits 0 with outcome `green`. Work autonomously and stop only for decisions and missing tools |
| `## Versions` | Nothing is pinned. Use current stable versions, prefer official generators, check current docs before writing config |
| `## Ground rules` | Run generators non-interactively and away from the project root, keep `AGENTS.md` accurate, keep `NOTES.md` up to date |
| `## Decisions` | Every entry's decisions, each with its default |
| `## Dependencies and tools` | Packages by role, names only, and whether each required tool is on PATH |
| One section per entry | The stack's guidance, then each fragment's |
| `## Definition of done` | The verify steps and their exact commands, the rules against weakening them, manual QA and what to do after green |
| `## Sandbox` | Only with `--sandbox`: skip deploy and release work, aim for the fastest path to green |
The header of that `go-cli` brief:
```md title=".stacks/BRIEF.md"
# Build demo: Go CLI
- Stack: Go CLI (`go-cli`)
- Fragments: `agent-ops`, `ci-github`, `git-hooks`
- Preset: sandbox (local only, never deployed)
- Target agents: claude
- Project root: the directory containing `.stacks/`. Run every command from there.
- Files stacks wrote:
- `.claude/` (10 files)
- `.editorconfig`
- `.gitignore`
- `.stacks/` (4 files)
- `AGENTS.md`
- `CLAUDE.md`
- `Makefile`
- `README.md`
```
### Decisions
A decision is a choice the stack author couldn't make for you, with a sensible default. With the default preset the brief tells the agent to ask you about each one. With `--yes` or `--sandbox` it tells the agent to take every default and list them in its final summary:
```md title=".stacks/BRIEF.md"
## Decisions
Use each default below without asking, and list what you chose in your final summary.
- Module path: github.com/<owner>/<project-slug> (default), owner from `gh api user -q .login` or the git remote, never the author's display name. ...
- Binary name: the project slug (default; the Makefile's BIN).
- Coverage floor: 50% (default).
- ci-github: Runners: ubuntu-latest (default) or self-hosted labels.
...
```
### Brief length and word budget
The `go-cli` brief above is about 3,300 words, and a stack with several fragments often passes 4,000. The agent reads it once, at the start, so everything it needs goes in one file. [`stacks validate`](https://stacks.steamfield.io/docs/reference/validation.md) holds every composition to a budget of 6,000 words, or 9,000 with an app, so briefs stay readable. `stacks show <id>` prints a stack's brief size with its defaults.
### Fixing a wrong brief
A wrong brief gets fixed in the stack or fragment that produced it. The brief is generated, and editing `BRIEF.md` changes nothing verify checks. The agent records the problem under `## Findings` in `NOTES.md` so the entry's author can fix it.
## The manifest
`stacks verify` reads only the manifest. Here is the same project's, trimmed to two steps and four commands:
```json title=".stacks/manifest.json"
{
"schemaVersion": 1,
"projectId": "fd22575b-8e97-4fce-868b-27856c7efd33",
"cli": "0.5.0",
"mode": "new",
"name": "demo",
"preset": "sandbox",
"agents": ["claude"],
"stack": { "id": "go-cli", "origin": "bundled", "trusted": true },
"fragments": [
{ "id": "agent-ops", "origin": "bundled", "trusted": true },
{ "id": "ci-github", "origin": "bundled", "trusted": true },
{ "id": "git-hooks", "origin": "bundled", "trusted": true }
],
"env": {},
"commands": {
"install": "Download modules and install dev tools that are missing",
"build": "Build the binary into bin/ with version info",
"lint": "Run golangci-lint",
"test": "Unit tests"
},
"verify": [
{
"name": "install",
"run": "make install",
"phase": "setup",
"tags": [],
"layer": "install",
"timeout": "10m",
"owner": "go-cli",
"skipByDefault": false
},
{
"name": "lint",
"run": "make lint",
"phase": "check",
"tags": [],
"layer": "lint",
"timeout": "10m",
"owner": "go-cli",
"skipByDefault": false
}
],
"verifyDigest": "sha256:38b641cbf6b495fb2b026e222c161ad5ca6ad48a26449d790611dbbc1d545748",
"fingerprint": "sha256:c1c76ffed7d10d3815c1bfa762899875465cb766f353796fd671ab6561f9f3d3"
}
```
| Field | What it's for |
| --- | --- |
| `projectId` | A random id that names the project's state record. It never leaves your machine |
| `preset`, `agents` | What the project was composed with |
| `stack`, `fragments` | Each entry's id, its [origin](https://stacks.steamfield.io/docs/concepts/registries-and-trust.md) and whether it was trusted |
| `env` | Default environment values for verify steps, such as ports. A variable you set in your shell wins |
| `commands` | Every project command and what it does |
| `verify` | The steps: name, command, phase, layer, tags, timeout, the entry that owns it, and whether it is skipped by default (`prod` steps in a sandbox) |
| `verifyDigest` | The fingerprint of the steps, `env` and `preset`, checked before every verify run |
| `fingerprint` | Identifies the exact composition, so a run can be compared with recorded runs of the same content |
Commit the manifest with the project. Anyone who clones the repository can run `stacks verify` and get the same checks, with no brief and no stacks registry needed.
## Adding to an existing project
`stacks add` writes into a project that already has code. It writes the same `.stacks/` files, adds the new fragments' verify steps to an existing manifest (or creates one with `mode: "add"` and no stack), and parks any file that would conflict with one the project already has under `.stacks/incoming/`, so the agent can merge it by hand. Before it plans anything, `add` runs the same tamper check as verify. [Add to an existing repository](https://stacks.steamfield.io/docs/guides/existing-repo.md) walks through it.
## Related
- [Verify: the definition of done](https://stacks.steamfield.io/docs/concepts/verify.md): how the manifest's steps run.
- [How stacks works](https://stacks.steamfield.io/docs/concepts.md): where the brief's sections come from.
- [`stacks new`](https://stacks.steamfield.io/docs/reference/commands.md#stacks-new) and [`stacks add`](https://stacks.steamfield.io/docs/reference/commands.md#stacks-add): every flag.
View as MarkdownOpen in ClaudeOpen in ChatGPTstacks new and stacks add write two files for your agent. .stacks/BRIEF.md is the agent's task for building the project. .stacks/manifest.json is the project's definition of done, which you commit and keep for the life of the project.
How the brief and the manifest differ
The brief is prose for an agent: long, specific to this build, and no longer needed once the project is green. The manifest is data for stacks verify: short, exact, and still used a year later by someone who clones the repository. Keeping them in separate files lets the instructions run as long as they need to while the checks stay small and machine-readable.
What new writes
Here is a sandboxed go-cli project straight after new. The rest of this page uses the same project.
stacks new go-cli demo --sandbox --no-launch.gitignore
BRIEF.md
manifest.json
NOTES.md
state/| Path | What it holds | Committed |
|---|---|---|
.stacks/manifest.json |
The stack, fragments, preset, agents, commands, environment defaults and verify steps, plus a digest of the steps | Yes |
.stacks/BRIEF.md |
The agent's task | No |
.stacks/NOTES.md |
The agent's notes: questions it asked under ## Asked, problems with the brief under ## Findings |
No |
.stacks/state/runs.jsonl |
One line per verify run | No |
.stacks/incoming/ |
Files add couldn't write because the project already had them |
No |
.stacks/.gitignore ignores the brief, the notes, state/ and incoming/, so a normal git add . commits only the manifest.
One more record lives outside the project: a state record under ~/.local/state/stacks/projects/<projectId>.json (or $STACKS_STATE_DIR/projects/). It holds a second copy of the verify digest and the project's timings. Verify explains why it exists.
The brief
The brief is assembled from fixed CLI text and the composed entries, in this order:
| Section | What it says |
|---|---|
| Header | Stack, fragments, preset, target agents, the project root and the files stacks wrote |
## Your job |
Done means stacks verify exits 0 with outcome green. Work autonomously and stop only for decisions and missing tools |
## Versions |
Nothing is pinned. Use current stable versions, prefer official generators, check current docs before writing config |
## Ground rules |
Run generators non-interactively and away from the project root, keep AGENTS.md accurate, keep NOTES.md up to date |
## Decisions |
Every entry's decisions, each with its default |
## Dependencies and tools |
Packages by role, names only, and whether each required tool is on PATH |
| One section per entry | The stack's guidance, then each fragment's |
## Definition of done |
The verify steps and their exact commands, the rules against weakening them, manual QA and what to do after green |
## Sandbox |
Only with --sandbox: skip deploy and release work, aim for the fastest path to green |
The header of that go-cli brief:
# Build demo: Go CLI
- Stack: Go CLI (`go-cli`)
- Fragments: `agent-ops`, `ci-github`, `git-hooks`
- Preset: sandbox (local only, never deployed)
- Target agents: claude
- Project root: the directory containing `.stacks/`. Run every command from there.
- Files stacks wrote:
- `.claude/` (10 files)
- `.editorconfig`
- `.gitignore`
- `.stacks/` (4 files)
- `AGENTS.md`
- `CLAUDE.md`
- `Makefile`
- `README.md`Decisions
A decision is a choice the stack author couldn't make for you, with a sensible default. With the default preset the brief tells the agent to ask you about each one. With --yes or --sandbox it tells the agent to take every default and list them in its final summary:
## Decisions
Use each default below without asking, and list what you chose in your final summary.
- Module path: github.com/<owner>/<project-slug> (default), owner from `gh api user -q .login` or the git remote, never the author's display name. ...
- Binary name: the project slug (default; the Makefile's BIN).
- Coverage floor: 50% (default).
- ci-github: Runners: ubuntu-latest (default) or self-hosted labels.
...Brief length and word budget
The go-cli brief above is about 3,300 words, and a stack with several fragments often passes 4,000. The agent reads it once, at the start, so everything it needs goes in one file. stacks validate holds every composition to a budget of 6,000 words, or 9,000 with an app, so briefs stay readable. stacks show <id> prints a stack's brief size with its defaults.
Fixing a wrong brief
A wrong brief gets fixed in the stack or fragment that produced it. The brief is generated, and editing BRIEF.md changes nothing verify checks. The agent records the problem under ## Findings in NOTES.md so the entry's author can fix it.
The manifest
stacks verify reads only the manifest. Here is the same project's, trimmed to two steps and four commands:
{
"schemaVersion": 1,
"projectId": "fd22575b-8e97-4fce-868b-27856c7efd33",
"cli": "0.5.0",
"mode": "new",
"name": "demo",
"preset": "sandbox",
"agents": ["claude"],
"stack": { "id": "go-cli", "origin": "bundled", "trusted": true },
"fragments": [
{ "id": "agent-ops", "origin": "bundled", "trusted": true },
{ "id": "ci-github", "origin": "bundled", "trusted": true },
{ "id": "git-hooks", "origin": "bundled", "trusted": true }
],
"env": {},
"commands": {
"install": "Download modules and install dev tools that are missing",
"build": "Build the binary into bin/ with version info",
"lint": "Run golangci-lint",
"test": "Unit tests"
},
"verify": [
{
"name": "install",
"run": "make install",
"phase": "setup",
"tags": [],
"layer": "install",
"timeout": "10m",
"owner": "go-cli",
"skipByDefault": false
},
{
"name": "lint",
"run": "make lint",
"phase": "check",
"tags": [],
"layer": "lint",
"timeout": "10m",
"owner": "go-cli",
"skipByDefault": false
}
],
"verifyDigest": "sha256:38b641cbf6b495fb2b026e222c161ad5ca6ad48a26449d790611dbbc1d545748",
"fingerprint": "sha256:c1c76ffed7d10d3815c1bfa762899875465cb766f353796fd671ab6561f9f3d3"
}| Field | What it's for |
|---|---|
projectId |
A random id that names the project's state record. It never leaves your machine |
preset, agents |
What the project was composed with |
stack, fragments |
Each entry's id, its origin and whether it was trusted |
env |
Default environment values for verify steps, such as ports. A variable you set in your shell wins |
commands |
Every project command and what it does |
verify |
The steps: name, command, phase, layer, tags, timeout, the entry that owns it, and whether it is skipped by default (prod steps in a sandbox) |
verifyDigest |
The fingerprint of the steps, env and preset, checked before every verify run |
fingerprint |
Identifies the exact composition, so a run can be compared with recorded runs of the same content |
Commit the manifest with the project. Anyone who clones the repository can run stacks verify and get the same checks, with no brief and no stacks registry needed.
Adding to an existing project
stacks add writes into a project that already has code. It writes the same .stacks/ files, adds the new fragments' verify steps to an existing manifest (or creates one with mode: "add" and no stack), and parks any file that would conflict with one the project already has under .stacks/incoming/, so the agent can merge it by hand. Before it plans anything, add runs the same tamper check as verify. Add to an existing repository walks through it.
Related
- Verify: the definition of done: how the manifest's steps run.
- How stacks works: where the brief's sections come from.
stacks newandstacks add: every flag.