skills/tap-scaffolding/SKILL.md
Modify or extend the `jwa-tobrew` scaffolding system — the templates that `init` writes into target projects. Trigger when the user says "add a new scaffold kind", "change what init writes", "update the templates", or asks how the embedded templates are wired.
npx skillsauth add jwa91/agentskills tap-scaffoldingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
init is the only command that writes files into target projects. Every scaffolded artifact has a corresponding contract enforced by align — that pairing is the system. If you change one without the other, align reports drift on freshly-scaffolded projects, which is the canary that something is misaligned.
tools/jwa-tobrew/
├── init.go runs scaffold; auto-detects kind; prints per-kind hints
├── templates.go //go:embed lines, one per template file
├── align.go the contract: alignProject() + alignTap()
└── templates/
├── goreleaser.yaml.tmpl Go projects only
├── release.sh.tmpl cask + formula projects (used to be two; unified in v0.3-ish)
├── cask.rb.tmpl cask .rb shape (used by writeNewTapFile in release.go)
├── formula.rb.tmpl formula .rb shape (single-asset; multi-platform formulas
come from source-repo GoReleaser, not from here)
Templates use Go's text/template syntax with double braces. To emit a literal {{ ... }} (e.g. for GoReleaser's own template variables in goreleaser.yaml.tmpl), wrap it: {{{{ .Version }}}}.
Only two functions write template-rendered files to disk:
init.go::writeTemplate(path, tmpl, data, force) — renders a template and writes. Refuses to overwrite unless force=true. Used by scaffold for release config files.release.go::writeNewTapFile — renders cask.rb.tmpl or formula.rb.tmpl and writes a brand-new tap entry. Always passes force=true because the file shouldn't have existed yet (add checks; release checks).scaffold itself does kind dispatch, then installs the generic release skill through agentskills:
switch kind {
case "go":
writeTemplate(".goreleaser.yaml", goreleaserTmpl, data, force)
case "cask", "formula":
writeTemplate("scripts/release.sh", releaseShTmpl, data, force)
chmod 0o755
}
writeAuxiliary(dir, force) // .env.template, .gitignore, agentskills bootstrap/link
Adding a new project kind (say node) is a 5-step recipe:
tools/jwa-tobrew/templates/<name>.tmpl (e.g. release-node.sh.tmpl).//go:embed line in templates.go and a var nodeReleaseTmpl string.init.go::detectKind to recognise the language marker (package.json, Cargo.toml, etc.) and return "node".init.go::scaffold with a case "node": branch that calls writeTemplate for the new template, plus a hint in the trailing per-kind switch.align.go::alignProject's switch with a case "node": that requires the same files (e.g. the new release script). This is what closes the loop: a freshly-scaffolded project must satisfy align immediately, otherwise the scaffold is incomplete.Then update the tap-alignment skill if the convention is interesting, and add a CHANGELOG entry. Run jwa-tobrew init --kind=node in a scratch dir, followed by jwa-tobrew align, to verify the contract closes.
If every project needs a new file (say .editorconfig):
templates/editorconfig.tmpl and a //go:embed line.init.go::writeAuxiliary (not scaffold) with a writeTemplate call. writeAuxiliary is the place for shared-across-kinds artifacts.align.go::alignProject with the corresponding existence check, outside the per-kind switch.prek.toml's jwa-tobrew-align hook regex if the new file's path isn't already covered.Anything
initwrites is somethingalignenforces. Anythingalignenforces is somethinginitwrites (or the user is told what to run, when auto-create isn't safe).
This is what makes the system honest. If you add an align rule without a scaffold for it, users get findings they can't auto-fix. If you add a scaffold without an align rule, users can drift away from the convention silently. Always update both in the same commit, and verify by scaffolding into a scratch dir + running align immediately after.
.goreleaser.yaml for non-Go projects — they don't use it.scripts/release.sh for Go projects — they don't use it; goreleaser release --clean is the entire pipeline locally and in CI.init. The scaffold-cli skill describes the recommended release.yml for tag-driven CI release.SECURITY.md, CHANGELOG.md, CODEOWNERS — repo-level files, not project-level. Owned by the repo's own conventions, not by jwa-tobrew init.LICENSE — too opinionated to template; user picks.go build ./tools/jwa-tobrew && go vet ./...mkdir /tmp/scratch-cli && cd /tmp/scratch-cli && git init && go mod init test && /path/to/jwa-tobrew init --kind=go --name=test --desc="test"jwa-tobrew align in the scratch dir — must report no driftprek run --all-files in the tap repo — must passdata-ai
Release the current project to the personal Homebrew tap from repo-local release config. Use when the user says "release", "ship", "cut a version", "publish", "make a new tag", or asks how to make a new version available via jwa91/tap.
tools
Use the `jwa-harden` CLI for secret-safe command execution, env-template discovery, and signing/notarization preflight checks. Trigger when a command needs secrets, when `.env.template` or 1Password references are involved, or before signed release flows.
development
Detect and fix drift between a project and the conventions encoded in `jwa-tobrew`, prek, and the tap ADRs. Trigger when the user says "align", "any drift", "verify conventions", or asks why a particular file/symlink/script is required.
tools
Advise on the stack for a new project. Given what the user wants to build, plus the user's principles and preferences, propose a language + tools as a short written proposal. Use when starting a new project or deciding what to build something in.