Create Agentic App
Walk the user from "I want to build something" to a verified, running Agentic Coding Starter Kit project at
. Every step has a clear purpose — explain it briefly to the user as you go, so they understand the choices being made on their behalf.
All shell commands below are written in POSIX form. On Windows, run them through the Bash tool (Git Bash / WSL), which is available on every supported platform. Do not translate to PowerShell unless a command actually fails.
This skill is linear with two real branch points: folder strategy (Step 2) and database choice (Step 6). Everything else is a yes/no or a default. Move through the steps in order — skipping ahead breaks assumptions downstream (e.g. migrations require a configured
).
substitution: Throughout this file and the references,
is a placeholder for the chosen package manager — substitute as follows:
- → , ,
- → , , (the is required for npm script invocation)
- → , ,
1. Pre-flight Checks
Detect what the user already has installed before asking them to pick anything. Probing first means later questions only offer real options — nothing is worse than asking "pnpm or npm?" and then discovering pnpm isn't installed.
Run all six probes in parallel via a single batch of Bash calls:
bash
node --version
pnpm --version
npm --version
yarn --version
docker --version
git --version
Interpret the results:
- Node.js must be . If fails or returns < 18, stop and tell the user to install Node 18+ from https://nodejs.org. Do not continue — every step from here on requires Node.
- Git must be present (the scaffolder uses it). If missing, stop and direct the user to https://git-scm.com/downloads.
- Package managers: remember which of , , succeeded. Discard the ones that failed — you will never offer them as options in Step 3.
- Docker is optional here; it only matters if the user picks the local-DB path in Step 6. Note whether succeeded.
Report findings as one short sentence to the user — for example: "Found Node 20.11, pnpm 9.1, npm 10.5, Docker 27.0, Git 2.43. Yarn not detected." Do not dump raw command output.
2. Folder Strategy
The scaffolder (
) refuses to write into a non-empty target. The agent has to pick the right invocation based on what is in the current working directory.
Run
(includes dotfiles) in the cwd to see what is there.
2a. Empty or git-only cwd
If the directory is empty or only contains
, scaffold directly in place. Skip to Step 3 — you will run
npx create-agentic-app@latest .
later.
2b. Non-empty cwd
"This folder isn't empty. Where do you want the starter scaffolded?"
- Subfolder — pick a name (default: ); the starter lives at .
- This folder — I will scaffold into a temp directory and move the files back into the current folder. Use this if you want the starter to replace the current folder's contents (or merge with them).
- Cancel — stop and let me sort the directory out first.
If they pick
subfolder: ask for the folder name, default to
. The scaffold target in Step 4 becomes
. Skip the temp-dir dance.
If they pick this folder: the agent does the following carefully, because hidden files and name collisions both bite:
- Pick a temp dir name that does not already exist:
../$(basename "$PWD")-scaffold-tmp
. If that path is already taken, append a short random suffix.
- Run the scaffolder in the temp dir (Step 4 with = the temp dir). Always pass for the temp-dir variant — otherwise the CLI creates an initial commit inside the temp dir, and the directory will overwrite the user's existing when you move files back, destroying their history.
- After scaffolding completes and the rest of the steps that can be done inside the temp dir are done (env file, migrations, etc. — they all work from inside the temp dir), move everything back. Use a command that includes hidden files. POSIX:
bash
shopt -s dotglob
mv ../<temp-dir>/* ./
shopt -u dotglob
This catches , , , , and any other dotfiles the starter ships.
- Before each overwrite: if a file in the temp dir collides with an existing file in the cwd (e.g. the user already has a , a , or a directory), stop and ask the user via which one to keep. Do not silently clobber their work.
- After the move, remove the now-empty temp dir: .
Document this plan to the user before running it so they know what is about to happen to their cwd.
3. Package-Manager Choice
Ask via
, but only show options that succeeded in Step 1's probe:
"Which package manager should the starter use?"
- pnpm (only show if detected) — recommended by the starter.
- npm (only show if detected)
- yarn (only show if detected)
- You pick for me — defer to the agent.
If the user picks "you pick", prefer in order:
→
→
based on what is installed. Never suggest pnpm if
failed in Step 1 — installing it just to satisfy a preference frustrates users.
Remember the chosen
for every subsequent step.
4. Run the Scaffold
bash
npx create-agentic-app@latest <target> --package-manager <pm> --yes
For the
temp-dir variant (Step 2b "this folder"), add
to the command above — see Step 2b for why.
Where
is the path from Step 2 (
,
, or
) and
is
,
, or
(the name only — no
prefix). The
flag auto-confirms the CLI's "directory is not empty" prompt; without it, the CLI prompts interactively and will hang under the Bash tool. Note that the CLI only prompts for confirmation when
is a named non-empty directory — when
is
, the CLI happily writes into the current folder regardless of contents, which is why Step 2's folder strategy matters.
Stream the scaffolder's output to the user so they can see what is happening. If the CLI errors (registry timeout, permissions, etc.), surface the exact error message and stop. Do not try to recover by guessing — most scaffolder failures need user-level fixes (network, npm config, permissions).
The CLI also runs
and
(unless
) for you automatically.
Critically: the CLI captures the install output with , so a failed install only prints a warning and the CLI still exits 0. Before continuing, verify dependencies actually installed:
bash
test -d <target>/node_modules && ls <target>/node_modules | head -n 5
If
is missing or near-empty, run
from inside
before moving on. Otherwise
will fail later with a confusing
Cannot find module 'drizzle-kit'
error and you will have wasted the user's time.
After the scaffold completes,
into the scaffolded directory for the rest of the flow. Subsequent commands assume you are inside it. For the temp-dir variant,
for now — you will move the files back into the original folder after Step 7 (post-migration) and then
back. Running migrations from inside the temp dir is fine; the
is right there.
5. Configure
The starter ships an
with sensible defaults but missing secrets. Set up
:
- Copy the template if does not already exist:
- Generate a strong (the value shipped in is a placeholder — replacing it is non-negotiable for any environment beyond throwaway local dev):
bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Take the output and write it into as BETTER_AUTH_SECRET=<value>
.
- Confirm
NEXT_PUBLIC_APP_URL=http://localhost:3000
is set (it already is in the template).
- Leave the following blank for now — later steps populate them based on user opt-in:
- (Step 8)
- (Step 9b)
- / (Step 9b)
Tell the user: "I have set up
with a fresh auth secret. Database URL and optional integrations come next."
6. Database Setup
"Which PostgreSQL setup do you want?"
- Local Docker (only show if succeeded in Step 1) — recommended for local development; uses the included .
- Neon — free serverless Postgres in the cloud (good for solo dev and small projects).
- Vercel Postgres — best if you plan to deploy to Vercel anyway.
- Bring your own — you have a already.
Once the user picks,
now read and follow the section for the chosen branch. That file has the exact commands, the connection-string format to expect, and the validation steps for each path. Do not paste those details here — they go stale and crowd this workflow.
After the chosen branch completes, you will have a valid
in
. Move on to migrations.
7. Run Migrations
This applies the starter's pre-generated migrations and creates the Better Auth tables. The boilerplate already ships generated migrations, so you do not need
here — that command is only relevant later when the user changes the schema.
Never run as a shortcut if migrations fail. Per the project's
rule: drizzle push bypasses the migration history and creates drift that is painful to recover from. If
fails, surface the exact error to the user — it is almost always a wrong
, an unreachable database, or stale auth credentials — and offer to retry once they fix the underlying cause.
8. AI Capabilities — Opt-in
Ask the user:
"Do you want AI features enabled? The starter wires up the Vercel AI SDK via OpenRouter, which lets you swap models without code changes. You can skip this and add it later."
If yes:
- Walk the user to https://openrouter.ai/settings/keys to create an API key.
- Ask them to paste it; set in .
- Confirm the default
OPENROUTER_MODEL="openai/gpt-5-mini"
is fine, or let them swap it for any model listed at https://openrouter.ai/models.
If
no: leave
blank. The chat route at
will return an error if invoked, but the rest of the app runs fine. Note this to the user so they are not surprised later.
9. Authentication — Inform, Don't Configure
Tell the user, in roughly these words:
The starter ships with email + password authentication enabled by default — that is enough for an MVP. If you want social sign-in (Google, GitHub, etc.), I can add it via Better Auth — but I recommend starting with email/password and adding OAuth later when you actually need it.
If the user wants OAuth
now,
read . That file links the Better Auth provider docs, tells the agent to fetch the relevant page with WebFetch, and reminds you to keep email/password enabled alongside any new providers. Otherwise, skip it — adding OAuth is cheap to do later and adds friction up front.
9b. Production Extras — Opt-in (Single Multi-Select)
Ask once via
(multi-select):
"Which production integrations do you want set up now? Pick any that apply, or leave them all unchecked to skip and keep the setup lean — you can add them later."
- File uploads with Vercel Blob
- Payments with Polar
- Transactional email (Resend / Postmark / etc.)
If the user picks nothing, skip this step entirely — do not load the reference file. Loading docs the user does not need wastes their context budget.
For each item the user
does pick,
read the corresponding section of references/production-extras.md
and walk them through it. That file has independent sections for Blob, Polar+ngrok, and email — only consult the ones that apply.
10. Verify the Build
Use
(not
) because the default
script also runs migrations — and we already migrated in Step 7. Running them twice is harmless but slower and noisier.
If the build fails: surface the exact error to the user. Common causes are missing env vars (re-check
) or stale Node modules (
again if needed). Do not paper over a build failure by "fixing forward" — most build errors at this stage indicate a misconfiguration that will haunt the dev server later.
11. Start the Dev Server and Verify
Start the dev server in the background:
Run this via the Bash tool's
option so the rest of the verification can run alongside it. The Bash tool returns immediately —
Next.js needs a few seconds to compile and bind to port 3000, so do not curl right away or you will get a connection-refused error and falsely conclude the app is broken.
Wait for readiness one of two ways:
- Preferred: use the tool to tail the background process and wait for a line containing or
Local: http://localhost:3000
. That is Next's own signal that the port is bound.
- Fallback: retry the HTTP check 5 times with a 2-second pause between attempts. Treat connection-refused as "not ready yet, retry"; treat any HTTP response (even 500) as "the server is up, now check the body".
Then verify three things:
- The process is still alive. A dev server that crashed during boot will not respond — check the background process output before concluding.
- HTTP 200 from . Use the Bash tool:
bash
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000
On Windows without curl, fall back to PowerShell via the PowerShell tool: (Invoke-WebRequest -Uri http://localhost:3000 -UseBasicParsing).StatusCode
.
- No fatal errors in the dev server's stdout/stderr — scan the background output for stack traces, DB connection refusals, or missing-env-var warnings.
If any of these fail, common causes to call out:
- Port 3000 already in use — another process is bound to it. Tell the user, and either kill the other process or run .
- Database connection refused — Docker container stopped, wrong , or the hosted DB is paused. Re-check Step 6.
- missing or weak — re-check Step 5 and regenerate.
Fix the failure before claiming success — a half-running app is worse than an honest error.
12. Report Success
Tell the user, in this order:
- The app is live at http://localhost:3000.
- Where is (absolute path) and a one-line summary of which integrations are set versus blank — for example: "auth secret set, Postgres set (Docker), OpenRouter set, Blob/Polar/email blank".
- A starter prompt they can paste into the agent to begin building their actual app. Use this template (matches the README):
text
I am using the Agentic Coding Starter Kit. Treat the existing app as boilerplate that should be replaced by the product I describe.
Use the project instructions in AGENTS.md or CLAUDE.md. During planning, ask clarifying questions before making assumptions. During implementation, split the work into small chunks, use sub-agents where useful, follow DESIGN.md for UI, preserve the existing tech stack unless there is a good reason to change it, and run lint, typecheck, and build before finishing.
What I want to build:
[Describe your app here]
- A pointer to the three files that will drive future agent behavior in this project: , , and .
Keep this final message short — the user wants to start building, not read a wall of text.
Publishing Note
If the user asks how other people can install this skill, the answer is:
bash
npx skills add <owner>/<repo>@create-agentic-app --agent claude-code
The
flag is required — without it, the installer drops the skill into 37+ IDE adapter folders at the project root, which is rarely what anyone wants.