Copier-first template for creating production-ready pi extension repositories.
This same README is used on npm (
@tryinget/pi-extensions-template_copier).
- Copier — templating engine used for scaffold generation.
Run directly without global install:
npm exec --yes --package @tryinget/pi-extensions-template_copier -- \
new-pi-extension-repo <repo-name> [command-name] \
[--target-dir <path>] \
[--github-maintainer <handle>]Install once, then run:
npm install -g @tryinget/pi-extensions-template_copier
new-pi-extension-repo <repo-name> [command-name] \
[--target-dir <path>] \
[--github-maintainer <handle>]copier copy --trust --vcs-ref HEAD ~/programming/pi-extensions/pi-extensions-template_copier ~/programming/pi-extensions/<repo-name> \
-d repo_name=<repo-name> \
-d command_name=<command-name> \
-d github_maintainer=<github-handle>If you publish under a different npm scope/name, update package.json first.
This package also ships npm-bootstrap-publish for first-time package publishes.
It creates a temporary .npmrc, runs publish, waits for registry propagation (30s default), retries verification, then cleans up credentials.
# token from 1Password CLI
npm-bootstrap-publish --project ~/programming/pi-extensions/pi-evalset-lab --op op://dev/npm-publish/token
# token from env var
NPM_TOKEN=... npm-bootstrap-publish --project ~/programming/pi-extensions/pi-evalset-labYou can run it without global install too:
npm exec --yes --package @tryinget/pi-extensions-template_copier -- \
npm-bootstrap-publish --project ~/programming/pi-extensions/pi-evalset-lab --op op://dev/npm-publish/tokenA local wrapper function is installed at:
~/.bashrc.d/functions/npmbp.bash
npmbp delegates to npm-bootstrap-publish (global binary if installed, otherwise this repo's bin/npm-bootstrap-publish.mjs) and defaults --project to your current directory.
npmbp-dry is the same wrapper but forces --dry-run unless you already passed it.
# from inside a package repo
npmbp --op op://dev/npm-publish/token
# safer preflight (dry-run)
npmbp-dry --op op://dev/npm-publish/token
# explicit project path
npmbp ~/programming/pi-extensions/pi-evalset-lab --op op://dev/npm-publish/tokenIf you want the old command shape, use:
bash ~/programming/pi-extensions/pi-extensions-template_copier/new-pi-extension-repo.sh <repo-name> [command-name]The wrapper is intentionally thin: argument validation + copier copy invocation.
When run from this template git checkout, it defaults to --vcs-ref HEAD so local changes are included.
For reproducible generation, pin a tag/commit explicitly:
PI_TEMPLATE_REF=v0.1.0 \
bash ~/programming/pi-extensions/pi-extensions-template_copier/new-pi-extension-repo.sh <repo-name> [command-name]Set a maintainer handle at generation time (optional):
PI_GITHUB_MAINTAINER=tryingET \
bash ~/programming/pi-extensions/pi-extensions-template_copier/new-pi-extension-repo.sh <repo-name> [command-name]The wrapper refuses to generate from a dirty template repo by default. Override only for local experiments:
ALLOW_DIRTY_TEMPLATE=1 \
bash ~/programming/pi-extensions/pi-extensions-template_copier/new-pi-extension-repo.sh <repo-name> [command-name]Template files live under copier-template/, configured by copier.yml.
Generated scaffold includes:
- package extension entrypoint in
extensions/<command-name>.ts - governance docs +
system4dfrontmatter - unified quality gate lane:
- Biome baseline:
biome.jsonc+.vscode/settings.json+ pinned@biomejs/biome scripts/quality-gate.shstages:pre-commit,pre-push,ci- hooks:
.githooks/pre-commit,.githooks/pre-push - npm scripts:
fix,quality:pre-commit,quality:pre-push,quality:ci
- Biome baseline:
- repo-local commit prompt:
.pi/prompts/commit.md
- docs discovery wrapper:
scripts/docs-list.sh- npm scripts:
docs:list,docs:list:workspace,docs:list:json
- release + security baseline:
.github/workflows/ci.yml.github/workflows/release-check.yml.github/workflows/release-please.yml.github/workflows/publish.ymlscripts/release-check.sh.release-please-config.json,.release-please-manifest.json.github/dependabot.yml,.github/CODEOWNERSSECURITY.md,LICENSE
- community intake baseline:
.github/ISSUE_TEMPLATE/{bug-report,feature-request,docs,config}.yml.github/pull_request_template.mdCODE_OF_CONDUCT.md,SUPPORT.md,CONTRIBUTING.md
- vouch trust gate baseline:
.github/VOUCHED.td(seeded fromgithub_maintainer; defaults to the current GitHub user when detectable).github/workflows/vouch-check-pr.yml.github/workflows/vouch-manage.yml
TypeScript lane reference (for generated repos):
uv tool run --from ~/ai-society/core/tech-stack-core tech-stack-core show pi-ts --prefer-repo- pinned lane metadata:
policy/stack-lane.json
This repository is the Copier template source, not a generated extension repo.
- Treat
copier-template/as the source of truth for scaffolded files. - Edit template behavior via
copier-template/**,copier.yml, and wrapper scripts. - Do not run
copier copy ... .into this repo root. - Do not commit a root
.copier-answers.ymlin this repo.
Install local pre-commit guardrails once:
bash ./scripts/install-hooks.shSmoke-test template changes by generating to a temp directory:
bash ./scripts/smoke-test-template.shGenerated repo contract check (required include/exclude paths + placeholder leak scan):
bash ./scripts/generated-contract-test.shContract rules live in contract/generated-repo.contract.json (versioned in git).
Run with custom names to test edge inputs:
CONTRACT_REPO_NAME=template.contract \
CONTRACT_COMMAND_NAME=feature-alpha \
bash ./scripts/generated-contract-test.shGenerated repo idempotency check (copier update fallback recopy):
bash ./scripts/idempotency-test-template.shCode metadata discovery (top-level comments in programming files):
node ./scripts/code-list.mjs
node ./scripts/code-list.mjs --json
node ./scripts/code-list.mjs --strictExpected top-level comment keys:
summary:one-line purposeread_when:list of hints for when to read that file
Manual invariant check:
bash ./scripts/template-guardrails.shCI guardrails in this repo run invariant checks, smoke generation, generated-contract assertions across name-variant matrix cases, and idempotency verification. On failures, CI uploads forensics artifacts (logs + generated temp repo) for debugging.
Template-source npm publishing uses:
.github/workflows/release-check.yml.github/workflows/release-please.yml.github/workflows/publish.yml.release-please-config.json,.release-please-manifest.jsonscripts/release-check-template.sh
Local preflight:
npm run check:full
npm run release:check
# quick artifact-only mode:
npm run release:check:quickTrusted-publishing learnings captured in this template:
- release-please uses
vX.Y.Ztags (include-component-in-tag: false) so publish trigger logic stays consistent. - release-please workflow uses
googleapis/release-please-actionv4.4.0 (SHA pinned) and no deprecatedcommandinput. - publish workflow and release-check workflow both upgrade npm (
>=11.5.1) for consistent trusted publishing behavior. - setup-node uses
package-manager-cache: falseto avoid implicit caching behavior changes from setup-node v5+. - setup-node v6 / setup-python v6 / upload-artifact v6 require Actions Runner
>=2.327.1on self-hosted runners (GitHub-hosted runners already satisfy this). - release-check script tolerates npm
already published versiondry-run responses for post-release idempotency. - package metadata must include
repository.urlmatching the GitHub repo for npm provenance verification. - for GitHub repos using this template, ensure Actions policy allows external actions and workflow permissions are
Read and writewith PR creation enabled. - first-time npm package bootstrap may still require one token-based publish before configuring npm trusted publisher on package settings.
Generated repos include .copier-answers.yml and should commit it.
- Run from a clean destination repo (commit or stash pending changes first).
- Use
copier update --trustwhen.copier-answers.ymlincludes_commitand update is supported. - In non-interactive shells/CI, append
--defaultsto update/recopy. - Use
copier recopy --trustwhen update is unavailable (for example local non-VCS source) or cannot reconcile cleanly. - After recopy, re-apply local deltas intentionally.
- After update/recopy, run
npm run check.
The scripts/update-generated-repos.sh script updates all generated repos under a root directory:
# Preview changes (dry-run)
bash ./scripts/update-generated-repos.sh --ref v0.3.0 --dry-run
# Update all repos with pre/post commits
bash ./scripts/update-generated-repos.sh --ref v0.3.0 --pre-commit --post-commit
# Parallel processing (requires GNU parallel)
bash ./scripts/update-generated-repos.sh --ref v0.3.0 --pre-commit --post-commit --parallel 4Options:
--ref <tag|HEAD>— template version to apply (required)--root <dir>— directory containing generated repos (default:~/programming/pi-extensions)--check-cmd <cmd>— validation command (default:npm run check)--pre-commit— commit dirty state before update--post-commit— commit changes after successful update--dry-run— preview without making changes--parallel <N>— process N repos concurrently (requires GNU parallel)
The script tries copier update first, then falls back to copier recopy if update fails. It stops on first failure and prints a summary table.
Using just:
just update-dry v0.3.0 # dry-run
just update v0.3.0 # with pre/post commits
just update-parallel v0.3.0 4 # parallel- Ensure template repo is clean (
git status). - Run local preflight:
npm run check:fullnpm run release:check
- Confirm GitHub Actions repo settings:
- workflow permissions:
Read and write - allow GitHub Actions to create/approve PRs
- allowed actions policy permits marketplace actions used by workflows
- workflow permissions:
- Commit template changes with Conventional Commit messages.
- Push to
mainand let release-please open/update the release PR. - Merge the release PR, then publish from the GitHub Release (
vX.Y.Z) via workflow. - If this is a brand-new npm package, do one bootstrap token publish, then configure npm trusted publisher.
- Prefer
PI_TEMPLATE_REF=vX.Y.Zin automation for deterministic generation.
copiermust be installed (pipx install copier,uv tool install copier, orpip install copier).- Post-copy tasks in
copier.ymlset executable bits, rungit init, and configure git hook path.