From cairn-builder
Build an app_spec.xml from scratch through Socratic Q&A. Use BEFORE /build-app when there is no app_spec.xml yet, or when the operator asks "help me write a spec", "scaffold my project spec", or "set up app_spec.xml". Walks the operator through templates/spec-template.xml section by section, asks 1–3 targeted questions per section, skips inapplicable sections, and writes the final app_spec.xml.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cairn-builder:spec-authorThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are guiding the operator through writing `app_spec.xml`, the input to the
You are guiding the operator through writing app_spec.xml, the input to the
autonomous-orchestrator harness. This spec is the single source of truth for
the entire build — every feature in feature_list.json will be derived from
it by the initializer subagent. Quality of the spec sets the ceiling on
quality of the build. Take this seriously.
The spec is XML, modeled on Anthropic's autonomous-coding quickstart
spec format. The OUTER scaffold (which top-level sections exist) is common
to every project; the INNER nested structure within each section is
project-specific (what tags appear under <technology_stack> depends on
whether it's a web app, CLI, pipeline, etc.).
<ui_layout>
or <design_system>. A throwaway prototype doesn't need
<auth_and_sessions>. Empty sections that ship in the final file
produce noise tests — drop the entire element, don't leave it empty.<technology_stack> can be web vs. CLI vs.
pipeline), explicitly ask the operator which shape fits, then propose
the nested tag set BEFORE filling content.ls app_spec.xml 2>/dev/null && echo "EXISTS" || echo "MISSING"
app_spec.xml already exists: tell the operator it exists. Ask whether
they want to (a) overwrite, (b) cancel and use /spec-updater instead to
amend it, or (c) review the existing one first. Default to (b) — overwriting
is destructive.cat templates/spec-template.xml
The template lists the candidate top-level sections and shows example nested shapes (in comments) for the project-specific bits. Use it as the agenda for the conversation.
Ask: "In one sentence, what is this app and who is it for?"
Use the answer to draft <project_name> and <overview>. Then ask one or
two follow-ups to clarify the target users and draft <target_users>.
Read all three back to the operator as XML snippets and confirm before
proceeding. This anchors the rest of the conversation.
For each remaining top-level section, in template order, do this mini-loop:
<technology_stack>. Should we fill this in?"<auth_and_sessions>), skip this step.<section></section> element to the file. Empty elements
become noise tests.<technology_stack>Example shape (web app):
<technology_stack>
<frontend>
<framework>React with Vite</framework>
<styling>Tailwind CSS</styling>
<port>5173</port>
</frontend>
<backend>
<runtime>Node.js with Express</runtime>
<database>SQLite with better-sqlite3</database>
</backend>
</technology_stack>
<prerequisites><core_features> (required)This is the longest section. Ask the operator to enumerate areas first (e.g., chat, sidebar, settings, billing). For each area, get 5-15 bullet points of features that must work.
Example shape:
<core_features>
<chat_interface>
- Streaming message responses with typing indicator
- Markdown rendering with code highlighting
- Multi-turn conversations with context
- Stop-generation button during streaming
</chat_interface>
<conversation_management>
- Create / rename / delete conversations
- Search by title or content
- Pin and archive
</conversation_management>
</core_features>
Push back if features are vague. "Users can interact with their data" is not a feature; "Click a row in the data table to open a detail drawer showing all fields, with an edit button" is.
<data_model> (skip if no persistence)<api_endpoints> (skip if no API)<auth_and_sessions> (skip if no accounts)<background_work> (skip if no async)<external_integrations> (skip if self-contained)<ui_layout> (skip if no UI)<design_system> (skip if no UI)<key_interactions><implementation_steps><success_criteria><out_of_scope> (recommended)After walking the standard template, ask:
"Anything else this spec should cover that we haven't touched on? Common additions:
<compliance>(HIPAA / SOC2 / GDPR),<multi_tenancy>,<ml_training_pipeline>,<internationalization>,<observability>."
For each yes, add a custom top-level section with a snake_case tag and walk the same question→draft→confirm mini-loop.
Stitch the filled sections into a single app_spec.xml in the working
directory. Order matches the template. Drop any sections the operator
skipped — do not leave empty elements.
The file MUST:
<?xml version="1.0" encoding="UTF-8"?> on line 1<project_specification>...</project_specification>Write the file with the Write tool, then validate it:
# Quick well-formedness check; xmllint may not be installed, that's OK.
xmllint --noout app_spec.xml 2>/dev/null && echo "VALID" || echo "(xmllint unavailable or invalid — eyeball the file)"
# Always show the operator what got written:
cat app_spec.xml
Tell the operator:
Spec saved to
app_spec.xml. To start the build, run:/build-appIf you want to revise the spec later (mid-run scope change, missed feature), use
/spec-updater— that preserves the orchestrator's "features only flip false→true" invariant by appending tofeature_list.jsonrather than rewriting it.
<core_features> that contradict <technology_stack>. If they say "must deploy to a static host" and then describe "user-uploaded video processing", flag the conflict immediately, don't bury it for the initializer to discover.<technology_stack>. "Uses pg.Pool with max:20" is not — that's a coder decision.<sections></sections> in the final file. Drop the element entirely. Empty sections become noise tests.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub bholzer/claude-cairn-builder