Skill v1.0.1
currentAutomated scan100/100+4 new
version: "1.0.1" name: scaffold license: MIT description: >- Project-aware file generation. Reads existing codebase conventions (naming, structure, imports, exports, test patterns) then generates new files that match exactly. Wires generated files into the project's registration points. user-invocable: true auto-trigger: false trigger_keywords:
- scaffold
- generate component
- generate module
- generate service
- new component
- new module
- new route
- new service
- create component
- stub out
- bootstrap
/scaffold — Project-Aware File Generator
Orientation
Use when: Creating a new component, module, service, route, hook, domain, or utility with existing examples in the project.
Do NOT use when: The file has no precedent (use /marshal for unconstrained generation), you're modifying existing files (use /refactor), or the project has no conventions yet.
Needs: target type, name, and optional description.
Protocol
Step 1: IDENTIFY THE TARGET
Parse the user's request into:
- type: component | module | service | route | hook | domain | utility | custom
- name: the name the user gave (e.g., "UserProfile", "auth-service", "settings route")
- description: what it does, if provided (otherwise leave blank for now)
If the type is ambiguous, ask ONE clarifying question. Do not ask more than one.
Step 2: FIND EXEMPLARS
Search the codebase for 2-3 existing files of the same type.
Search strategy by type:
| Type | Search Pattern | What to Look For | |
|---|---|---|---|
| component | **/*.tsx in the same directory or sibling directories | Functional components with similar complexity | |
| module | Same directory as where new module will live | Registration pattern, exports, config shape | |
| service | **/services/**, **/lib/** | Class vs function, singleton vs factory, error handling | |
| route | Router config files, **/routes.*, **/pages/** | Route definition format, lazy loading, guards | |
| hook | **/hooks/**, **/use*.ts | Naming, parameter patterns, return types, cleanup | |
| domain | Top-level domain/feature directories | Manifest structure, entry point, internal layout | |
| utility | **/utils/**, **/helpers/** | Pure function style, type signatures, JSDoc |
For each exemplar, extract:
- File naming convention (PascalCase, kebab-case, camelCase, snake_case)
- Directory placement (co-located with component? separate
hooks/dir?) - Import style (path aliases? relative? named imports? default exports?)
- Export style (named exports? default? re-exported from barrel/index file?)
- Internal patterns (how state is managed, how errors are handled, JSDoc or no)
- Test co-location (
.test.tsnext to file?__tests__/directory? separatetests/tree?) - Types pattern (inline? separate
.types.ts? shared types file?)
Output a brief analysis (3-5 lines) summarizing the conventions you found.
Step 3: DETERMINE THE FILE SET
Based on the exemplars, determine which files to generate. Not every project needs every file. Only generate what the project's conventions call for.
Decision matrix:
| File | Generate IF... | |
|---|---|---|
| Main file | Always | |
Types file (.types.ts) | Project separates types into their own files (check exemplars) | |
Test file (.test.ts) | Project has co-located tests for this type of file | |
| Barrel/index file | Project uses barrel exports AND this file's directory doesn't already have one | |
| Barrel update | Project uses barrel exports AND the directory already has an index file | |
Style file (.module.css, .styled.ts) | Project uses co-located styles for this type | |
Storybook file (.stories.tsx) | Project has stories for this type of file |
Do NOT generate:
- Empty placeholder files with only a TODO comment
- Test files that only contain
describe('...', () => { it.todo('...') }) - Types files that only re-export from elsewhere
- Any file type the project doesn't already use
Step 4: GENERATE THE FILES
For each file in the set, generate content by adapting the closest exemplar.
Rules:
- Match the exemplar's structure exactly — same section order, same patterns
- Replace names and specific logic, keep structural patterns
- Every generated file must be syntactically valid and importable
- No placeholder comments (
// TODO: implement,// Add logic here) - No empty function bodies unless the exemplar has them
- Minimal but functional — renders something, has at least one real method, returns a typed value
- Match the project's TypeScript strictness
Match the exemplar's props pattern, state management, utility imports, async patterns, and error handling exactly.
Step 5: WIRE IT IN
Find every registration point the exemplars use and add the new file there.
Common wiring points (check which ones the project uses):
| Wiring Point | How to Find It | What to Add | |
|---|---|---|---|
| Barrel exports | index.ts in the same or parent directory | export { NewThing } from './NewThing' | |
| Route registration | Router config file (search for exemplar's route) | New route entry matching the pattern | |
| Module registry | Bootstrap/registration file | New registration call | |
| Navigation/sidebar | Nav config array | New nav entry if appropriate | |
| Lazy loading map | Dynamic import map | New lazy import entry | |
| Type unions | Discriminated unions that list all variants | New variant if this is a new "type" of thing |
Rules:
- Only wire into registration points that the exemplars actually use
- Match the exact format — same spacing, same trailing commas, same comments
- If a registration point uses alphabetical ordering, maintain it
- Never create new registration points — only add to existing ones
Step 6: VERIFY
Run typecheck — every generated file must pass. Fix failures before exiting. If typecheck is unavailable, do a manual read-through for syntax and import correctness.
Fringe Cases
- Target directory or file already exists: Do not silently overwrite. Confirm with the user before proceeding. Output: "A file at
{path}already exists. Overwrite it?" and wait for confirmation. - Template or exemplar not found: List the available file types in the codebase and ask which one to use as the exemplar. Never scaffold from memory if no exemplar exists.
- Language or framework not detected: Ask the user directly rather than guessing. One question: "What type of file should this be? (e.g., React component, Express route, utility function)"
- Typecheck fails after generation: Fix the issue before exiting — do not leave the user with broken generated files.
- No wiring point found: Note the missing registration explicitly in the exit summary rather than silently leaving the file unwired.
Contextual Gates
Reversibility: Amber — creates new files and modifies registration points; git checkout to undo. Cost: No cost actions — file generation only; no agents spawned, no confirmation needed. Trust: No gates — safe at all trust levels; overwrite confirmation is in Fringe Cases.
Quality Gates
All of these must be true before the skill exits:
- [ ] Found 2+ exemplar files of the same type in the project
- [ ] Generated files match the project's naming convention exactly
- [ ] Generated files match the project's import/export style exactly
- [ ] No placeholder comments, TODO stubs, or empty function bodies
- [ ] Every generated file is syntactically valid TypeScript/JavaScript
- [ ] Main file is wired into the project (barrel export, route, registry, etc.)
- [ ] Test file exists IF AND ONLY IF the project co-locates tests for this type
- [ ] Types file exists IF AND ONLY IF the project separates types for this type
- [ ] Typecheck passes (or manual verification if typecheck unavailable)
Exit Protocol
Output a summary in this format:
SCAFFOLD COMPLETECreated:- path/to/MainFile.tsx (component)- path/to/MainFile.test.tsx (test)- path/to/MainFile.types.ts (types)Wired into:- path/to/index.ts (barrel export)- path/to/routes.ts (route registration)Conventions matched from:- path/to/ExemplarA.tsx- path/to/ExemplarB.tsxTypecheck: PASS
---HANDOFF---- Scaffolded: {name} ({type})- Created: {N} files, wired into {N} registration points- Conventions matched from: {exemplar names}- Reversibility: green -- new files only, delete to undo---