One Python file (scripts/solo.py, stdlib only, Python 3.9+) that diagnoses a repo and applies only
what is missing. Its defining rule: it never adds a setting that makes a one-person repo
unmergeable (required approvals, required CODEOWNERS review, enforce_admins). It detects existing
settings like that as ❌ and shows how to remove them, but never removes them itself.
Where is the script? In the directory this SKILL.md was loaded from: <skill dir>/scripts/solo.py
(~/.claude/skills/github-solo/scripts/solo.py for a user install, ${CLAUDE_PLUGIN_ROOT}/scripts/solo.py
for the plugin). Below, SOLO stands for python3 <skill dir>/scripts/solo.py.
This file follows the Agent Skills layout (SKILL.md + scripts/ + references/), which Claude Code, Codex and Cursor can load from
their skills directories (see the README for the paths). Agents without skills support can read AGENTS.md, or call the same commands
as MCP tools: python3 scripts/solo_mcp.py (stdio; solo_apply / solo_restore are dry runs unless confirm is true).
Everything below applies to every agent; only the way you detect the environment differs.
Advice depends on it: a cloud container can read GitHub but its network proxy may refuse settings writes,
while Claude Code running on the user’s PC can run apply --yes directly. Determine it from facts:
SOLO doctor and read the environment row (or check the variables yourself:
CLAUDE_CODE_REMOTE=true / CCR_AGENT_PROXY_ENABLED → managed cloud container;
CLAUDECODE=1 without those → Claude Code running on this PC; neither → another agent, plain shell or CI: then
judge by facts (doctor shows whether the API is reachable and which admin endpoints answer 403 “not permitted through this proxy”).
CLAUDE_CODE_ENTRYPOINT shows how the session was started (observed values: remote_mobile in a cloud session started
from the app, cli in Claude Code running on a user’s PC); report the raw value and do not guess what an unfamiliar value means: say it is unknown.read_documentation tool in
Claude Code cloud sessions) before explaining, then hand the user the commands as described in “Telling the user where to run it” below.Users often cannot tell an app / cloud session from Claude Code on their own PC, so a vague “run it on your machine” leaves them lost. Always:
RESULT:”).python instead of python3, and Git Bash needs API paths without the leading slash.OWNER/REPO the user gave. Otherwise the current directory’s
git remote origin is used automatically (omit the argument). For “all my repos” use
SOLO audit --all-repos OWNER. If neither exists, ask once.
Token: GH_TOKEN → GITHUB_TOKEN → gh auth token. No token → tell the user to run
gh auth login (or set GH_TOKEN); do not ask them to paste a token into chat.SOLO doctor OWNER/REPO first: it shows which token is used,
whether the API is reachable and which admin endpoints the token can read.SOLO audit OWNER/REPO (add --json if you need to parse it). Exit code 1 means there is
at least one ❌.SOLO apply OWNER/REPO (dry run) and show the user the plan.SOLO apply OWNER/REPO --yes
after showing the plan (the user’s request to “set it up / fix it” is the go-ahead; if they only
asked for a diagnosis, ask first).--only and only after asking about each one, because
they change the public face or can break workflows: pages, discussions, topics
(--topics a,b), workflow-permissions, tag-guard, labels, community-files, actions-can-create-prs. Example:
SOLO apply OWNER/REPO --yes --only pages --pages-path /docs..github/dependabot.yml, .github/release.yml, SECURITY.md):
release-workflow row of the audit. If it is ⚠️, a
push to the default branch can start a release workflow (it may publish a real release or
tag). Tell the user, and get an explicit OK before you commit or push. Prefer a branch + PR
when they want to avoid it.--commit-files commits through the Contents API straight to the default
branch. It refuses when a release workflow may fire unless --accept-release-risk is also
given; only add that flag after the user agreed.dependabot.yml exists, apply prints the missing
entries as a proposal; merge them by hand.SOLO audit OWNER/REPO) and report what changed: before/after counts and anything
that remains (opt-in items the user declined, ➖, license, social preview, which cannot be done via API).SOLO audit --profile app|library|site|docs hides checks that do not fit the kind of repo; ask the user what the repo is.
Audits print a 0-100 score. SOLO ci-template prints a weekly audit workflow. GHES: SOLO_API_BASE=https://HOST/api/v3.SOLO explain CHECK_ID: prints why/API/undo of one check (offline). SOLO badges OWNER/REPO: README badge Markdown.
audit --quiet --ignore a,b --fail-on warn for CI. SOLO links --workflow: release workflow template (version-less assets).SOLO restore OWNER/REPO (dry run) / --yes: reverts what the last apply --yes changed, using the snapshot it saved.
Offer it whenever the user regrets a change. It does not delete generated files.
--lang ja makes the text output Japanese (--json stays English); audit --github-annotations adds CI annotations;
apply --json prints the plan and the execution log; links --markdown prints ready-to-paste list items.SOLO links OWNER/REPO: fixed download URLs https://github.com/O/R/releases/latest/download/<asset>.
If it says all releases are pre-releases (/latest ignores pre-releases → 404) or asset names contain
the version (URL would change every release), relay the printed fix and see
references/release-latest.md (workflow example that uploads a version-less copy).SOLO dependabot OWNER/REPO: prints a generated dependabot.yml (monthly, one grouped PR per
ecosystem) to stdout; nothing is written.Full list with API, reason and how to undo each: references/checks.md. Summary:
| Category | check id (apply id) | default apply? |
|---|---|---|
| Security | dependabot-alerts, dependabot-security-updates |
yes |
secret-scanning, push-protection, private-vuln-reporting, codeql (public repos only) |
yes | |
dependabot-config (generates .github/dependabot.yml) |
yes | |
actions-pinning, actions-hardening, open-alerts (report only) |
n/a | |
actions-can-create-prs (let Actions open / approve PRs; release-please needs it) |
opt-in | |
workflow-permissions (default GITHUB_TOKEN = read) |
opt-in | |
| Solo | solo-blocker (❌ detect only) |
never |
guardrail (ruleset solo-guard: no delete / force-push of the default branch) |
yes | |
tag-guard (ruleset solo-tag-guard: no deleting / force-moving v* tags) |
opt-in | |
delete-branch-on-merge |
yes | |
discussions |
opt-in | |
| Distribution | pages |
opt-in |
releases, release-workflow, release-tag-format, ci-status (report only) |
n/a | |
release-notes-config (.github/release.yml) |
yes | |
| Metadata | security-policy (SECURITY.md) |
yes |
topics |
opt-in (--topics) |
|
labels (create the labels release.yml uses), community-files (issue / PR templates, CONTRIBUTING) |
opt-in | |
description, license, social-preview, issues-enabled (report only; license is the user’s decision, social preview has no API) |
n/a |
Private repos: GitHub Secret Protection / Code Security are paid, so those rows show ➖ with the reason and are skipped. Dependabot alerts / security updates are free on private repos and still apply.
apply --yes on a repo the user did not name or that you inferred from a stray remote
without saying which repo you are about to change.apply is idempotent: a second run changes nothing.solo-guard ruleset can be lifted temporarily:
gh api -X PUT repos/O/R/rulesets/<id> -f enforcement=disabled (re-enable with active).references/troubleshooting.md (scopes, admin rights, plan
limits) instead of retrying blindly. In sandboxes that block admin API paths the audit shows
“could not read”; say so instead of guessing the state.read_documentation tool in Claude Code cloud sessions). Fetch the page (WebFetch / browser), say which
URL you used, and tell the user the concrete next step. If the page does not answer it, say “not confirmed”.| Topic | URL |
|---|---|
| Repo settings API (alerts, security fixes, private vuln reporting, PATCH repo) | https://docs.github.com/en/rest/repos/repos |
| Code scanning default setup | https://docs.github.com/en/rest/code-scanning/code-scanning |
| Rulesets / rules for a branch | https://docs.github.com/en/rest/repos/rules |
| Classic branch protection | https://docs.github.com/en/rest/branches/branch-protection |
| Pages API | https://docs.github.com/en/rest/pages/pages |
| Actions workflow permissions | https://docs.github.com/en/rest/actions/permissions |
Releases API (/releases/latest) |
https://docs.github.com/en/rest/releases/releases |
| Token permissions per endpoint | https://docs.github.com/en/rest/authentication/permissions-required-for-fine-grained-personal-access-tokens |
| Dependabot options / ecosystems | https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference |
Auto-generated release notes (release.yml) |
https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes |
| Plans and which features are free | https://docs.github.com/en/get-started/learning-about-github/githubs-plans |
references/checks.md: every check: why, API, what apply does, how to revert.references/release-latest.md: version-less asset names, pre-release handling, workflow examples.references/troubleshooting.md: 403 errors, token scopes, private repo paid features.