
Python CLI that creates GitHub repos with safe defaults — branch protection, Dependabot, secret scanning, and pre-flight security scanning — applied automatically.
Create GitHub repositories with safe defaults applied, in one command.
gh-safe-repo create <owner/repo>
Branch protection, immutable tags, locked-down Actions, Dependabot, secret scanning with push protection, and private vulnerability reporting are all configured before you push your first commit. The same tool audits and fixes repos you already have, and scans local code for secrets before it leaves your machine.
Status: the core workflow is stable and verified end to end, but the CLI is still being polished. Expect occasional breaking changes before 1.0.
--local and --fromGitHub's defaults favour discoverability over safety: a new repo has no
branch protection, no Dependabot, and Actions that can write to the repo and
approve their own pull requests. gh-safe-repo changes that, and shows you
the plan before it touches anything:
--public to make it public.Every setting is configurable. See Safe defaults for the exact values and Configuration for how to change them.
Requirements:
gh CLI logged in (gh auth login), or
GITHUB_TOKEN set in the environmentuv to install from sourcePATH
or run via podman/docker; without either, a regex scanner is used.Pushing code with --local or --from also needs your normal git
credentials for GitHub. See Pushing code.
git clone https://github.com/AriESQ/gh-safe-repo
cd gh-safe-repo
uv tool install .
gh-safe-repo --help
To run without installing:
uv sync
./gh-safe-repo create <owner/repo>
1. Preview. --dry-run makes no API calls and creates nothing.
$ gh-safe-repo create AriESQ/demo-repo --dry-run
Configuring AriESQ/demo-repo...
Planned Changes
Type Category Setting Value / Note
------ ----------------- -------------------------------------- ----------------------------------------------------------------
ADD repo repository AriESQ/demo-repo
DELETE file readme README.md
UPDATE actions allowed_actions 'all' → 'selected'
UPDATE actions verified_allowed False → True
UPDATE actions sha_pinning_required False → True
UPDATE actions default_workflow_permissions 'write' → 'read'
UPDATE actions can_approve_pull_request_reviews True → False
SKIP branch_protection branch_protection Branch protection requires a public repo or paid GitHub plan
SKIP security dependabot_alerts Requires a public repo or paid GitHub plan
SKIP security secret_scanning Requires a public repo or paid GitHub plan
SKIP security dependabot_security_updates Requires a public repo or paid GitHub plan
SKIP security private_vulnerability_reporting Requires a public repo or paid GitHub plan
SKIP security enable_dependency_graph Requires a public repo or paid GitHub plan
SKIP security enable_secret_scanning_push_protection Requires a public repo or paid GitHub plan
SKIP tag_protection tag_protection Tag protection rulesets require a public repo or paid GitHub plan
7 change(s) to apply, 8 skipped
Dry run — no changes made.
The SKIP rows are what a private repo on a free plan looks like. Those
features need a public repo or a paid plan, and the tool says so rather than
failing silently. See GitHub plan limitations.
2. Apply. Drop --dry-run. You see the same plan, then a confirmation
prompt (--yes skips it).
gh-safe-repo create AriESQ/demo-repo
3. Start working. On success you get a Verified section (every setting read back from GitHub) and a banner with ready-to-paste commands:
╭─ Done ───────────────────────────────────────────────────╮
│ Repository created successfully! │
│ https://github.com/AriESQ/demo-repo │
│ │
│ Add remote to existing repo: │
│ SSH : git remote add origin [email protected]:AriESQ/… │
│ HTTPS: git remote add origin https://github.com/… │
│ │
│ Clone fresh: │
│ SSH : git clone [email protected]:AriESQ/demo-repo.git │
│ HTTPS: git clone https://github.com/AriESQ/demo-… │
╰──────────────────────────────────────────────────────────╯
Your preferred protocol (gh config get -h github.com git_protocol) is
listed first.
gh-safe-repo create <owner/repo> # private (default)
gh-safe-repo create <owner/repo> --public # public: branch and tag protection apply
The repo is initialized so a default branch exists (branch protection needs
one), then the auto-generated README.md is deleted so you start clean. Set
auto_init = true in config to keep it. The owner must match your
authenticated account; this guards against mistakes on multi-account
systems.
gh-safe-repo create <owner/repo> --local ~/projects/myapp
Scans the directory for secrets, creates the repo, pushes every branch and
tag, then sets origin and upstream tracking in your original directory so
git push works immediately. An origin that already points elsewhere is
left alone and the banner tells you what to run instead. Afterwards every
pushed branch and tag is checked against GitHub SHA for SHA. Details in
Pushing code.
gh-safe-repo create <owner/repo> --from <owner/source>
gh-safe-repo create <owner/pub> --from <owner/priv> --public # scanned thoroughly first
Clones the source with full history, scans it, mirrors it into the new repo, and copies the source's default branch, description and topics. If you abort at the scan, no code reaches GitHub.