Scaffold CLI
Contract
| Field | Bound contract |
|---|---|
| Trigger | Create or scaffold a new TypeScript command-line package. |
| Authority | Reversible local: writes only inside a new project directory; rollback is deleting it. No remote repository, registry, credential, or publish mutation. |
| Side effect | Creates the project tree, installs dependencies with pnpm, and writes pnpm-lock.yaml. |
| Done | pnpm run check, pnpm test, pnpm run build, and one invocation of the built executable through the package-manager-resolved bin path all pass on Node.js 24; the lockfile is present and CI uses frozen installation. |
Inputs
- Project name: required, non-empty kebab-case.
- Parent directory: required and writable.
- Description: optional; defaults to
A TypeScript CLI tool. - Executable name: optional; defaults to the project name.
Procedure
Validate name, parent, Node 24, and pnpm 11. Stop if the target exists or the parent is not writable. Run
node --versionand require Node.js 24 (major version 24). Runpnpm --versionand require pnpm 11 (major version 11); record the exact pnpm version forpackageManager. Runpnpm exec tsc --versionafter install to confirm TypeScript 7 (major version 7). Done when: name, parent, Node major, and pnpm major are validated.Create the project directory and initialize Git. Create the target directory and run
git initso every later file removal or rollback is recoverable. Done when: the directory exists and Git is initialized.Write the project tree with pinned dependency versions and immutable CI action SHAs. Write the following files:
package.jsonwithtype: "module",engines.node: ">=24 <25",packageManager: "pnpm@<observed-version>",binmapping the executable todist/index.js, and scripts:build: tsdown,check: biome check . && tsc --noEmit,check:fix: biome check --write .,test: vitest run,release: changeset publish. Pin development dependencies to exact current versions:@biomejs/biome,@changesets/cli,@types/node,tsdown,typescript(pinned to^7), andvitest. Add no runtime dependency.tsconfig.jsonfor NodeNext with target and libES2024. Enablestrict,noUncheckedIndexedAccess,exactOptionalPropertyTypes,noImplicitOverride,noFallthroughCasesInSwitch,noPropertyAccessFromIndexSignature,noImplicitReturns,allowUnreachableCode: false,verbatimModuleSyntax,erasableSyntaxOnly,isolatedDeclarations,declaration, andoutDir: "dist". Includesrc/**/*.tsand excludedist.tsdown.config.tswithsrc/index.tsas the entry, Node 24 as the platform target, ESM output, declarations, and a clean output directory.biome.jsonfor Biome 2.5 with formatter, import organization, and recommended linter rules enabled. Excludedistand coverage output.src/index.tswith a Node shebang. Usenode:utilparseArgsto accept one optional positional name and export a pureformatGreeting(name: string): string;main(args: readonly string[]): numberprints that string and returns zero. Invokemain(process.argv.slice(2))only when the module is the process entry point.src/index.test.ts. Invoke the built command through the package-manager-resolved bin path (pnpm exec <executable-name> Adaornpx <executable-name> Ada) and assert exit code zero, empty stderr, and stdoutHello, Ada!. This test protects the package bin link, build output, argument parsing, and observable result. Do not invokenode dist/index.jsdirectly; the test must prove the bin link works..changeset/config.jsonwith the official@changesets/clikeys, accessrestricted, base branchmain, and patch internal dependency updates..gitignorefornode_modules/,dist/,coverage/, logs, local environment files, and editor output..github/workflows/ci.ymlfor pushes tomainand pull requests. Pin the Node.js 24 and pnpm 11 setup actions by immutable commit SHA (not floating tag). Runpnpm install --frozen-lockfile,pnpm run check,pnpm run build, andpnpm test.
Done when: all files are written with pinned dependency versions and immutable CI action SHAs.
Run install, check, build, and test. Run
pnpm install, thenpnpm run check,pnpm run build, andpnpm test. Confirmpnpm exec tsc --versionreports TypeScript 7. Confirmpnpm-lock.yamlexists. Done when: install, check, build, and test all pass and the lockfile is present.Invoke the built executable through the package-manager-resolved bin path and confirm the lockfile and frozen-install CI. Run
pnpm exec <executable-name> Ada(ornpx <executable-name> Ada) and confirm exit code zero and stdoutHello, Ada!. Confirm the CI workflow usespnpm install --frozen-lockfileand the action SHAs are immutable. Done when: the built executable invocation passes through the bin path, the lockfile is present, and CI uses frozen installation with pinned actions.
Failure and recovery
- Target exists: stop without writing.
- Wrong runtime or package-manager major: stop before creating the directory and report both observed versions.
- Install or verification fails: keep the target for diagnosis and report the first failing command. Rollback is deletion of this new Git-initialized directory only after the user requests it.
- Generated command is not executable: fix the shebang, bin mapping, or file mode and repeat the built-command test through the bin path; do not claim success from compilation alone.
Output
A new Node.js 24 TypeScript 7 CLI project with source, one integration test, strict compiler configuration, Biome configuration, tsdown build, Changesets configuration, frozen pnpm lockfile, and CI with pinned actions. Return the created path and the exact outputs of the check, test, build, and built-executable invocation through the bin path.