A new copy becomes its repository on GitHub with one command that it brings¶
- Status: accepted
- Date: 2026-10-18
Context¶
Copier writes the files of a project into a folder and nothing more. The quick start then took six commands: git init, the first commit, gh repo create with the owner and the name typed in once more, and settings apply and checklist from a checkout of the blueprint, ../repo-blueprint/blueprint.py, although every copy brings the same tool as .github/blueprint.py. Copier's own message after the copy named <blueprint>/blueprint.py and a gh repo create --source . --push that fails in a folder without a repository and without a commit. git init made the branch that Git's configuration names, master on Git for Windows and on every Git without init.defaultBranch, while every workflow runs on pushes to main and on pull requests to it: in such a repository, none of them ever ran, and nothing said so.
Options¶
- Keep the commands in the README and fix them:
git init --initial-branch=mainand the tool in.github/. Still six commands to type in the right order, and the owner and the name twice. - Tasks of Copier that run the commands after the copy: Copier runs them only with
--trust, which lets a template run any code on the machine. The blueprint promises a copy that runs none of its code, as its security design says. - A command of the tool that every copy brings,
blueprint.py create, that does all of it from the answers of Copier.
Decision¶
Option 3.
createreads the owner and the name from.copier-answers.yml, or from--repo OWNER/NAME, and the description from.github/repository.toml, whose settings it loads first, so that a configuration that can't be right stops it before anything is made. It runsgit init --initial-branch=main,git add --all,git commit --signoff,gh repo create OWNER/NAME --public(or--private)--source . --remote origin --push, thensettings applyandchecklist, as the commands of the tool do.--dry-runprints the commands and runs none.- A folder that Git knows already is taken as it is, as the quick start of older releases left it: its branch is renamed to
main, and the first commit is made only when there is none. A folder with uncommitted changes next to its commits is refused, ascreatepushes commits only, and so is a folder that pushes to a remote already, which is no new copy; the refusal namessettings applyandchecklistfor a repository that is on GitHub. - Only a refused part of the settings fails it. What a person does, such as the secrets and the release app, the checklist names, so a new repository with those steps left still ends with success.
settings checkreports a default branch other thanmain, with the place where GitHub renames it and the commands for each clone.settings applyleaves the renaming to a person, since every clone has to follow it.- Copier says it too: before its questions what the command after the copy needs (Git, Python 3.12, GitHub CLI 2.48, signed in as an administrator of the owner) and that copying needs no
--trust; after the files,cdinto the folder andpython3 .github/blueprint.py create. - The quick start copies with the Copier that the blueprint bot updates with, by
uvxorpipx runwith its version pinned, which Renovate moves with the Copier ofstacks/copier/.
Consequences¶
A new user goes from copier copy to a configured repository with two commands and needs no checkout of the blueprint; the default branch is always main, and a repository where it isn't is named by settings check and by the settings bot. create needs Python 3.12 and the GitHub CLI as the rest of the tool does, and Git. A private repository on a free plan of GitHub gets no rulesets, which GitHub offers for public repositories only there: settings apply reports the refused part, and create fails after the repository was made, so that the person sees what is missing.