Bootstrap new GitHub repositories with best practices, SOLID principles, and language-agnostic templates.
Creates fully configured repositories with:
- Team-based code ownership
- Branch protection rules
- Dependabot configuration
- Development and production environments
- Documentation templates
- Editor and Git configurations
- Conventional commits enforcement via pre-commit hooks
- Release Please workflow for automated semantic versioning
- Pre-commit linting workflow for PR and push (provider-aware: micromamba, mise, or system)
- AI code review with CodeRabbit and Claude (see AI Code Review)
- Makefile for local linting (
make lintvia selected environment provider) - SECURITY.md and CONTRIBUTING.md
- CodeQL security scanning workflow (language-aware)
- Vulnerability alerts and Dependabot security updates enabled automatically
Recommended: use a tenant-installed GitHub App (safer, short-lived installation tokens). Fallback: use a PAT when App setup is not available.
-
Create or use an existing GitHub App with the following minimum permissions:
Permission scope Level Required for ContentsRead and write Clone template, push initial commits AdministrationRead and write Create repos, configure settings, delete repos MetadataRead-only Read repository info (auto-granted) For organization repositories also add:
Permission scope Level Required for MembersRead-only Resolve org membership for team setup -
Install the App in each target user/org (tenant isolation). The App must be installed on every
app_ownervalue you intend to target. -
In the repository that runs bootstrap, set:
BOOTSTRAP_APP_PRIVATE_KEY(Actions secret — the PEM private key of the App)
-
When running the workflow, provide:
app_id(the numeric App ID, visible in the App's settings)app_owner(target tenant owner)
The workflow mints a short-lived installation token for that owner and uses it for all API calls.
Organization targets only: GitHub App installation tokens (server-to-server) cannot create repositories under a personal user account — this is a GitHub API constraint. The target
repo_ownermust be a GitHub Organization. For personal user account targets, use the PAT fallback (Option B) instead.
There are two ways to supply the token, listed from most to least recommended:
- Fork this repository or click Use this template → Create a new repository (for company use, create the fork/template repo inside your organization)
- Go to your fork → Settings → Secrets and variables → Actions
- Click New repository secret
- Name:
GH_PAT, Value: your token from step 1 - Click Add secret
The workflows will automatically pick up GH_PAT without any extra input.
If you are working in an enterprise or internal repository where you cannot add repository secrets, you can pass your token directly when triggering a workflow:
- Go to Actions → select the workflow → Run workflow
- Fill in the Personal Access Token (gh_token) field with your
ghp_…token
Security note: The token is immediately masked with
::add-mask::at the start of each job so it never appears in plain text in the workflow logs. Masking only prevents the token from being printed in logs; the raw workflow input value may still be visible in the run's inputs/metadata to anyone who can view the run. Prefer Option A — Repository secret whenever possible, and if you must use Option B, use a short-lived token with the minimum required scopes.
Note: internal visibility is only available for repositories inside a GitHub Organization.
Use private for personal account repositories.
Choose one of three methods to bootstrap a new repository:
Copy-paste ready launcher files:
examples/launcher-actions.yml(Actions) andexamples/launcher-terraform.yml(Terraform). Copy one into your repo's.github/workflows/and replaceBOOTSTRAP_OWNER.
Create a minimal launcher workflow in your own repo:
name: Bootstrap Repository
on:
workflow_dispatch:
inputs:
repo_name:
required: true
type: string
repo_owner:
required: true
type: string
jobs:
bootstrap:
# Replace {{BOOTSTRAP_OWNER}} with the GitHub user or org that owns this bootstrap repository.
uses: {{BOOTSTRAP_OWNER}}/github-bootstrap/.github/workflows/create-repository.yml@main
with:
repo_name: ${{ inputs.repo_name }}
repo_owner: ${{ inputs.repo_owner }}
env_manager: micromamba
node_version: "24"
java_version: "25"
visibility: private
app_id: ${{ vars.BOOTSTRAP_APP_ID }}
app_owner: ${{ inputs.repo_owner }}
allowed_repo_owners: ${{ vars.ALLOWED_REPO_OWNERS }}
require_cleanup_approval: true
secrets:
app_private_key: ${{ secrets.BOOTSTRAP_APP_PRIVATE_KEY }}This example calls the standard Actions bootstrap workflow (create-repository.yml).
If you prefer Terraform orchestration, call
.github/workflows/terraform-create-repository.yml instead.
Cleanup approval environment (required when
require_cleanup_approval: true): The default istrue. When enabled, the cleanup gate looks for abootstrap-cleanupenvironment in your launcher repository (not in the bootstrap repo). Create it before running:
- Your repo → Settings → Environments → New environment
- Name:
bootstrap-cleanup- Add required reviewers who must approve before a failed repo is deleted
If this environment does not exist and cleanup is triggered, the
cleanup-approvaljob will fail and the partially-created repository will not be deleted automatically. Setrequire_cleanup_approval: falseto skip approval and delete immediately on failure.
- Complete the Setup steps above
- Go to Actions → Create Bootstrap Repository
- Click Run workflow
- Enter repository name (required)
- Configure optional settings
- Run
-
Complete the Setup steps above
-
Go to Actions → Terraform Create Repository
-
Click Run workflow and fill in the inputs, or apply locally:
cd terraform terraform init terraform apply \ -var="github_token=ghp_yourtoken" \ -var="repo_name=my-new-repo" \ -var="repo_owner=my-org"
See terraform/README.md for full documentation.
Your new repository is created with all templates and settings.
You can also use this repository to configure a repository that already exists. Existing-repo setup is explicit and opt-in: each action has one responsibility, and file changes default to a pull request or plan mode instead of silently overwriting repository content.
Copy a launcher example into your launcher repository and replace
BOOTSTRAP_OWNER. The launcher files are the copy-paste source of truth for
caller-side inputs, secrets, and uses: syntax.
| Use case | Launcher example | Reusable workflow |
|---|---|---|
| General setup | examples/launcher-existing-repo.yml |
.github/workflows/setup-existing-repository.yml |
| CodeRabbit only | examples/launcher-coderabbit.yml |
.github/workflows/setup-coderabbit.yml |
| Labels and security | examples/launcher-security-labels.yml |
.github/workflows/setup-labels-and-security.yml |
| Agent instructions | examples/launcher-agent-templates.yml |
.github/workflows/setup-agent-instructions.yml |
For exact workflow inputs, secrets, and outputs, read the workflow_call block in
the reusable workflow file. For capability behavior, read the relevant composite
action metadata under .github/actions/.
Launcher workflows pass non-secret values as explicit inputs and private values as secrets from the launcher repository. Target repository access comes from the resolved GitHub App token or PAT.
For organization usage, prefer a GitHub App installation token. For personal repositories or local use, a PAT can be used as a fallback.
Typical permissions needed by the resolved token:
| Capability area | Required access |
|---|---|
| Repo settings/rulesets | Repository administration read/write |
| Security settings | Repository administration read/write; some features require GitHub plan support |
| Labels | Issue/label write access or repository administration access |
| File pull requests | Contents read/write and pull requests write |
CodeRabbit setup has one extra prerequisite: install the CodeRabbit GitHub App on the target repository. This toolkit can add the config file, labels, and optional ruleset, but it cannot universally install CodeRabbit for every tenant.
Local GitHub setup scripts live in scripts/github-setup/.
Use that folder's README as the entry point for local setup and live verification
guidance. Each script's --help output is the source of truth for command usage.
Creation workflow inputs live in the workflow metadata. Use the workflow files and launcher examples as the source of truth instead of duplicating input tables in this README:
.github/workflows/create-repository.yml.github/workflows/terraform-create-repository.ymlexamples/launcher-actions.ymlexamples/launcher-terraform.yml
Repository bootstrap now follows a clear separation of responsibilities:
- Orchestrator workflows:
.github/workflows/create-repository.ymland.github/workflows/terraform-create-repository.yml - Shared normalization contract:
tools/pkg/bootstrapinputsandtools/cmd/bootstrap-inputs - Reusable composite actions under
.github/actions/:render-precommit-configs,configure-provider-tooling-files,configure-release-tool,configure-codeql,apply-repo-settings, andapply-repository-ruleset - Manual E2E parity harness:
.github/workflows/test-repository-creation.yml
Use the test workflow's preset input to compare Actions and Terraform creation
paths. The preset list lives in the workflow file.
Editor configurations, Git settings, and ignore patterns that work across all languages and tools.
Code ownership rules and automated dependency updates. Vulnerability alerts and Dependabot automated security fixes are enabled on every created repository.
Project readme and AI assistant instructions (Agent, Claude, Copilot) following SOLID, TDD, and DDD principles.
- Pre-commit hooks — All quality checks run via
.pre-commit-config.yamlas the single source of truth - Selectable provider — choose
micromamba,mise, orsystemwhen creating repositories - Config file by provider —
environment.yml(micromamba),mise.toml(mise), or direct machine tooling (system) - Template layout (for maintainers) — provider assets live in
templates/languages/<language>/providers/<provider>/ - Template composition (for maintainers) — pre-commit source templates live in
templates/languages/*/pre-commit-snippets/and are rendered bytools/cmd/precommit-renderer - Root config behavior — generated root
.pre-commit-config.yamlfollows the first selected language so hooks match the provisioned toolchain - Monorepo behavior — generated
.pre-commit/languages/*.yamlfiles are emitted for all selected languages for explicit per-project opt-in - One linter per file type — prettier (JSON/YAML/Markdown), shellcheck + shfmt (shell), markdownlint, editorconfig-checker, yamllint, taplo (TOML), terraform fmt
- Local and CI —
make lintauto-fixes locally;LINT_MODE=check make lintfails on violations in CI - Language-specific linters — Add language linters to
.pre-commit-config.yamlas needed
To regenerate language template pre-commit files after snippet changes:
make render-precommitDependabot does not cover every tooling surface in this repository. For pinned tooling files
such as mise.toml, micromamba environment.yml, provider bootstrap binaries, and
pre-commit hook revisions, use:
make tooling-update-repo— update tooling pins for this repositorymake tooling-update-templates— update tooling pins undertemplates/for generated reposmake tooling-update-all— run both update pathsmake tooling-verify— verify layout assumptions and run updater unit tests before merging changesmake tooling-update-micromamba/make tooling-update-mise/make tooling-update-system/make tooling-update-precommit— run explicit modular updaters
Tooling commands automatically build the updater binary from latest source before execution, so users and AI agents always run the current implementation.
If Go is not installed on your machine, use ENV_MANAGER=micromamba or ENV_MANAGER=mise
and make will provision Go/tooling for you. ENV_MANAGER=system expects host tools to be
already installed.
The updater CLI also supports --verify-only for fast offline validation of expected
repository/template layout.
It also supports --updaters to run one or more decoupled updater modules.
Implementation lives in the monorepo tools module under tools/cmd/tooling-updater + tools/internal/ + tools/pkg/ and is built/executed from Make targets.
Automation is provided by .github/workflows/weekly-tooling-updates.yml:
- runs weekly and on manual dispatch
- opens or updates one PR with all non-Dependabot tooling updates
- enables PR auto-merge so GitHub merges only after required checks, required approvals, and repository merge requirements are satisfied
All repositories enforce conventional commits via pre-commit hooks:
- Commit format -
type(scope): description(e.g.,feat: add login,fix(auth): token refresh) - Allowed types -
feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert - Enforcement - Validated by the
conventional-pre-commithook on every commit
Every repository gets two independent AI reviewers that focus on high and critical issues only — no noise from style nitpicks (linters handle those).
CodeRabbit reviews every PR automatically via its GitHub App:
- Free tier — Works out of the box on public/open-source repositories
- Paid tiers (Pro / Teams) — Sign up at coderabbit.ai and connect your GitHub organization for private repo support and advanced features
- Enterprise — Requires the CodeRabbit GitHub App installed on your GitHub Enterprise Server instance; see coderabbit.ai/enterprise for self-hosted deployment options
- No secrets needed — Authentication is handled by the GitHub App
- Configuration —
.coderabbit.yamlat the repository root (included in all templates)
Setup: install the CodeRabbit GitHub App on your
repository or organization. Reviews start automatically on the next PR.
The default ruleset also requires the CodeRabbit status check, so CodeRabbit
must be installed and have review quota available. If CodeRabbit is rate-limited,
release, Dependabot, and other automation PRs can remain blocked until quota
resets or usage-based reviews are enabled.
Claude provides a second AI review layer via the
anthropics/claude-code-action GitHub Action:
- API key — Add an
ANTHROPIC_API_KEYrepository secret from console.anthropic.com - Graceful skip — The workflow is skipped with a notice when no API key is configured, so it never breaks CI
- Interactive — Comment
@claudeon any PR to ask follow-up questions - Configuration —
.github/workflows/ai-code-review.yml
Both reviewers are configured to flag only high-impact issues:
| Category | Examples |
|---|---|
| Security | Injection, auth bypass, secrets exposure, XSS, CSRF |
| Bugs | Null pointers, off-by-one, race conditions, resource leaks |
| Critical design flaws | Broken API contracts, missing input validation, SOLID issues |
Style, formatting, and naming concerns are not flagged — those are handled by pre-commit hooks and the lint workflow.
Add the skip-ai-review label to any PR to skip both AI reviewers for that PR.
Choose your release automation tool when creating a repository:
Lightweight, tag-driven releases powered by git-cliff (~9k ⭐):
- Tag-based workflow — Push a version tag (
v1.2.3) to trigger a release - Fast — Written in Rust; generates changelogs in milliseconds
- Language-agnostic — Works for any language without version file management
- CHANGELOG.md — Generated from conventional commits, committed back to the default branch
- GitHub Releases — Created automatically with the tag's changelog section as release notes
- Config file —
cliff.toml(Tera template for full customisation)
# Create a release with git-cliff
git tag v1.2.3
git push origin v1.2.3 # triggers the git-cliff-release.yml workflowAutomated PR-based releases powered by Google's Release Please:
- Semantic versioning — Versions bumped automatically from commit types
(
feat→ minor,fix→ patch,feat!/BREAKING CHANGE→ major) - Language-aware — Release type set from the selected language (updates
package.json,Cargo.toml,pyproject.toml, etc.) - Release PRs — Release Please opens a PR that tracks changes and updates the changelog
- CHANGELOG.md — Generated automatically from conventional commit messages
- GitHub Releases — Created automatically when the release PR is merged
- Config files —
release-please-config.json,.release-please-manifest.json
| Language Input | Release Type | Version Files Updated |
|---|---|---|
javascript |
node |
package.json |
typescript |
node |
package.json |
python |
python |
pyproject.toml, setup.py, setup.cfg |
go |
go |
Go module tags |
rust |
rust |
Cargo.toml |
java / kotlin |
java |
pom.xml |
ruby |
ruby |
*.gemspec, lib/**/version.rb |
php |
php |
composer.json |
terraform |
terraform-module |
Terraform module tags |
all / language-agnostic-only |
simple |
CHANGELOG.md only |
typescript,python (multi, first wins) |
node |
Same as first language (package.json) |
semantic-release (~23k ⭐) — the most popular
release automation tool. Zero manual steps: every merge to main is analysed and released
automatically.
- Fully automated — No tags, no PRs needed; semantic-release decides the version from commits
- Language-agnostic — GitHub-releases-only mode works for any language
- CHANGELOG.md — Generated and committed back to
mainautomatically - GitHub Releases — Created with generated release notes on every merge
- Config file —
.releaserc.json(plugin-based, highly extensible)
# Nothing to do manually! Just merge to main with conventional commits.
# semantic-release runs on every push to main and auto-tags + releases.| Tool | Stars | Trigger | Language support | Monorepo | Manual step |
|---|---|---|---|---|---|
| git-cliff | ~9k | git tag | any | ✅ | git tag |
| release-please | ~7k | push to main (PR) | language-aware | partial | merge PR |
| semantic-release | ~23k | push to main | any | via plugins | automatic |
- Squash merge only
- Delete branches after merge
- Auto-merge enabled
- Dev environment (no wait, no review)
- Prod environment (30s wait, reviews required)
Every bootstrapped repository gets a core security baseline out of the box:
| Feature | Details |
|---|---|
| Vulnerability alerts | Enabled automatically via the GitHub API |
| Dependabot security updates | Enabled automatically — auto-PRs for vulnerable deps |
| Dependabot version updates | Configured in .github/dependabot.yml for all ecosystems |
| CodeQL scanning | Workflow generated and scoped to the selected language(s) |
| Branch protection / rulesets | Default ruleset configured from .github/config/ruleset-default.json with review, lint, CodeRabbit, and CodeQL gates |
| SECURITY.md | Security policy and vulnerability reporting instructions |
| Secret scanning | Enabled by GitHub for all public repos automatically |
All templates follow SOLID principles, TDD, DDD, type safety, and language-agnostic code formatting (4 spaces code, 2 spaces config).
Templates use a single source of truth pattern for AI agent instructions:
- Canonical file:
.github/instructions/project.instructions.md - Thin pointers:
AGENT.md,CLAUDE.md,.github/copilot-instructions.md - Cursor rules:
.cursor/rules/project.mdc - Windsurf rules:
.windsurfrules
Edit only the canonical file — all agents pick up changes automatically.
Every created repository ships with a reusable PR review agent kit:
- 29 specialist agents under
.github/agents/and.claude/agents/ - 37 skills under
.github/skills/(symlinked to.claude/skills/) - Key commands:
full review,quick review,security review,resolve PR comments - Agents use only
git,grep,gh— no third-party tools required
All templates are in templates/. Modify them to match your team's needs.
See repository settings, environment configuration, and pre-commit options.
For adding support to a new language, provider, or runtime version, use:
This is the canonical checklist for extension work and validation steps.
The Terraform module (in terraform/) manages the same infrastructure declaratively:
- Creates the repository with all settings via
github_repository - Creates
devandprodenvironments viagithub_repository_environment - Optionally creates a repository ruleset via
github_repository_rulesetwhen Terraform inputenable_branch_protection=true - The wrapper workflow then copies template files and configures linting
Bootstrap workflows apply the default ruleset payload from
.github/config/ruleset-default.json after repository creation.
The default ruleset requires one approving review, approval after the latest
push, resolved review threads, linear history, the lint and CodeRabbit
status checks, and CodeQL code scanning results. CODEOWNERS remains generated
as ownership documentation, but the ruleset does not require code-owner-specific
approval.
Because CodeRabbit is a required third-party status, repositories using the
default ruleset should install CodeRabbit and monitor review quota. Rate limits
can leave release and dependency automation PRs waiting for the required status.
If you run Terraform directly, you can also manage rulesets through Terraform
inputs (for example, enable_branch_protection=true) or configure them
manually in repository settings.
Avoid enabling both approaches for the same repository at the same time.
Applying both the bootstrap default ruleset and Terraform ruleset management
can create overlapping/conflicting rules on main.
Terraform provides idempotent applies and state tracking, making it suitable for managing repositories as long-lived infrastructure.
Common failure signatures and what to check first:
| Failure signature | Where it appears | Likely cause | What to do |
|---|---|---|---|
Workflow monitoring timed out in test-repository-creation.yml |
Test workflow monitor step | Dispatch/run correlation mismatch | Confirm dispatch_actor is captured from gh api /user and actor filtering is enabled. |
Invalid target_ref / Invalid workflows / Invalid release_tool |
Test workflow validation step | Dispatch input outside allow-list | Use supported values from workflow inputs or a preset. |
Missing repository settings payload: .github/config/repo-settings.json |
apply-repo-settings action |
Action executed without expected repo checkout/layout | Ensure bootstrap repository is checked out before running actions and file path is intact. |
| Ruleset step exits with plan/feature warning | apply-repository-ruleset summary |
Target plan does not support rulesets or required features | Upgrade plan/features or accept skip on unsupported targets. |
Unexpected input while calling reusable workflow |
Launcher workflow run | Caller passes removed/unknown inputs | Align caller with: block to current inputs in create/terraform workflow definitions. |
When in doubt, re-run with test-repository-creation.yml using the matching
preset for the path you are validating (api-* or terraform-*).
- Recommended: GitHub App credentials (
app_id+BOOTSTRAP_APP_PRIVATE_KEY) installed in each target tenant owner - Fallback: GitHub personal access token (PAT) with
reposcope (addadmin:orgfor organization repositories) — stored as aGH_PATrepository secret or provided via thegh_tokenworkflow input — see Setup - One of:
micromamba,mise, or system-installed tooling for local linting withmake lint
MIT