Bootstraps the AGENTS.md + context/ + /design documentation system for
any project — new or existing — following the project-foundation skill.
Point it at a folder, answer a handful of questions, get back a project
operating manual an AI agent can actually work from.
Every new AI-assisted project starts the same way: someone has to explain the product, the stack, and the boundaries to the AI by hand — in a prompt, a meeting, a Slack thread — before it can be trusted with real work. Skip that step and the AI decides those things for you: the wrong data model, a secret that ends up reachable from the browser, an architecture call that gets re-litigated differently every session because nothing was written down.
This tool automates that step instead of skipping it. It asks the six
questions that actually matter (mobile or web, what the app does, who
creates/consumes it, where the data lives, what's public vs. gated, what
must stay server-side), inspects what's actually installed rather than
trusting a description, and writes the result as AGENTS.md + context/ —
a real operating manual an AI agent can start from, instead of a blank
prompt. A second, read-only agent checks that output before anything gets
reported, so the review isn't just the same reasoning checking itself.
It costs cents, not a planning meeting — see Cost & time below — and it never commits, pushes, or touches an external tool without an explicit, per-action confirmation.
git clone <this-repo-url> project-foundation-agent
cd project-foundation-agent
npm install
npm run scaffold -- "C:\path\to\your\project"That's the whole setup. Nothing else to configure, no separate skill install step — see Portability for why.
npm installRequires Node 18+. Everything else (the Agent SDK, tsx, TypeScript) is a
devDependency/dependency already declared in package.json.
npm run scaffold -- "C:\path\to\project"Brownfield project with pre-existing planning docs — pass them as extra arguments (file or directory, either works):
npm run scaffold -- "C:\path\to\project" "C:\path\to\requirements.md" "C:\path\to\meeting-notes.md"This does two things: grants Read access outside cwd via
additionalDirectories (the SDK doesn't allow reading outside cwd by
default), and tells the skill's Step -1 to read those files before
asking anything — so it confirms what the docs already answer instead of
re-interviewing you from zero.
Brand-new project, folder doesn't exist yet — that's fine, agent.ts
creates it (mkdirSync(..., {recursive: true})) before the SDK needs a real
cwd to spawn into. No manual mkdir step required.
This is interactive — Step 0 asks product-shape questions (mobile/web,
what the app does, who creates/consumes content, where data lives, public vs.
authed, what must stay server-side) before writing anything. Run it from a
real terminal — it blocks on readline waiting for your answers, so a
non-interactive script runner or CI job will just hang.
Since the skill ships as a plugin bundled in this repo, you can also just
point a live Claude Code / Agent SDK session at it without running
agent.ts. From inside (or told to look at) the target project:
Usa el skill project-foundation para este proyecto. Ya existen documentos de
planeación fuera del repo — léelos primero (Step -1) antes de preguntarme
nada:
- C:\path\to\requirements.md
- C:\path\to\meeting-notes.md
This works because project-foundation is also installed at
~/.claude/skills/project-foundation/ on this machine (a manual copy, kept
in sync with plugin/skills/project-foundation/SKILL.md — see
Portability for the distinction).
Prefer Path A when you want a reusable, scriptable command; prefer Path B
for a one-off, or when Path A's billing (below) is the blocker.
AGENTS.mdat the target project's rootcontext/project-overview.md,architecture.md,build-plan.md,code-standards.md,library-docs.md,ui-tokens.md,ui-rules.md,ui-registry.md(always starts empty, on purpose),progress-tracker.md(starts as a one-phase skeleton — every future session working this project checks items off and adds new ones here, the same way a real project's client-feedback rounds get tracked over time)/design/<brand>-design-system.md— reused if one already exists at that path, created as a labeled draft if not
It never commits or pushes. Review with git status / git diff in the
target project before committing — if the target has no .git yet
(common for a not-yet-formalized project), run git init there first so you
have something to diff against.
Two things: what it costs, and where the money went.
npm run scaffold -- "C:\path\to\project"
...
Cost: $0.4213 · Turns: 12 · Wall time: 38.2s (API: 31.7s)
claude-haiku-4-5-20251001: $0.0412 (in: 18420, out: 640)
claude-sonnet-5: $0.3801 (in: 9210, out: 3140)The per-model breakdown (message.modelUsage, exact field names from the
SDK's own cost-tracking docs) is what actually answers "where did the money
go" — Steps 1&2 (inspection + web research) run on Haiku, delegated to
the foundation-inspector subagent, since reading a manifest and searching
the web is mechanical, not creative. Steps 0 and 3-7 (the parts that need
real judgment: asking the right questions, writing real content, verifying
it) stay on Sonnet. This isn't a guess at savings — it's a structural
split, so the report above tells you exactly which part cost what, not just
one combined number a business would have to trust blindly.
maxTurns: 40 / maxBudgetUsd: 3 remain hard stops regardless — a run
that goes long stops on its own instead of surprising anyone with the bill.
Off by default. Only activates if you pass a config file for an already set up MCP server for your PM tool (Jira, Linear, etc.):
npm run scaffold -- "C:\path\to\project" --pm-mcp "C:\path\to\your-jira-mcp-config.json"About the login: this script never sees or handles that authentication. The config file just points to an MCP server you've already set up and authenticated on your own — however that server logs in (an API token in its own environment, an OAuth flow it runs itself the first time it starts) happens entirely outside this repo. This script only asks two separate yes/no questions: one before connecting to the server at all (printed to the terminal, before the SDK session even starts), and one more before it's allowed to actually create or edit anything there — connecting a tool and writing a real, visible ticket into someone's real project-management system are different levels of consequence, and each gets its own consent.
| Option | Value here | Why |
|---|---|---|
cwd |
the target project path (arg 1) | scopes all file access to that project |
additionalDirectories |
dirs of any extra doc paths (args 2+) | lets Step -1 read planning docs that live outside the target repo |
tools / allowedTools |
Read, Write, Glob, Grep, WebSearch, Skill, Agent (no AskUserQuestion in allowedTools) |
hard-restricts what the model can do at all; AskUserQuestion is deliberately left un-auto-approved so it falls through to canUseTool below instead of running silently |
canUseTool |
intercepts AskUserQuestion always, plus mcp__* only if --pm-mcp was confirmed |
prints question+options to the terminal for AskUserQuestion, feeds the pick back as answers: {[question]: label} — shape verified against sdk-tools.d.ts, not guessed. For MCP tools, asks a real per-call yes/no instead of auto-approving |
agents |
foundation-inspector (Haiku, Steps 1&2) + foundation-verifier (Sonnet-tier default, Step 6) |
one delegates mechanical inspection/research to a cheaper model; the other independently reviews the output with no Write access, so it can only report gaps, not paper over them |
mcpServers |
only set if --pm-mcp <config> was passed and confirmed at the pre-flight prompt |
opt-in project-management tool sync — see Cost & time |
settingSources |
[] (full isolation) |
ignores whatever CLAUDE.md/skills happen to exist on the machine running this — the plugin below is the only source of truth, so behavior is identical on any machine |
plugins |
[{type: "local", path: <this file's own dir>/plugin}] |
bundles the skill inside this repo instead of depending on a ~/.claude/skills/ install — see Portability |
skills |
["ammae-foundation:project-foundation"] |
plugin skills are namespaced <plugin-name>:<skill-folder-name> — confirmed live via the init message's skills list |
model |
sonnet |
this generates real documentation content, not a mechanical task — worth the better model |
maxTurns / maxBudgetUsd |
40 / $3 |
hard stops so a stuck run can't loop or overspend |
The skill used to live only at ~/.claude/skills/project-foundation/ — a
path specific to one machine, outside any repo. Cloning this repo elsewhere
would run, but silently without the skill.
It's now also bundled as an SDK plugin, inside this repo:
project-foundation-agent/
└── plugin/
├── .claude-plugin/plugin.json (name: "ammae-foundation")
└── skills/project-foundation/SKILL.md
agent.ts resolves the plugin's path against its own file location
(fileURLToPath(new URL("./plugin", import.meta.url))), not against cwd —
cwd is the target project and changes every run, so a path relative to it
would resolve wrong. Verified live, with settingSources: [] (so nothing
from the machine's own ~/.claude/ could be filling the gap):
PLUGINS: [{"name":"ammae-foundation","path":"...\\project-foundation-agent\\plugin", ...}]
SKILLS: [..., "ammae-foundation:project-foundation", ...]
RESULT: success
The ~/.claude/skills/project-foundation/ copy still exists on this
machine — that's what makes Path B (asking Claude Code directly) work
without this repo at all. It's a convenience for interactive use, not a
dependency of this script anymore. If you edit the skill, keep both copies
in sync: the plugin copy here, the ~/.claude/skills/ copy for Path B, and
the source-of-truth copy in ammae-utilities/.agents/skills/architect/project-foundation/SKILL.md.
Agent SDK practices checklist (vs. the official overview)
The overview lists eight capability areas. Here's what this project uses, and what it deliberately doesn't:
| Capability | Status | Why |
|---|---|---|
| Built-in tools | ✅ Used, minimally | Read/Write/Glob/Grep/WebSearch/AskUserQuestion/Skill only — no Bash, no Edit of files outside scope |
| Permissions | ✅ Used | tools/allowedTools restriction + a custom canUseTool scoped to exactly one tool |
| Skills | ✅ Used | the entire point of this runner |
| Plugins | ✅ Used | bundles the skill for portability (see above) |
| Sessions | session_id is captured and logged on error_max_turns so you can manually resume, but this script doesn't auto-resume |
|
| Hooks | ❌ Not used | subagent verification (below) covers the same "catch it before it ships" need a Stop hook would; revisit if a stronger enforcement point is ever needed |
| Subagents | ✅ Used | foundation-verifier — a fresh-context, read-only reviewer the skill's Step 6 invokes after writing everything, before the final report. It has no Write access on purpose: it can only flag gaps, never quietly "fix" them by rewriting what it's supposed to be checking |
| MCP | ❌ Not used | no external tool/service integration required |
Agent patterns used (vs. Anthropic's Building Effective Agents)
- Prompt chaining — Steps -1 through 7 are a fixed sequence, each building on the last, gated by Step 0 requiring all six answers before anything gets written.
- Evaluator-optimizer —
foundation-verifier(Step 6) is the evaluator; the main loop is the optimizer, re-invoking it up to twice on gaps found. - Orchestrator-workers — considered and rejected for Step 4 (writing the 8
context/files in parallel via separate subagents). Writing 8 markdown files isn't the expensive part of this task — the thinking in Steps 0-2 is — so parallelizing the write step would add coordination risk (keeping Step 0's decisions consistent across independent workers) without a measured speed problem to justify it. Revisit only ifcontext/generation is ever profiled as an actual bottleneck.
"Credit balance is too low" — Agent SDK / claude -p usage draws from a
separate monthly credit, independent of your interactive Claude Code
session/weekly quota (/status can show plenty of headroom there and this
error can still happen). On a Team/Enterprise plan, only Owners/Primary
Owners manage this, under Organization settings → Usage — not under your
own personal Settings. See Use the Claude Agent SDK with your Claude
plan
and Manage usage credits for Team and seat-based Enterprise
plans.
If you hit this, Path B above sidesteps it entirely — it bills against
the interactive quota instead.
What it actually costs when it works — a real run against an empty
project, no tool calls beyond a one-line reply, was $0.1432. A full
scaffold (Step -1 through Step 6, several file writes, a couple of
WebSearch calls) should land well under the $3 maxBudgetUsd cap in
most cases — the cap exists precisely so a run that goes long stops instead
of surprising you.
readline was closed — only ever seen when simulating interactive
input via a pipe that closes early (a test-harness artifact, not a real
terminal issue); agent.ts recreates the readline.Interface on demand as
a safety net regardless.