Fix empty scaffold, add agent skills and non-interactive flags - #1
Merged
Merged
Conversation
Templates moved out of the monorepo into strataljs/examples, where each one sits at the repo root instead of under examples/. giget resolves a missing subdirectory to an empty extraction rather than an error, so every scaffold silently produced an empty folder. Repoint the source and fail loudly when nothing is extracted. Also add the two examples that landed since (commands, inertia), install the Stratal agent skills into each new project by default with a --no-skills opt-out, and upgrade dependencies to current. TypeScript 7 no longer auto-includes @types packages, so tsconfig now names node explicitly. Yarn 4.12 could not fetch TypeScript 7 (its builtin compat patch expects lib/_tsc.js, which the Go rewrite does not ship), hence the yarn bump to 4.18.
npx is a .cmd there, which Node refuses to spawn from execFile without a shell since the CVE-2024-27980 fix. The failure was swallowed by the surrounding try/catch, so Windows users silently got no agent skills.
The package manager choice and the overwrite confirmation had no flags, so the CLI could not run unattended. Add --package-manager, --no-install, --force and --yes, and refuse to prompt at all when stdin is not a tty: anything still unanswered is reported as an error naming the flag to pass, so a run either completes or exits non-zero instead of hanging. Unknown options and missing flag values are now rejected too, rather than being silently ignored. Publishing moves to npm trusted publishing, which authenticates over OIDC and attaches provenance on its own, so the workflow needs no token and no --provenance flag. It also now typechecks and refuses to publish when the tag and the package version disagree.
giget merges into the target, so scaffolding one template over another left the previous project's files sitting alongside the new ones even though the prompt had offered to overwrite. Empty the directory first so --force means what it says. The template is staged in a sibling directory and moved into place only once it has downloaded, so a failed fetch no longer leaves the target emptied. A project name is now also rejected unless it resolves inside the current directory: "app/.." passes the character check but points at the directory the command was run in, which this would otherwise clear.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
npm create stratal@latest my-appcreated an empty folder and exited successfully.The examples moved out of the monorepo into
strataljs/examples, where each one sits at the repo root rather than underexamples/. The CLI still pointed atgithub:strataljs/stratal/examples/<dir>, and giget resolves a missing subdirectory to an empty extraction that exits 0 — so there was a folder, no files, and no error.Repointed the source, and added a guard that fails loudly when nothing is extracted. Also added the two examples that landed since:
commandsandinertia.Agent skills by default
Each new project now gets the Stratal agent skills —
.agents/skills/stratal, the.claude/skills/stratalsymlink andskills-lock.json. They are fetched at scaffold time rather than vendored into the package, the same way templates are, so they cannot go stale against the framework.--no-skillsopts out, and a failure there never fails the scaffold.Non-interactive use
The package manager choice and the overwrite confirmation had no flags, so the CLI could not run unattended. Added
--package-manager,--no-install,--forceand--yes.More importantly it now refuses to prompt at all when stdin is not a tty: anything still unanswered is reported as an error naming the flag to pass, so a run either completes or exits non-zero instead of hanging. Unknown options and missing flag values are rejected rather than silently ignored.
--forcereplacesgiget merges into the target, so scaffolding one template over another left the previous project's files alongside the new ones even though the prompt had offered to overwrite. The directory is now emptied first.
The template is staged in a sibling directory and moved into place only once it has downloaded, so a failed fetch no longer leaves the target emptied. A project name is also rejected unless it resolves inside the current directory —
app/..passes the character check but points at the directory the command was run in, which this would otherwise clear.Dependencies
@clack/prompts1.8.1,giget3.3.1,nypm0.6.10,@types/node26.6.2,typescript7.0.2.Two upgrades needed follow-ups:
typesto[], sotsconfig.jsonnow namesnodeexplicitly. Without it the build produced 21 errors.lib/_tsc.js, which the Go rewrite does not ship. Hence yarn 4.18. Script execution stays disabled; esbuild's binary arrives through its optional platform dependency, verified from a clean install.Publishing
Moved to npm trusted publishing, which authenticates over OIDC and attaches provenance on its own — no token and no
--provenanceflag. The job also typechecks now, and refuses to publish when the tag and the package version disagree.Verification
hello-world,crud-apiandinertia; all 18 declared templates confirmed to exist upstream.wrangler dev, and serves{"message":"Hello World"}/ HTTP 200.npm pack, so the published artifact is exercised, including thebinwiring.--forceremoves files from a previous template; a failed download leaves the target untouched and no staging directory behind.One behaviour change worth noting for Windows:
installSkillsspawnsnpxthrough a shell there, becausenpxis a.cmdthat Node has refused to spawn fromexecFilesince the CVE-2024-27980 fix. Previously this failed silently and Windows users got no skills. That fix is reasoned from the Node behaviour and has not been executed on Windows.