A bare-bones Next.js project set up to demonstrate an agentic development loop in Claude Code: go from a vague idea to shipped, test-covered code with a chain of skills, ending in a batch loop that works a ticket backlog until it's empty.
idea
│ /grill-me interview until the idea is sharp
▼
shared understanding
│ /to-prd synthesize the conversation → docs/prd.md
▼
docs/prd.md
│ /to-issues docs/prd.md slice the PRD into tickets/TKT-*.md
▼
tickets/ (the work queue)
│ /loop /next-ticket ← the batch loop
▼
for each actionable ticket:
/next-ticket → /tdd (red → green → refactor) → mark done → commit
│
▼
backlog empty ✅ (loop stops itself)
Relentless one-question-at-a-time interview about what you want to build, until you and the agent share an understanding of the design.
Synthesizes the conversation into a Product Requirements Document at docs/prd.md
(problem, solution, user stories, implementation + testing decisions, scope).
Breaks the PRD into tracer-bullet vertical slices, one file per ticket under
tickets/. Each ticket has YAML frontmatter (id, status, type,
blocked_by) that the loop reads. AFK tickets run unattended; HITL tickets pause
for a human. See tickets/README.md for the format.
/next-ticket works one ticket: it picks
the lowest-id ticket that is todo, AFK, and unblocked; implements it test-first
with /tdd; runs npm test; then flips it to done
and commits. Run it on its own to do a single ticket. To drain the whole backlog,
loop it one of two ways:
Interactively, inside Claude Code:
/loop /next-ticket
/loop re-invokes the skill until /next-ticket prints ✅ BACKLOG EMPTY, then stops.
Headless, from your shell: scripts/work-backlog.sh
owns the loop in bash and calls the CLI (claude -p /next-ticket) each iteration.
Bash reads the ticket frontmatter to decide when to stop — it exits when no AFK
ticket is left in todo, or when an iteration completes no ticket (blocked / HITL /
failing test), so it never spins forever.
./scripts/work-backlog.sh # drain the AFK backlog unattended
MODEL=sonnet ./scripts/work-backlog.sh # choose the model
MAX_ITERS=5 ./scripts/work-backlog.sh # cap iterationsThe script defaults to
--permission-mode bypassPermissionsso it can edit, test, and commit without prompting. That grants full tool access — read the header comment and setPERMISSION_MODE=acceptEditsif you'd rather supervise it.
Guidance is loaded into context only when it's relevant to the file being worked
on, via Claude Code's path-scoped rules (paths: glob frontmatter):
| Rule file | Loads when touching |
|---|---|
.claude/rules/app-router.md |
app/**/*.ts(x) — Server/Client Components, async params, file conventions |
.claude/rules/testing.md |
*.test.ts(x), __tests__/** — Vitest + RTL, behavior-first testing |
.claude/rules/styling.md |
*.css — Tailwind CSS v4 conventions |
So a TDD cycle automatically gets the testing rules while writing the test and the App Router rules while writing the component — no manual context management.
Vitest + React Testing Library (configured per the bundled Next.js guide).
npm test # single run (vitest run) — used by the loop
npm run test:watch # watch mode for local devThere's a ready-made demo brief in demo/brief.md (a landing page
for a lightweight HR SaaS called Digipa) — paste it into /grill-me to exercise
the full loop.
npm install
# then, in Claude Code:
/grill-me # paste demo/brief.md (or your own idea), get grilled
/to-prd # → docs/prd.md
/to-issues docs/prd.md # → tickets/
/loop /next-ticket # drain the backlog (interactive)…or drain it headless from a shell:
./scripts/work-backlog.shnpm run dev # http://localhost:3000