Skip to content

Chapter 14 · Repo-as-Spec and the AGENTS.md Design ​

Chapter goals: Understand the "repo IS the spec" principle, master the design method of AGENTS.md as a table of contents, and learn to use init.sh to establish a standardized startup flow.

14.1 Repo IS the Spec ​

OpenAI proposed a core principle in their harness engineering article: repo IS the spec.

The meaning of this sentence: the agent can only see files in the repo. Any information not existing in the repo is equivalent to non-existent for the agent. Your mental architecture conventions, decisions discussed in Slack three months ago, interaction details on Figma designs — if not written into the repo, the agent won't know.

This aligns with Anthropic's "state persistence" philosophy: all context the agent needs should exist in the repo as structured files, not rely on conversation history or verbal communication.

Two companies focus on different aspects, but say the same thing: all necessary information of engineering infrastructure must reside in the repo.

14.2 AGENTS.md: Table of Contents, Not an Encyclopedia ​

Building on the previous chapter, AGENTS.md's positioning is a table of contents — telling the agent "what the project is, how to use it, where to find more info" — not stuffing all knowledge into it.

A Complete AGENTS.md Structure ​

markdown
<!-- project-root/AGENTS.md -->
# AGENTS.md — Working with this repository

## What this project is
A FastAPI-based task management API with PostgreSQL backend.
Built for the Python Engineering team.

## Tech Stack
- Python 3.12 · FastAPI 0.141 · SQLAlchemy 2.0 (async)
- PostgreSQL 16 · Redis 7 (caching) · Celery 5 (background tasks)
- Testing: pytest + httpx TestClient
- Linting: ruff + mypy --strict

## First Run
```bash
make dev-up      # starts postgres + redis via docker-compose
uv sync
uv run pytest tests/ -q   # smoke test

Hard Constraints ​

  • All API routes must be under /api/v2/...
  • No synchronous database calls — use async with session()
  • All new endpoints require OpenAPI schema + request model

Verification Commands ​

  • Tests: pytest tests/ -x
  • Types: mypy src/ --strict
  • Lint: ruff check src/
  • Full: make check

Architecture ​

See your project's architecture documentation

API Spec ​

See your project's API specification


### Key Design Principles

1. **No more than 100 lines**: if too long, the agent treats it as "background noise" and key information gets drowned out. Split if necessary.
2. **Hard constraints in the main text**: non-negotiable rules (tech stack versions, naming conventions, auth methods) go directly into AGENTS.md.
3. **Detailed docs in docs/**: architecture decisions, API specs, database ER diagrams — these the agent only reads when needed; don't stuff them into AGENTS.md.
4. **Verification commands must be executable**: every command should be copy-pasteable directly into the terminal, not just text descriptions.

## 14.3 init.sh: An Independent Initialization Phase

One of the five failure modes mentioned in Chapter 10 is "incomplete environment." The agent opens a repo and spends 10 minutes troubleshooting the environment, installing dependencies, setting up the database — time that should have been spent on actual work.

**The independent value of the initialization phase**:剥离 the environment exploration cost from the task itself, so the environment is already known-good at the start of each session.

The responsibilities of `init.sh`:

```bash
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$ROOT_DIR"

INSTALL_CMD=(uv sync)
VERIFY_CMD=(pytest tests/ -q)
START_CMD=(uv run fastapi dev src/main.py)

echo "==> Working directory: $PWD"
echo "==> Syncing dependencies"
"${INSTALL_CMD[@]}"

echo "==> Running baseline verification"
"${VERIFY_CMD[@]}"

echo "==> Startup command"
printf '    %q\n' "${START_CMD[@]}"

if [ "${RUN_START_COMMAND:-0}" = "1" ]; then
    echo "==> Starting the app"
    exec "${START_CMD[@]}"
fi
echo "Set RUN_START_COMMAND=1 to launch the app directly."

init.sh Workflow Design ​

The agent should execute in a fixed order each time it starts:

bash
# 1. Confirm working directory
pwd

# 2. Read last session's progress record
cat PROGRESS.md   # or claude-progress.md

# 3. Read the feature list, select the highest-priority unfinished item
cat feature_list.json | jq '.features[] | select(.status == "in_progress")'

# 4. Check recent commits to understand current code state
git log --oneline -5

# 5. Run init.sh to ensure the environment is available
./init.sh

# 6. Run smoke tests to confirm baseline passes
pytest tests/smoke/ -q

Baseline Failure Handling Principle

If init.sh or the smoke test fails, fix the baseline first, then do new features. Don't stack new work on top of a broken baseline — this only makes the problem deeper.

14.4 AGENTS.md and init.sh in Concert ​

AGENTS.md and init.sh are complementary:

DimensionAGENTS.mdinit.sh
RoleStatic instruction docDynamic startup script
Who reads itAgent reads (at session start)Agent executes (at session start)
ContentTech stack, constraints, verification commandsDependency installation, baseline verification, service startup
LifecycleLow change frequency (after architecture stabilizes)Nearly immutable (copy and use)

Typical collaboration flow:

text
Agent starts
    ↓
Read AGENTS.md (get project overview + hard constraints)
    ↓
Read PROGRESS.md (get last session breakpoint)
    ↓
Read feature_list.json (select current task)
    ↓
Run ./init.sh (ensure clean, reproducible environment)
    ↓
Start working

This flow ensures each session starts from the same environment baseline, avoiding inconsistent behavior across sessions due to manual interventions changing the environment state.

14.5 Common Pitfalls ​

Pitfall 1: Writing AGENTS.md as a blog post

Writing 500 lines of project intro, history, team story … the agent doesn't need to know why your project was born; it only needs to know "how to work here." Keep it under 100 lines.

Pitfall 2: Verification commands in AGENTS.md that have never been run

If the make check you wrote doesn't run on your own machine, the agent can't run it either. Every command in AGENTS.md should have been actually verified on your own machine.

Pitfall 3: init.sh assuming the environment is already configured

uv sync failing, docker-compose not starting, database unreachable — these are edge cases init.sh should handle, not problems the agent should spend time troubleshooting.

Pitfall 4: PROGRESS.md never updated

Writing PROGRESS.md but not updating it is the same as not writing it at all. You must update the progress record before each session ends; otherwise the next session has nothing to read.

Chapter Summary ​

  • repo IS the spec: the agent can only see files in the repo; information not in the repo is non-existent to it
  • AGENTS.md is a table of contents (~100 lines); detailed content goes in docs/ for on-demand reading
  • Four elements of AGENTS.md: project overview / tech stack and versions / hard constraints / verification commands
  • init.sh剥离 the environment initialization cost from the task itself, ensuring each session starts from the same baseline
  • init.sh execution order: pwd → read progress → select feature → check git log → run init.sh → run smoke test
  • AGENTS.md (static instructions) and init.sh (dynamic execution) work in concert to form the minimum runnable harness baseline

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. What is the core meaning of "repo IS the spec"?

2. Regarding AGENTS.md length control, which statement is correct?

3. When init.sh baseline verification fails, what is the correct handling principle?

4. Which description best captures the relationship between AGENTS.md and init.sh?

🛠️ Hands-on Practice ​

  1. Create an AGENTS.md (under 100 lines) in your project root, containing the four elements, and ensure every verification command actually runs on your local machine.
  2. Write init.sh implementing: install dependencies → run baseline tests → optionally start services, three phases, using set -euo pipefail to keep errors可控.
  3. Create PROGRESS.md, simulating a "leftover interrupted state from the last session," letting the next agent pick up seamlessly from where it left off.

After completing, proceed to Next chapter: Adversarial Attacks and Defense.