Create the repo, and scaffold into non-empty directories#12
Conversation
Packkit assumed a greenfield empty directory, but the real workflow is "the repo already exists" — either you made it, or you cloned it. Two halves of the same gap. Create the repo --github creates the remote and pushes; --git-remote <url> does the same for GitLab/Bitbucket/Gitea/self-hosted. Shells out to `gh` rather than calling the API, so Packkit never reads, prompts for, or stores a token. Opt-in, and private unless --public — a wrong default here leaks source. The remote is resolved *before* generating, because the repository URL is baked into package.json links and README badges at generate time. Deriving it up front is what makes those badges point somewhere real in the first commit. Creation runs last, so a failure leaves a complete local project and a printed retry command rather than a half-state. Scaffold into a non-empty directory --merge writes what's absent and never overwrites; collisions are kept and reported. Separately, a directory holding only .git now counts as empty: `git clone` of a fresh repo left .git behind and the old check aborted on it, breaking create -> clone -> scaffold outright. That was the abort behind the reported "backup, move, restore" workaround. Both surfaces are exposed over MCP (merge/github/public), which is what moves packkit-mcp to 0.2.0. It now imports the shared side-effect layer via a new create-packkit/scaffold export instead of duplicating it, so "never overwrite" has one implementation. That import means packkit-mcp needs create-packkit >= 2.8.0, so sync-mcp-version.mjs now fails the release if the version being cut falls outside the range mcp declares — a patch bump would otherwise publish an MCP server that cannot install. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Found by creating a real repo: --github with --no-install pushed a project with no lockfile, and actions/setup-node's `cache: npm` errors outright when it can't find one. Every repo Packkit created that way was red on its very first CI run, which rather defeats the point of creating the repo for you. When a remote is being created and the install was skipped, write the lockfile without installing (~15s vs a full install). Yarn has no mode that works across its v1/v2+ split, so it warns instead of failing silently. Verified end to end: a freshly created private repo now goes green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Verified against real repos before merge. Created That test also caught a real bug. CI on the new repo failed immediately: Fixed by writing the lockfile without a full install (~15s) whenever a remote is being created and the install was skipped. Yarn has no mode that works across its v1/v2+ split, so it warns rather than pushing a repo that will fail. Re-verified on 41 tests pass. |
Implements the two items at the top of Next up. They're two halves of one gap: Packkit assumed a greenfield empty directory, but the real workflow is "the repo already exists" — either you created it, or you cloned it.
Create the repo
npx create-packkit ts-lib my-lib --github # private, pushed npx create-packkit ts-lib my-lib --github --public npx create-packkit ts-lib my-lib --git-remote git@bitbucket.org:me/my-lib.git--githubshells out toghrather than calling the REST API, so Packkit never reads, prompts for, or stores a token —ghalready owns those credentials. Opt-in, and private unless--public, since a wrong default there leaks source.The remote is resolved before generating. The repository URL is baked into
package.jsonlinks and README CI badges at generate time, so creating the repo afterwards would ship a first commit pointing at nothing. Verified:Creation runs last, so a failure leaves a complete local project plus a printed retry command rather than a half-state.
Scaffold into a non-empty directory
--mergewrites what's absent and never overwrites; collisions are kept and reported.Separately — and this is the more consequential fix — a directory holding only
.gitnow counts as empty.git cloneof a fresh repo leaves.gitbehind, anddirIsEmptyOrMissingcounted dotfiles, so the entire create → clone → scaffold flow aborted on the clone. That abort is what forced the "backup, move, restore" workaround in the field review; it was never an overwrite risk, it was a refusal to run.MCP
merge,github, andpublicare exposed onpackkit_scaffold, movingpackkit-mcpto 0.2.0. It now imports the shared side-effect layer through a newcreate-packkit/scaffoldexport instead of keeping its own copy, so "never overwrite" has exactly one implementation.That import means
packkit-mcprequirescreate-packkit >= 2.8.0.sync-mcp-version.mjsnow fails the release if the version being cut falls outside the range mcp declares — a patch bump would otherwise publish an MCP server that cannot install. Confirmed green at 2.8.0, red at 2.7.3.Testing
40 tests pass, including 5 new ones covering the
.git-only case, merge preservation (asserts original bytes survive), and nested writes. Manually verified: clean scaffold unchanged,.git-only dir scaffolds, non-empty aborts with exit 1,--mergepreserves modified files, push lands in a local bare repo,--github --no-gitrejected, MCP server starts and lists the new options.Not exercised: creating a real GitHub repo — that needs your account.
🤖 Generated with Claude Code