project-bootstrapper
Skill1 starsChanged 4 months agoMITView on GitHub
Turn a clone of the project-template repo into a real, named project, or add a new package to one that already exists. Handles project identity, package scaffolding from the pyproject/tach examples, .env and sandbox setup, skill syncing, Dockerfiles, OpenWiki regeneration, and a full verification pass. Triggers on "bootstrap this template", "set up a new project", "start a new project from the template", "scaffold a new package", "add a package", "initialise the repo", "new service", "new microservice".
- Reads credentials
- Deletes or force-pushes
5 other projects use a version of this.
Adopted by
Most recently taken up by
- OpenxIntelligence/Coding-Agent-Skillstheir own version, first seen Nov 1, 2026
- I-Onlabs/claude-code-skillstheir own version, first seen Oct 25, 2026
- nek1987/auto-agent-harnesstheir own version, first seen Oct 11, 2026
- adriaalcala/claude-code-setuptheir own version, first seen Sep 24, 2026
- rm2thaddeus/Aitor_Skillstheir own version, first seen Jan 22, 2026
Other versions5 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 5
- I-Onlabs/claude-code-skills★ 4same name
- nek1987/auto-agent-harness★ 4same name
- OpenxIntelligence/Coding-Agent-Skills★ 4same name
- rm2thaddeus/Aitor_Skills★ 4same name
- adriaalcala/claude-code-setup★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository5 other files it gives its agents.
- code-reviewerSkill
- designdoc-creatorSkill
- feature-coderSkill
- python-async-scalingSkill
- python-tutorSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
18 rules. 0 are common, 4 are distinctive, and 14 are very specific to this project.
0
Common
Most of the 5 edited versions we read keep these.
4
Distinctive
This author's own choices. Worth a look.
14
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 47
If the target directory is empty or does not exist yet, create the project first with git clone …
- Distinctive: line 91
Never start editing before this phase completes.
- Distinctive: line 111
If they decline, carry on and list it as skipped in the final report.
- Very specific: line 158
Run sh bootstrap.sh <project-name> to do the mechanical rename (mv README_TEMPLATE.md README.md and set package.json's "name") in one shot.
- Very specific: line 166
If bootstrap.sh isn't in the clone or failed, do both steps by hand: mv README_TEMPLATE.md README.md (Bootstrap only) and set package.json …
- Very specific: line 171
If the user asked for a history reset: rm -rf .git is commonly blocked outright by sandboxed permission configs (categorically, no …
- Very specific: line 180
Delete openwiki/.last-update.json — it pins the *template's* gitHead and would otherwise be carried into the new project as false …
- Very specific: line 197
Write 3.13 to {package_name}/.python-version.
- Very specific: line 199
Write src/{package_module}/__init__.py and, for a service, a main.py entrypoint that calls configure_logger("INFO") exactly once — per …
- Distinctive: line 203
Write a short README.md for the package: what it is, its public surface, and the three taskipy commands.
- Very specific: line 207
Never fork the logger package into the new one.
- Very specific: line 210
Check packages/data-utils/ before writing any helper or schema — anything reused across packages belongs there, not in a service package.
- Very specific: line 221
If the user is on macOS and wants the sandbox profile: sed "s|__HOME__|$HOME|g" claude-sandbox.sb > ~/claude-sandbox.sb and print the alias …
- Very specific: line 234
If the user named a first feature, cp docs/DESIGN_DOC_TEMPLATE.md {FEATURE_NAME}.md at the repo root and pre-fill the title, Background, …
- Very specific: line 238
If OpenWiki was requested and GEMINI_API_KEY is set: npx openwiki --init, then review the generated pages before staging them.
- Very specific: line 273
Commit with a chore: or feat: message describing the project or package, per CLAUDE.md's commit conventions: no assistant or employer …
- Distinctive: line 293
Don't invent structure: Create only the directories the user asked for.
- Very specific: line 295
Don't add skills locally: If a needed skill is missing, add it to the skillset repo.
“Common” is measured: kept by at least 6 in 10 of the 5 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Project Bootstrapper
Bootstraps a clone of the project-template monorepo into a working project,
and scaffolds new packages inside an already-bootstrapped one. Everything in the
template README's "Quick start — bootstrap your own repo" section, plus the identity,
hygiene, and verification work that section leaves to the reader.
External dependencies
None of these can be assumed to exist locally. Fetch them from their public GitHub repos; never go looking for a sibling checkout on disk.
| Dependency | Source | How it is fetched |
project-template | https://github.com/konrad-woj/project-template.git | git clone (Bootstrap target, Adopt reference) |
skillset | https://github.com/konrad-woj/skillset.git | sh sync_skills.sh (Phase 4) |
logger | https://github.com/konrad-woj/logger.git | uv sync, via [tool.uv.sources] in each pyproject.toml |
ponytail | https://github.com/DietrichGebert/ponytail | Claude Code plugin, installed in Phase 0 |
When to use this
| Situation | Mode |
| Empty or not-yet-existing target directory | Bootstrap, after cloning the template into it |
Fresh clone of project-template, no real packages yet | Bootstrap |
| Real project content (README, LICENSE, a package dir) but no template scaffold | Adopt |
| Named project already, needs another service package | Add package |
| Neither — repo is unrelated to the template | Don't use this skill |
Detect the mode before doing anything: the repo is still un-bootstrapped (Bootstrap) if
README_TEMPLATE.md exists, package.json still has "name":
"project-template", or the only package directories under
packages/ are data-utils, example-library and example-service.
If the target directory is empty or does not exist yet, create the project
first with git clone https://github.com/konrad-woj/project-template.git
<target-dir>, then continue in Bootstrap mode from inside <target-dir>.
Phase 1 repoints origin and optionally resets history.
It's Adopt instead of Bootstrap if the repo was never actually cloned from
project-template — it has its own real README/LICENSE/docs (not the
template's placeholders) but is missing the scaffold itself: no
package.json, no CLAUDE.md, no packages/*/pyproject.toml, no
run_on_each.sh/sync_skills.sh. This happens when a repo was hand-created
or bootstrapped some other way and the user now wants the template's
conventions layered in. Don't rediscover the scaffold file-by-file: clone a
read-only reference copy of the template into a scratch directory, outside
the target repo:
git clone --depth 1 https://github.com/konrad-woj/project-template.git <scratch-dir>/project-templateThen port these files from it verbatim, unmodified, before touching anything else:
package.json, package-lock.json, CLAUDE.md, AGENTS.md, .gitignore,
.markdownlint.json, .dockerignore, Dockerfile.example, claude-sandbox.sb,
bootstrap.sh, run_on_each.sh, sync_skills.sh, .env.example,
docs/DESIGN_DOC_TEMPLATE.md, .github/workflows/ci.yml,
.github/workflows/openwiki-update.yml, packages/pyproject.toml.example,
packages/tach.toml.exampleAlso port packages/data-utils/ as a whole directory if the user opted in to
it in Phase 0.
Then continue into Phase 1 as normal, with two differences: treat the
existing README/LICENSE/git history as real project content to build on, not
template artifacts to discard (don't port README_TEMPLATE.md — its presence
would make the repo look un-bootstrapped; write README.md fresh, modeled on
the reference clone's README_TEMPLATE.md), and only change CLAUDE.md's title line rather than
copying its whole "New Project Setup"/"Code Structure" section verbatim if
the repo already documents its own conventions differently.
Phase 0 — Preflight and inputs
Never start editing before this phase completes.
- Check the toolchain.
uv --version,node --version,git --version,npx --version. Python must be 3.13 (uv python list). If anything is missing, stop and say exactly what to install — do not silently degrade. - Check the remote dependencies are reachable.
git ls-remote <url> HEADforproject-template,skillsetandlogger(see External dependencies).uv synccannot resolveloggerwithout GitHub access, so an unreachableloggeris a hard stop; an unreachableskillsetonly makes Phase 4's skill sync fail. Check the
ponytailplugin is installed. The template'sCLAUDE.mdpoints agents at/ponytail-reviewand/ponytail-audit. Ifclaude plugin listdoesn't showponytail, ask the user whether to install it, then run:claude plugin marketplace add DietrichGebert/ponytail claude plugin install ponytail@ponytailIf they decline, carry on and list it as skipped in the final report.
- Check the working tree is clean.
git status --short. If it is dirty, ask whether to proceed or stash; bootstrapping rewrites many files and a dirty tree makes the result unreviewable. - Read
CLAUDE.mdin the repo. It is the source of truth for conventions and overrides anything in this skill that conflicts with it. - Collect inputs by asking the user, in one round, not one at a time:
- Project name (kebab-case; becomes
package.json"name"and the README title). - One-line project description.
- Package(s) to create: for each, a kebab-case directory name, the importable module name (defaults to the directory name with underscores), and whether it is a FastAPI service, a worker, or a library.
- Whether to include
packages/data-utils(cross-package helpers for env access and JSONL I/O). Default yes — it's core reusable infra referenced elsewhere inCLAUDE.md— but ask rather than assuming, since an unused package is dead weight in a POC repo. Don't decide this mid-flight and let the user correct it after it's already written. - New git remote URL, and whether to reset history to a single initial commit.
- Which skills to sync from
skillset(default: whateversh sync_skills.shpulls with no arguments). - Whether to regenerate OpenWiki now (needs
GEMINI_API_KEY).
- Project name (kebab-case; becomes
Present a plan and get approval before writing anything. This is a hard gate, not a conceptual "sound good?" question — literally enumerate every file that will be created, renamed, or deleted, e.g.:
Create: packages/{package_name}/pyproject.toml packages/{package_name}/tach.toml packages/{package_name}/src/{package_module}/__init__.py ... Rename: README_TEMPLATE.md -> README.md Delete: openwiki/.last-update.jsonIn "Add package" mode this list is short; in "Bootstrap" or "Adopt" mode it is not — write it out in full anyway. A conceptual approval ("shall I port the scaffold in?") is not a substitute: it will not surface a decision like "skip data-utils" the way a concrete file list does, and the user ends up correcting it after the write instead of before.
Phase 1 — Project identity
- Run
sh bootstrap.sh <project-name>to do the mechanical rename (mv README_TEMPLATE.md README.mdand setpackage.json's"name") in one shot. In Adopt mode there is noREADME_TEMPLATE.md, so it only sets the name — writeREADME.mdfresh instead, modeled on the reference clone'sREADME_TEMPLATE.md. Either way, fill in the title, TL;DR, description, and the packages table from Phase 0's inputs. Leave{placeholder}markers only where the user has not decided yet, and list them in the final report. - If
bootstrap.shisn't in the clone or failed, do both steps by hand:mv README_TEMPLATE.md README.md(Bootstrap only) and setpackage.json"name"to the project name. - Replace template descriptions in
packages/*/pyproject.tomlthat still refer to the template rather than the project. - If the user asked for a history reset:
rm -rf .gitis commonly blocked outright by sandboxed permission configs (categorically, no confirmation prompt possible) — don't retry the same blocked call. Usefind .git -depth -deleteinstead (a depth-first delete that reaches the same end state without tripping anrm -rfblock), thengit init && git branch -M mainand set the new remote. Iffind -deleteis also blocked, ask the user to run the deletion themselves in their own terminal. Otherwise justgit remote set-url origin <new-url>and confirm the old template remote is gone (git remote -v). - Delete
openwiki/.last-update.json— it pins the template'sgitHeadand would otherwise be carried into the new project as false provenance.
Phase 2 — Package scaffolding
For each package from Phase 0, from packages/:
mkdir -p {package_name}/src/{package_module} {package_name}/tests/unit {package_name}/tests/integration {package_name}/docs. Addnotebooks/,evals/, andscripts/only if the user asked for them — empty directories that nobody uses are noise.evals/andscripts/need__init__.py;notebooks/does not.cp pyproject.toml.example {package_name}/pyproject.tomland populatename,description, and dependencies. Drop FastAPI/uvicorn from the dependency list for a library package. Uncomment and rename theapptask to the real module for a service.cp tach.toml.example {package_name}/tach.toml.- Write
3.13to{package_name}/.python-version. Don't copy it fromexample-service, which may already be deleted or never ported. - Write
src/{package_module}/__init__.pyand, for a service, amain.pyentrypoint that callsconfigure_logger("INFO")exactly once — perCLAUDE.md, configuration happens in the executable entrypoint and nowhere else. - Write a short
README.mdfor the package: what it is, its public surface, and the three taskipy commands. Do not restate the code. cd {package_name} && uv sync --all-groups && uv run tach sync --add.
Never fork the logger package into the new one. It comes from the shared git
repo via [tool.uv.sources], already present in the example pyproject.
Check packages/data-utils/ before writing any helper or schema — anything
reused across packages belongs there, not in a service package.
Phase 3 — Environment and secrets
cp .env.example .envat the repo root, and into each package that needs its own keys.- Never read, print, or echo the contents of a populated
.env. List which keys are unset by name only, and tell the user to populate them. - Confirm
.envis ignored:git check-ignore .envmust succeed. If it does not, fix.gitignorebefore continuing. - If the user is on macOS and wants the sandbox profile:
sed "s|__HOME__|$HOME|g" claude-sandbox.sb > ~/claude-sandbox.sband print the alias line for their shell rc. Do not edit their rc file without asking.
Phase 4 — Skills, Docker, and docs
sh sync_skills.sh [skill ...]. If it fails (no network, no repo access), report it and continue — it is not fatal to the bootstrap.- For each deployable service:
cp Dockerfile.example Dockerfile.{package_name}and replace every{package_name}and{package_module}placeholder. Verify none remain:grep -n "{package" Dockerfile.*must return nothing outsideDockerfile.example. - If the user named a first feature,
cp docs/DESIGN_DOC_TEMPLATE.md {FEATURE_NAME}.mdat the repo root and pre-fill the title, Background, and Revision History rows. Do not invent Goals — hand it back for the user to fill, or hand off to/designdoc-creator. - If OpenWiki was requested and
GEMINI_API_KEYis set:npx openwiki --init, then review the generated pages before staging them. If the key is missing, skip and say so.
Phase 5 — Verification
This phase is the point of the skill. Do not skip it, and do not report success without it.
sh run_on_each.sh -b "uv sync --all-groups --locked"
sh run_on_each.sh -b "uv run task ci"
npx --yes markdownlint-cli@0.49.1 '**/*.md' --ignore node_modules --ignore openwiki --ignore '**/.venv' --config .markdownlint.jsonThen check the things a green gate does not catch:
- Wheels are not empty. For every package with a
[build-system], runuv buildand list the wheel contents. A[tool.hatch.build.targets.wheel] packagesentry that does not match the realsrc/path produces an empty wheel with no error. Deletedist/afterwards. - No leaked identity. Grep the tree for the previous project's name, for
absolute home paths (
/Users/,/home/), and for{packageplaceholders. - No secrets staged.
git status --shortmust not list any.env. Rungit diff --cachedand scan for anything key-shaped before committing. - CI matrix covers the new package. The workflow discovers packages from
packages/*/pyproject.toml, so a package missing itspyproject.tomlis silently untested. Confirm the discovery command lists every package.
Fix what you can, then re-run the gate. Report anything you could not fix rather than lowering the bar — never delete a failing test or loosen a lint rule to get green.
Phase 6 — Commit and report
Commit with a chore: or feat: message describing the project or package, per
CLAUDE.md's commit conventions: no assistant or employer names, no
Co-Authored-By or Generated with trailers, and branch names prefixed
feature/, fix/, or chore/.
Close with a short report:
- Packages created and their module names.
- Env keys still unpopulated (names only).
- Anything skipped and why (no network, no API key, user declined).
- Remaining
{placeholder}markers inREADME.mdand the design doc. - The verification result, verbatim if anything failed.
Guardrails
- Ask before destroying. Resetting git history, overwriting a populated
.env, and deleting an existing package all need explicit confirmation, every time — regardless of which command performs the deletion. - Idempotent by default. Re-running on a bootstrapped repo must detect that and switch to "Add package" mode rather than re-templating the README.
- Don't invent structure. Create only the directories the user asked for.
The layout in
CLAUDE.mdis a permitted set, not a required one. - Don't add skills locally. If a needed skill is missing, add it to the
skillsetrepo..claude/skills/is vendored and gitignored; anything written there is lost on the next sync.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

