repo-scaffold¶
A modern project scaffolding tool that helps you quickly create standardized project structures with best practices.
Features¶
- 🚀 Quick project initialization with modern best practices
- 📦 Cookiecutter templates with standardized structure
- ⚙️ Interactive project configuration
- 🔧 Pre-configured development tools (ruff, pytest, just)
- 📚 Documentation setup with MkDocs Material
- 🔄 GitHub Actions workflows included
- 🏷️ Conventional-commit driven versioning via Cocogitto
- 📦 Dependency / workspace management with uv
Installation¶
# Recommended: install as a uv tool
uv tool install repo-scaffold
# Or run without installing
uvx repo-scaffold list
# Or with pip
pip install repo-scaffold
Quick Start¶
# List available templates
repo-scaffold list
# Create a new project (interactive)
repo-scaffold create python
# Create a project in a specific directory, no prompts
repo-scaffold create python --no-input -o ./my-projects
# Create a uv workspace monorepo
repo-scaffold create uv-workspace -o ./my-projects
# Push a generated project to GitHub: create the repo, set CI secrets,
# push the initial commit, create the gh-pages branch, and point GitHub
# Pages at it. Reads GITHUB_TOKEN from the environment.
export GITHUB_TOKEN=ghp_...
repo-scaffold gh-init ./my-projects/my-python-project
# Add a new package to a workspace project (auto-detects Rust or uv)
repo-scaffold add-member my-new-lib --type ts-lib -p ./my-projects/my-workspace
See the GitHub bootstrap docs for the full flag list and the secrets/variables gh-init knows how to set.
End-to-End: From create to GitHub Pages¶
A full walkthrough from an empty directory to a published repository with CI and docs.
# 1. Generate the project. `create` also runs `git init` on branch `master`
# (opt out with --no-git). Drop --no-input to configure it interactively.
repo-scaffold create python --no-input -o ./workspace
cd ./workspace/my_python_project # directory name is the project_slug
# 2. (Optional) make your own first changes here. gh-init creates the
# initial commit for you, so an extra commit at this point is optional.
# 3. Provide a GitHub token with `repo` scope (or `public_repo` for public repos).
export GITHUB_TOKEN=ghp_...
# 4. Bootstrap GitHub. By default gh-init will:
# - create the repository (name/description pulled from pyproject.toml)
# - set the CI secrets/variables the generated workflows expect
# - push the initial commit to `master`
# - create the `gh-pages` branch and set it as the GitHub Pages source
repo-scaffold gh-init .
# 5. Publish docs: push a release tag (or let the Cocogitto version-bump
# workflow create one). The docs-deploy workflow builds the site and
# pushes it to `gh-pages`, which GitHub Pages now serves automatically.
git push --tags # or: git tag 0.1.0 && git push origin 0.1.0
Common opt-outs:
repo-scaffold create python --no-git— skip the localgit init.repo-scaffold gh-init . --private— create a private repository.repo-scaffold gh-init . --protect-branch— protect the default branch (require PR review; admins can still push so releases keep working).repo-scaffold gh-init . --no-push— create the repo and set secrets without pushing (Pages setup is skipped, since it needs the pushed branch).repo-scaffold gh-init . --no-pages— push, but don't creategh-pagesor configure Pages (you can set it later in repo Settings → Pages).
Shared GitHub Actions¶
Python and uv-workspace projects use a thin caller workflow backed by the
versioned reusable-python-ci.yaml workflow in this repository. CI behavior is
maintained centrally while generated repositories keep control of triggers,
permissions, Python versions, and optional container checks. Workflow
references are pinned to a repo-scaffold release and can be upgraded by
Renovate.
See Shared Workflow Contracts for supported inputs, secrets, versioning, and migration guidance.
The maintenance model is intentionally layered: templates generate thin caller workflows, this repository publishes the reusable workflow implementation, and Renovate proposes version upgrades in each consumer repository. CI/CD logic is therefore fixed centrally, while triggers, permissions, and project-specific options remain visible in the consumer.
Available Templates¶
Currently supported project templates:
python— single-package Python projectpyproject.toml+uvfor dependency managementpytest+ coverage,rufffor lint & format- Optional Click CLI, Podman compose files, GitHub Actions, MkDocs Material docs
-
Reusable Cocogitto release workflow that bumps version, builds the selected tag, publishes to configured PyPI indexes, creates a GitHub Release, and deploys docs; optional Podman projects also publish a GHCR image
-
uv-workspace— uv workspace monorepo - Workspace-aware
pyproject.tomlwith one initial member underpackages/ - Shared
dev/docsdependency groups - Cocogitto monorepo release workflow with per-package and global tags
- Reusable, tag-pinned release pipeline that builds only changed packages, publishes to configured indexes, creates a GitHub Release, and deploys docs
-
Same lint / test / docs tooling as the python template
-
react— TanStack Start (SSR React) project - TanStack Router/Query/Form/Store, MUI, Tailwind CSS
- Biome for lint/format, pnpm for deps, Vitest for testing
-
Optional Docker/Podman support, GitHub Actions CI, and demo pages
-
rust— Axum + SQLx cargo workspace project - Cargo workspace with
packages/api-server/as initial member - Domain-driven architecture (domain/infra/api/dto layers)
- Axum web framework + SQLx (PostgreSQL, compile-time queries, offline mode)
- JWT auth middleware, health check reference domain
- Optional Docker/Podman, GitHub Actions CI, OpenAPI/Swagger (utoipa), and OpenTelemetry support
-
Cocogitto monorepo versioning with
cargo-workspaces -
ts-sdk— TypeScript SDK library - Vite lib mode producing dual ESM + CJS output with bundled type declarations
- Generic
ApiClientwith automatic token lifecycle (authenticate → cache → refresh → fallback) AuthServicesupporting four OAuth grant types with exponential-backoff retry- Prettier for formatting, pnpm for deps
-
Optional GitHub Actions CI + dual npm/GPR publish + Cocogitto version bump
-
pnpm-workspace— pnpm monorepo with mixed sub-package types - Workspace root with
pnpm-workspace.yaml+ Prettier - Initial sub-package type selection:
vue-app/ts-lib/react-app/ts-cli/react-lib/node-service - Cocogitto monorepo versioning with
pnpm --filterper-package hooks repo-scaffold add-member --type ts-lib|ts-cli|react-app|vue-app|react-lib|node-service|electron-appadds a typed member to pnpm workspacesrepo-scaffold add-member --type python-libor--type rust-libadds a shared uv or Cargo library member-
Optional GitHub Actions CI
-
vue-project— standalone Vue 3 project with Router, Pinia, and Tailwind CSS - Full layered component structure:
components/ui/,components/layout/,components/common/ - Pages with colocated sub-components:
pages/HomePage/,pages/AboutPage/ - Vue Router with lazy-loaded routes, Pinia stores with Composition API
- Tailwind CSS v4 via
@tailwindcss/vite, Prettier, pnpm - Optional GitHub Actions CI + Cocogitto version bump
Both templates use just (via rust-just) as the task runner. Bootstrap from a clean machine with uvx --from rust-just just init — that recipe also installs rust-just as a uv tool, so every subsequent recipe can be run as plain just <recipe>.
Adding Workspace Members¶
The v1 add-member command adds a typed member and registers it in cog.toml for Cocogitto tracking:
# Inside a generated workspace project directory
repo-scaffold add-member my-new-lib --type ts-lib
# Or specify the project path explicitly
repo-scaffold add-member my-new-lib --type ts-lib -p /path/to/project
Supported pnpm member types are ts-lib, ts-cli, react-app, vue-app, react-lib, node-service, and electron-app. TypeScript members use Biome and Vitest; app and library templates use Vite and Tailwind CSS v4. The Electron member is a CommonJS desktop app under apps/.
The command auto-detects the project type:
- pnpm workspace (pnpm-workspace.yaml): renders a TypeScript library under
packages/<name>/, supports --scope and repeated --depends-on, adds the
workspace glob if needed, and runs filtered checks by default.
- Rust workspace (Cargo.toml with [workspace]): creates a crate skeleton under packages/<name>/, appends a [packages.<name>] section to cog.toml with cargo workspaces version pre-bump hooks, and runs cargo check.
- uv workspace (pyproject.toml with [tool.uv.workspace]): runs uv init --lib, appends a [packages.<name>] section to cog.toml with uv version --package pre-bump hooks, and runs uv sync.
Generated pnpm and Electron workspaces expose just add-member <name> [type],
just add-lib <name>, and just plan-member <name> [type]. These recipes run
the generator through a pinned uvx --from repo-scaffold==1.0.0 command.
Development Setup¶
# Clone the repository
git clone https://github.com/ShawnDen-coder/repo-scaffold.git
cd repo-scaffold
# Bootstrap once: installs rust-just as a uv tool, syncs deps, installs hooks
uvx --from rust-just just init
# Subsequent runs use `just` directly
just lint
just test
Releasing¶
This project (and the templates it generates) uses Cocogitto driven by conventional commits:
- Push a
feat:/fix:/ breaking-change commit tomasterand theversion-bumpworkflow runscog bump --auto, updatingCHANGELOG.md, bumpingpyproject.tomlviauv version, committing, and tagging. For a first major release or another explicit version, manually dispatch the workflow withrelease-version(for example1.0.0). - The release workflow then builds and publishes the tagged version.
- Generated
uv-workspaceprojects pass the resolved global tag into a reusable release workflow. The workflow validates and checks out that tag, builds only packages tagged at the release commit, publishes private packages by default, optionally publishes to public PyPI whenPUBLISH_TO_PUBLIC_PYPI=true, creates the GitHub Release, and deploys documentation. - To retry a workspace release or docs deployment, run the corresponding workflow manually and provide an existing SemVer tag such as
1.2.3.
See cog.toml for hook and changelog configuration.