-
Confirm the name and the point of the template. The name becomes the directory and the
default package.json name, so keep it lowercase-kebab. Ask what the template is for if
it isn't obvious — that determines what gets added on top of basic.
-
Copy the reference toolchain. From the repo root:
templates/basic/{package.json,tsconfig.json,eslint.config.mjs,jest.config.mjs}
templates/basic/{.prettierrc.json,.prettierignore,.gitignore}
templates/basic/scripts/{config.mjs,dev.mjs,build.mjs,shell.mjs}
templates/basic/scripts/{nwbin.mjs,profile.mjs,devlock.mjs,pid.mjs}
templates/basic/.npmrc (nwjs flavour + shared download cache)
templates/basic/docs/ (keep the plans/ research/ debugging/ tree)
Copy scripts/ as a set. shell.mjs imports the other four, and the nwjs isolation rules
in the CLAUDE.md you are about to copy describe behaviour those files implement — take
one without the rest and the document starts lying.
Set name in the copied package.json to the template name. Leave the scripts alone
unless the template genuinely needs different ones.
-
Copy assets/CLAUDE.md to templates/<name>/CLAUDE.md, unchanged.
-
Append a template-specific section to that CLAUDE.md — and only that. It covers what
makes this template different: extra dependencies, extra directories, conventions that
don't apply elsewhere. Everything general already lives in the copied part.
-
Write the skeleton — and only the skeleton. public/index.html, src/main.ts, and
whatever the template is actually demonstrating. Include at least one jest test — a
template whose test command has nothing to run is a template that silently stops being
checked. Respect the comment rules in the CLAUDE.md you just copied; the template's own
source is the first example anyone reads.
A template with a default prompt implements none of that prompt. The prompt is the task
a future agent is given; anything already built is a task already done, and the run stops
testing what it was set up to test. That covers the whole domain, not just the finished
feature — no game loop for a game prompt, no grid or entity types, no "scaffolding they'll
need anyway", however obvious the shape looks from here. If in doubt, copy basic's counter
demo across unchanged as the placeholder and let the prompt do the rest. Guessing at the
foundation is the same mistake as building the feature, only harder to notice.
What the template does carry beyond basic is toolchain: a dependency the task genuinely
requires, a directory the conventions need, a config change. Those are inputs to the work,
not the work.
-
Add a short templates/<name>/README.md — one paragraph on what the template is for
and the command to stamp it.
-
Write the default prompt, if one was given. If the invocation supplied prompt text —
as the skill's arguments, or anywhere in the request ("…with the prompt: build a
spirograph") — save it to templates/<name>/prompt.md.
Save it verbatim. It is the input to a future run, not documentation of one. Do not
rewrite it, expand it, correct its grammar, split it into steps, or wrap it in headings
and preamble. Editing a prompt changes the thing being tested. The only additions allowed
are a trailing newline and, if the text is not already a markdown document, nothing else.
If no prompt was given, do not create the file — not an empty one, not a placeholder,
not a TODO. An absent prompt.md says "this template has no default task"; a stub says
"someone meant to write one", which is a different and untrue claim. Do not invent a
prompt to fill the gap, and do not ask for one unprompted; templates without a default
task are ordinary.
-
Verify before declaring done:
pnpm use-template <name> tmp-verify
cd instances/tmp-verify && pnpm check
Then delete instances/tmp-verify. If pnpm check fails, fix the template, not the
instance — the instance is a throwaway.
Confirm the copied CLAUDE.md is still the asset verbatim, with nothing but the appendix
added:
diff .claude/skills/create-template/assets/CLAUDE.md templates/<name>/CLAUDE.md
Every line must be a >. A < line means the asset moved on and this template did not.
If you wrote a prompt.md, confirm the stamped instance has it and that its bytes match
what the user supplied.
If the template changed anything under scripts/, run the repo's own pnpm test from the
root as well. It stamps two instances and runs their nwjs shells side by side, which is the
only thing that catches a shared port or a shared chromium profile.