git-repokit
One repokit command creates a project that is ready to work in (including the structure, the code for its language, the tooling and hooks, a private notes vault, a license, and the repository on GitHub with its labels and first issues).
repokit create replaces the hand-run route of copying a template repository, running its setup, then setting up GitHub and the notes by hand. Every piece is optional and configurable, so your own house style lives in one config file, and a create becomes one short command.
What a project gets
A full create (the Quick Start below) produces:
- The structure: README, CONTRIBUTING, CHANGELOG, LICENSE,
.gitignore,.gitattributes,docs/,tests/,scripts/, and, if you ask for them, ROADMAP, a funding file, Dependabot, a stale-issue policy and PR and release templates. - The code for its language: a Python package with
pyproject.tomland a CLI, a CMake or Visual Studio C/C++ project, a TypeScript npm package, a Claude Code plugin, and more. Each comes with tests, a CI workflow and a VS Code debug configuration that work from the first commit. See Languages and layers. - A README that names the project: the real GitHub owner, badges for the release, the Python or Node minimum and the license, install and test commands for the preset, and a License section at the end.
- The tooling: git-repokit-common vendored at
scripts/repokit-common/, with git hooks that keep version numbers in step, keep private files out of public commits, and run the tests before a push. - A private vault:
private/is its own git repository, ignored by the project, for notes, design documents and postmortems. It starts with a map, an index for an oracle session and a to-do board. See The vault. - The repository on GitHub (with
--github): created with yourghlogin and pushed. It gets the standard labels, Roadmap and Quick Notes as issues #1 and #2 (pinned), discussions and topics. See GitHub setup.
📦 Installation
Python 3.10 or newer. The command is repokit.
pip install git-repokit
# or the same tool under its DazzleTools alias
pip install dazzle-git-repokit
--github also needs the GitHub CLI, logged in once with gh auth login.
From source:
git clone https://github.com/DazzleTools/git-repokit.git
cd git-repokit
pip install -e ".[dev]" # with the test and lint tools
🎯 Quick Start
A full project, on GitHub
This is the most common create: a Python package with everything turned on, published to GitHub with its labels, first issues and topics.
repokit create my-tool --language python --license gpl-3.0-or-later \
--description "What my-tool does, in one sentence" \
--extras all \
--github --github-setup labels,issues,pin,discussions,topics \
--topics cli,python
You get a private GitHub repository under your gh login (add --public for a public one, --org MyOrg for an organization), with main pushed, the labels made, and issues #1 (Roadmap) and #2 (Quick Notes) pinned. Locally, my-tool/ holds the project and its vault in my-tool/private/. GitHub setup lists the few steps that are still done by hand afterwards.
The same create from your house config
Put the choices you make every time in ~/.repokit/config.json:
{
"license": "gpl-3.0-or-later",
"license_private": "all-rights-reserved",
"extras": ["all"],
"github_setup": ["labels", "issues", "pin", "discussions", "topics"],
"github": {"username": "your-login"}
}
Then the full create is:
repokit create my-tool --language python --github \
--description "What my-tool does, in one sentence" --topics cli,python
Every key is listed in Configuration.
A multi-branch project
The private-branch model keeps all your working history on a local-only private branch, and moves finished work to public branches that are checked out beside it:
repokit create my-app --branch-strategy standard --language python --license mit --github
my-app/
local/ the repository, on the private branch: work here
dev/ the dev branch
github/ the main branch
Then the day-to-day loop is:
cd my-app/local # work and commit on private, notes and all
git add -A && git commit -m "Add the parser"
cd ../dev # bring the work to dev, without the private files
repokit safe-merge private --preview
repokit safe-merge private
git commit -m "Add the parser"
cd ../github # and on to main when it is ready
repokit safe-merge dev
git commit -m "Release the parser"
git push
safe-merge leaves out the private content (private/, CLAUDE.md, revisions/, ...), and the hooks refuse it on a public branch if it ever gets staged. --github pushes only the public branches. Other layouts: simple (private, dev, main), gitflow, github-flow, and your own with --branches and --worktrees; see Branch strategies below.
Known issue in 0.9.11: this create prints
fatal: ambiguous argument 'private'once per public branch, anddev/andgithub/start with only the README and.github/. The loop above still brings the work across. The fix is tracked in #16.
Other common creates
# Local only: no GitHub, nothing pushed
repokit create my-tool --language python --license mit
# A Claude Code plugin (hooks in JavaScript; add --language python for Python hooks)
repokit create my-plugin --with claude-plugin --license apache-2.0 --github
# A C/C++ app with CMake, or a Visual Studio solution
repokit create my-app --language c-cpp --license bsd-3-clause
repokit create my-app --with c-cpp/msbuild --license gpl-3.0-or-later
# A TypeScript npm package
repokit create my-lib --language js-ts --license mpl-2.0
# A one-file Python script, no packaging, given away to the public domain
repokit create my-script --with python/script --license unlicense
# Several pieces in one --with, comma-separated; repokit puts them in order
repokit create my-plugin --with claude-plugin,ts --license mit # a Claude Code plugin in TypeScript
repokit create my-lib --with node,ts,node-package --license isc # the same layers as --with js-ts/node-package
repokit create my-app --with c-cpp/cmake-app,python/script --license mit # two languages, a preset for each
# A private project: all rights reserved, evaluation-only, your own terms, or no LICENSE at all
repokit create my-work --language python --license all-rights-reserved
repokit create my-work --language python --license proprietary-evaluation
repokit create my-work --language python --license file=../terms/client-terms.txt
repokit create my-sketch --license none
# What every language offers, and the license catalogue
repokit list
The catalogue has every license GitHub and GitLab offer when you create a repository, beyond the ones above: lgpl-3.0, agpl-3.0, epl-2.0, 0bsd, cc0-1.0 and more, with the texts from choosealicense.com, which also helps you pick one. repokit list prints every id, ready to copy. Two more are for software you are not giving away: all-rights-reserved, and proprietary-evaluation, which allows evaluation and non-commercial use until you revoke it, forbids everything else, and optionally provides an email for permission requests.
Choosing the code type
--language picks the language: python, c-cpp, js-ts, or generic (the default, which adds no code). Each language has a default preset, and --with picks another one, such as python/claude-plugin or c-cpp/msbuild. --with also takes a comma-separated list of presets and single layers (--with claude-plugin,ts). A name can be bare when only one language has it, and is qualified when two do: script is refused as ambiguous, python/script is not. repokit list shows every preset and layer, including the planned ones.
| Language | Default preset | Other presets |
|---|---|---|
python |
python/pypi: a package with pyproject.toml, a CLI, tests, and publish-on-release |
python/script, python/setuppy, python/claude-plugin |
c-cpp |
c-cpp/cmake-app: CMake presets, vcpkg, CTest, a version header |
c-cpp/msbuild, c-cpp/minimal |
js-ts |
js-ts/node-package: a TypeScript npm package with node:test |
js-ts/script, js-ts/claude-plugin |
Several languages stack: --language python,c-cpp. The details, and how to add a language, are in Languages and layers.
The license
A license is required. --license <id> writes LICENSE from a catalogue of the licenses GitHub and GitLab offer (mit, apache-2.0, gpl-3.0, gpl-3.0-or-later, bsd-3-clause, ...), plus all-rights-reserved and proprietary-evaluation for a private project. --license file=<path> copies a text as it is, and --license none writes no file. The holder and year come from your git identity and the clock, and the license also populates in pyproject.toml or the plugin manifest. With license set in the config, you can leave the flag off.
Branch strategies
repokit has two ways to keep private work private:
main-only(the default): the project folder is the repository, onmain, andprivate/is its own nested git repository that the project ignores. One branch, no merging rules to learn.- The private-branch model: your working history lives on a local-only
privatebranch in<name>/local/, and the public branches are git worktrees in sibling folders. You move finished work across withrepokit safe-merge, which leaves the private content behind. This is the model repokit was first built for, and it suits projects with several release stages or several people.
--branch-strategy |
Public branches | Checked out in folders | Flow |
|---|---|---|---|
main-only |
main | the project folder itself | commit on main |
standard |
dev, staging, test, live, main | dev/, github/ (main) |
private -> dev -> test / staging -> main -> live |
simple |
dev, main | github/ (main) |
private -> dev -> main |
gitflow |
develop, release, hotfix, main | develop/, github/ (main) |
private -> develop -> release -> main, with hotfixes |
github-flow |
main | github/ (main) |
private -> main |
minimal |
main | none (switch branches in local/) |
private -> main |
# A GitFlow project on GitHub
repokit create my-lib --branch-strategy gitflow --language python --license mit --github
# Your own branches, with worktrees for two of them (name a private-branch
# strategy too, or the project gets no private branch)
repokit create my-app --branch-strategy simple --branches main,develop,qa,production \
--worktrees main,develop --license mit
The guards for the private-branch model: repokit check-guardrails shows what is protected, repokit setup-guardrails installs the hooks in a project repokit did not make, and repokit safe-merge-dev merges between development branches while keeping their history out of the public ones. The Branch strategies guide covers each layout, and the Workflow guide covers the day-to-day work.
Existing projects
repokit analyze ./my-project # what repokit would do, changing nothing
repokit adopt ./my-project --dry-run # preview adopting a git repository in place
repokit adopt ./my-project --language python --migration-strategy safe --backup
repokit migrate ./my-folder --dry-run # add repokit's folders and files to a folder
adopt fills in what the project lacks. It keeps the project's own license file (LICENSE, LICENSE.md, COPYING, ...); with none, it writes the license your config names, or adopts the project without one and says so. --license is only for choosing one (it replaces the project's own file). It keeps the repository's history and sets up the private-branch layout (--branch-strategy standard unless you name another): your folder stays on the private branch, with main and dev checked out in sibling folders. The safe strategy keeps every existing file and adds what is missing beside it. repokit setup-guardrails adds the private-content hooks to a project repokit did not create. The Adoption guide and the Migration guide walk through each case.
All commands
| Command | What it does |
|---|---|
create |
Create a new project |
list |
List the languages, presets and layers |
analyze |
Report what repokit would do with an existing folder |
adopt |
Add repokit's structure to an existing git repository, in place |
migrate |
Add repokit's standard folders, files and hooks to an existing folder |
publish |
Publish an existing repository to GitHub or GitLab |
bootstrap |
Write a script that sets repokit up |
init-config |
Write a .repokit.json |
store-credentials |
Store a GitHub or GitLab token for --publish-to |
setup-guardrails, check-guardrails |
Install, or check, the private-content protection |
safe-merge, safe-merge-dev |
Merge branches without carrying private content across |
clean-history, analyze-history |
Find, or remove, sensitive data in a repository's history |
manage-gitkeep |
Add or remove .gitkeep files |
list-templates |
List the template files |
repokit <command> --help shows each command's options and examples.
🧪 Testing
python -m pytest -q # the full suite, about ten minutes
python -m pytest -q -m unit # the unit tests, a few seconds
Every run is isolated from your git config, home directory and tokens. A git push runs the unit tests through the vendored pre-push hook; CI runs the unit tests on Python 3.10 to 3.13, on Linux and Windows. tests/README.md covers the test classes and the live GitHub tests.
📚 Documentation
- Configuration: every config key, and the flag that matches it
- Languages and layers: presets,
--with, and adding a language - GitHub setup:
--github,--github-setup, and what GitHub has no API for - The vault:
private/, its first files, and the sessions that use it - Branch strategies: main-only and the private-branch model
- Workflow guide: day-to-day work under the private-branch strategies
- Deployment demo: worked examples, from a new project to GitHub
- Adoption guide and Migration guide: existing projects
- Recipes and how-tos: commands for common cases
- Auth guide: the
ghlogin, and tokens for--publish-to - Platform support: what runs where, and what each platform needs
- Why repokit exists
The documentation guide suggests a reading order.
Contributing
Contributions are welcome! See the CONTRIBUTING.md for more details.
Like the project?
Related Projects
- git-repokit-common - The shared scripts and git hooks every project gets at
scripts/repokit-common/: version sync, private-content checks, tests before a push,gh_issue_full.py. repokit vendors it into each project it creates, and into itself - git-repokit-template - The template repository repokit grew from: copy it, run its setup, then finish GitHub and the notes by hand.
repokit create --language pythonreproduces its project tree, and a regression test keeps the two in step - dazzlecmd - The DazzleTools CLI (
dz). Itsdz private-initfirst madeprivate/its own repository; repokit's vault is a port of it - github-traffic-tracker - Traffic history beyond GitHub's 14 days (
ghtraf).--github-setup trafficprints its setup commands, and theinstallsandviewsbadges read its counts
Acknowledgments
- Inspired by modern DevOps practices and GitOps workflows
- https://nvie.com/posts/a-successful-git-branching-model/
- https://trunkbaseddevelopment.com/
- https://docs.github.com/en/get-started/quickstart/github-flow
- https://martinfowler.com/articles/continuousIntegration.html
- https://www.atlassian.com/continuous-delivery
- https://www.perforce.com/blog/vcs/best-branching-strategies-high-velocity-development
- Built for developers who value consistency and automation
- Special thanks to the open-source community writ large
License
git-repokit, Copyright (C) 2025-2026 Dustin Darcy
Licensed under the MIT License (MIT) -- see LICENSE.
Metadata
Release files for git-repokit 0.9.11
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| git_repokit-0.9.11.tar.gz | 343.4 kB | With provenance | Details for git_repokit-0.9.11.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| git_repokit-0.9.11-py3-none-any.whl | Python 3 | none | any | Details for git_repokit-0.9.11-py3-none-any.whl |
Total release size: 678.5 kB
Release files / git_repokit-0.9.11.tar.gz
| Download URL | git_repokit-0.9.11.tar.gz |
|---|---|
| Size | 343.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b59c12442694d42b95e4e68491d8ed267c171fb7fc357cb7ab390a0ff93fb29d
|
|
BLAKE2b-256 checksum How to use checksums |
554e18eeedd30e0461cfc20153992ccb614b40cfad0ecb6873f7eab1c4bfc83d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logRelease files / git_repokit-0.9.11-py3-none-any.whl
| Download URL | git_repokit-0.9.11-py3-none-any.whl |
|---|---|
| Size | 335.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d18d64e4f78ad6454f4a0ef24f92d96125eaf35495392ecc0df19541d7ff6d64
|
|
BLAKE2b-256 checksum How to use checksums |
04212a0351460772741e069e7f704d80f4c6c78865bd7513d88cd399151868e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logSecurity for git-repokit 0.9.11
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for git_repokit-0.9.11.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.