Skill v1.1.0
currentAutomated scan94/100+5 new
name: github-repo-management description: "Clone/create/fork repos; manage remotes, releases." version: 1.1.0 author: Hermes Agent license: MIT platforms: [linux, macos, windows] metadata: hermes: tags: [GitHub, Repositories, Git, Releases, Secrets, Configuration] related_skills: [github-auth, github-pr-workflow, github-issues]
GitHub Repository Management
Create, clone, fork, configure, and manage GitHub repositories. Each section shows gh first, then the git + curl fallback.
Prerequisites
- Authenticated with GitHub (see
github-authskill)
Setup
if command -v gh &>/dev/null && gh auth status &>/dev/null; thenAUTH="gh"elseAUTH="git"if [ -z "$GITHUB_TOKEN" ]; thenif _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -f "$_hermes_env" ] && grep -q "^GITHUB_TOKEN=" "$_hermes_env"; thenGITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" "$_hermes_env" | head -1 | cut -d= -f2 | tr -d '\n\r')elif grep -q "github.com" ~/.git-credentials 2>/dev/null; thenGITHUB_TOKEN=$(grep "github.com" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]*:\([^@]*\)@.*|\1|')fififi# Get your GitHub username (needed for several operations)if [ "$AUTH" = "gh" ]; thenGH_USER=$(gh api user --jq '.login')elseGH_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user | python3 -c "import sys,json; print(json.load(sys.stdin)['login'])")fi
If you're inside a repo already:
REMOTE_URL=$(git remote get-url origin)OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github\.com[:/]||; s|\.git$||')OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1)REPO=$(echo "$OWNER_REPO" | cut -d/ -f2)
1. Cloning Repositories
Cloning is pure git — works identically either way:
# Clone via HTTPS (works with credential helper or token-embedded URL)git clone https://github.com/owner/repo-name.git# Clone into a specific directorygit clone https://github.com/owner/repo-name.git ./my-local-dir# Shallow clone (faster for large repos)git clone --depth 1 https://github.com/owner/repo-name.git# Clone a specific branchgit clone --branch develop https://github.com/owner/repo-name.git# Clone via SSH (if SSH is configured)git clone git@github.com:owner/repo-name.git
With gh (shorthand):
gh repo clone owner/repo-namegh repo clone owner/repo-name -- --depth 1
2. Creating Repositories
With gh:
# Create a public repo and clone itgh repo create my-new-project --public --clone# Private, with description and licensegh repo create my-new-project --private --description "A useful tool" --license MIT --clone# Under an organizationgh repo create my-org/my-new-project --public --clone# From existing local directorycd /path/to/existing/projectgh repo create my-project --source . --public --push
With git + curl:
# Create the remote repo via APIcurl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/user/repos \-d '{"name": "my-new-project","description": "A useful tool","private": false,"auto_init": true,"license_template": "mit"}'# Clone itgit clone https://github.com/$GH_USER/my-new-project.gitcd my-new-project# -- OR -- push an existing local directory to the new repocd /path/to/existing/projectgit initgit add .git commit -m "Initial commit"git remote add origin https://github.com/$GH_USER/my-new-project.gitgit push -u origin main
To create under an organization:
curl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/orgs/my-org/repos \-d '{"name": "my-new-project", "private": false}'
From a Template
With gh:
gh repo create my-new-app --template owner/template-repo --public --clone
With curl:
curl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/owner/template-repo/generate \-d '{"owner": "'"$GH_USER"'", "name": "my-new-app", "private": false}'
3. Forking Repositories
With gh:
gh repo fork owner/repo-name --clone
With git + curl:
# Create the fork via APIcurl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/owner/repo-name/forks# Wait a moment for GitHub to create it, then clonesleep 3git clone https://github.com/$GH_USER/repo-name.gitcd repo-name# Add the original repo as "upstream" remotegit remote add upstream https://github.com/owner/repo-name.git
Keeping a Fork in Sync
# Pure git — works everywheregit fetch upstreamgit checkout maingit merge upstream/maingit push origin main
With gh (shortcut):
gh repo sync $GH_USER/repo-name
4. Repository Information
With gh:
gh repo view owner/repo-namegh repo list --limit 20gh search repos "machine learning" --language python --sort stars
With curl:
# View repo detailscurl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO \| python3 -c "import sys, jsonr = json.load(sys.stdin)print(f\"Name: {r['full_name']}\")print(f\"Description: {r['description']}\")print(f\"Stars: {r['stargazers_count']} Forks: {r['forks_count']}\")print(f\"Default branch: {r['default_branch']}\")print(f\"Language: {r['language']}\")"# List your reposcurl -s \-H "Authorization: token $GITHUB_TOKEN" \"https://api.github.com/user/repos?per_page=20&sort=updated" \| python3 -c "import sys, jsonfor r in json.load(sys.stdin):vis = 'private' if r['private'] else 'public'print(f\" {r['full_name']:40} {vis:8} {r.get('language', ''):10} ★{r['stargazers_count']}\")"# Search reposcurl -s \"https://api.github.com/search/repositories?q=machine+learning+language:python&sort=stars&per_page=10" \| python3 -c "import sys, jsonfor r in json.load(sys.stdin)['items']:print(f\" {r['full_name']:40} ★{r['stargazers_count']:6} {r['description'][:60] if r['description'] else ''}\")"
5. Repository Settings
With gh:
gh repo edit --description "Updated description" --visibility publicgh repo edit --enable-wiki=false --enable-issues=truegh repo edit --default-branch maingh repo edit --add-topic "machine-learning,python"gh repo edit --enable-auto-merge
With curl:
curl -s -X PATCH \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO \-d '{"description": "Updated description","has_wiki": false,"has_issues": true,"allow_auto_merge": true}'# Update topicscurl -s -X PUT \-H "Authorization: token $GITHUB_TOKEN" \-H "Accept: application/vnd.github.mercy-preview+json" \https://api.github.com/repos/$OWNER/$REPO/topics \-d '{"names": ["machine-learning", "python", "automation"]}'
6. Branch Protection
# View current protectioncurl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/branches/main/protection# Set up branch protectioncurl -s -X PUT \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/branches/main/protection \-d '{"required_status_checks": {"strict": true,"contexts": ["ci/test", "ci/lint"]},"enforce_admins": false,"required_pull_request_reviews": {"required_approving_review_count": 1},"restrictions": null}'
7. Secrets Management (GitHub Actions)
With gh:
gh secret set API_KEY --body "your-secret-value"gh secret set SSH_KEY < ~/.ssh/id_rsagh secret listgh secret delete API_KEY
With curl:
Secrets require encryption with the repo's public key — more involved via API:
# Get the repo's public key for encrypting secretscurl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/secrets/public-key# Encrypt and set (requires Python with PyNaCl)python3 -c "from base64 import b64encodefrom nacl import encoding, publicimport json, sys# Get the public keykey_id = '<key_id_from_above>'public_key = '<base64_key_from_above>'# Encryptsealed = public.SealedBox(public.PublicKey(public_key.encode('utf-8'), encoding.Base64Encoder)).encrypt('your-secret-value'.encode('utf-8'))print(json.dumps({'encrypted_value': b64encode(sealed).decode('utf-8'),'key_id': key_id}))"# Then PUT the encrypted secretcurl -s -X PUT \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/secrets/API_KEY \-d '<output from python script above>'# List secrets (names only, values hidden)curl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/secrets \| python3 -c "import sys, jsonfor s in json.load(sys.stdin)['secrets']:print(f\" {s['name']:30} updated: {s['updated_at']}\")"
Note: For secrets, gh secret set is dramatically simpler. If setting secrets is needed and gh isn't available, recommend installing it for just that operation.
8. Releases
With gh:
gh release create v1.0.0 --title "v1.0.0" --generate-notesgh release create v2.0.0-rc1 --draft --prerelease --generate-notesgh release create v1.0.0 ./dist/binary --title "v1.0.0" --notes "Release notes"gh release listgh release download v1.0.0 --dir ./downloads
With curl:
# Create a releasecurl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/releases \-d '{"tag_name": "v1.0.0","name": "v1.0.0","body": "## Changelog\n- Feature A\n- Bug fix B","draft": false,"prerelease": false,"generate_release_notes": true}'# List releasescurl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/releases \| python3 -c "import sys, jsonfor r in json.load(sys.stdin):tag = r.get('tag_name', 'no tag')print(f\" {tag:15} {r['name']:30} {'draft' if r['draft'] else 'published'}\")"# Upload a release asset (binary file)RELEASE_ID=<id_from_create_response>curl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \-H "Content-Type: application/octet-stream" \"https://uploads.github.com/repos/$OWNER/$REPO/releases/$RELEASE_ID/assets?name=binary-amd64" \--data-binary @./dist/binary-amd64
9. GitHub Actions Workflows
With gh:
gh workflow listgh run list --limit 10gh run view <RUN_ID>gh run view <RUN_ID> --log-failedgh run rerun <RUN_ID>gh run rerun <RUN_ID> --failedgh workflow run ci.yml --ref maingh workflow run deploy.yml -f environment=staging
With curl:
# List workflowscurl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/workflows \| python3 -c "import sys, jsonfor w in json.load(sys.stdin)['workflows']:print(f\" {w['id']:10} {w['name']:30} {w['state']}\")"# List recent runscurl -s \-H "Authorization: token $GITHUB_TOKEN" \"https://api.github.com/repos/$OWNER/$REPO/actions/runs?per_page=10" \| python3 -c "import sys, jsonfor r in json.load(sys.stdin)['workflow_runs']:print(f\" Run {r['id']} {r['name']:30} {r['conclusion'] or r['status']}\")"# Download failed run logsRUN_ID=<run_id>curl -s -L \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/logs \-o /tmp/ci-logs.zipcd /tmp && unzip -o ci-logs.zip -d ci-logs# Re-run a failed workflowcurl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/rerun# Re-run only failed jobscurl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/rerun-failed-jobs# Trigger a workflow manually (workflow_dispatch)WORKFLOW_ID=<workflow_id_or_filename>curl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/repos/$OWNER/$REPO/actions/workflows/$WORKFLOW_ID/dispatches \-d '{"ref": "main", "inputs": {"environment": "staging"}}'
10. Gists
With gh:
gh gist create script.py --public --desc "Useful script"gh gist list
With curl:
# Create a gistcurl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/gists \-d '{"description": "Useful script","public": true,"files": {"script.py": {"content": "print(\"hello\")"}}}'# List your gistscurl -s \-H "Authorization: token $GITHUB_TOKEN" \https://api.github.com/gists \| python3 -c "import sys, jsonfor g in json.load(sys.stdin):files = ', '.join(g['files'].keys())print(f\" {g['id']} {g['description'] or '(no desc)':40} {files}\")"
Quick Reference Table
| Action | gh | git + curl | |
|---|---|---|---|
| Clone | gh repo clone o/r | git clone https://github.com/o/r.git | |
| Create repo | gh repo create name --public | curl POST /user/repos | |
| Fork | gh repo fork o/r --clone | curl POST /repos/o/r/forks + git clone | |
| Repo info | gh repo view o/r | curl GET /repos/o/r | |
| Edit settings | gh repo edit --... | curl PATCH /repos/o/r | |
| Create release | gh release create v1.0 | curl POST /repos/o/r/releases | |
| List workflows | gh workflow list | curl GET /repos/o/r/actions/workflows | |
| Rerun CI | gh run rerun ID | curl POST /repos/o/r/actions/runs/ID/rerun | |
| Set secret | gh secret set KEY | curl PUT /repos/o/r/actions/secrets/KEY (+ encryption) |