📄 SKILL.md

← Vault

name: github-repo-management

description: Clone, create, fork, configure, and manage GitHub repositories. Manage remotes, secrets, releases, and workflows. Works with gh CLI or falls back to git + GitHub REST API via curl.

version: 1.1.0

author: Hermes Agent

license: MIT

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

Setup

`bash

if command -v gh &>/dev/null && gh auth status &>/dev/null; then

AUTH="gh"

else

AUTH="git"

if [ -z "$GITHUB_TOKEN" ]; then

if [ -f ~/.hermes/.env ] && grep -q "^GITHUB_TOKEN=" ~/.hermes/.env; then

GITHUB_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; then

GITHUB_TOKEN=$(grep "github.com" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]:\([^@]\)@.*|\1|')

fi

fi

fi

Get your GitHub username (needed for several operations)

if [ "$AUTH" = "gh" ]; then

GH_USER=$(gh api user --jq '.login')

else

GH_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:

`bash

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:

`bash

Clone via HTTPS (works with credential helper or token-embedded URL)

git clone https://github.com/owner/repo-name.git

Clone into a specific directory

git 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 branch

git 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):

`bash

gh repo clone owner/repo-name

gh repo clone owner/repo-name -- --depth 1

`

2. Creating Repositories

With gh:

`bash

Create a public repo and clone it

gh repo create my-new-project --public --clone

Private, with description and license

gh repo create my-new-project --private --description "A useful tool" --license MIT --clone

Under an organization

gh repo create my-org/my-new-project --public --clone

From existing local directory

cd /path/to/existing/project

gh repo create my-project --source . --public --push

`

With git + curl:

`bash

Create the remote repo via API

curl -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 it

git clone https://github.com/$GH_USER/my-new-project.git

cd my-new-project

-- OR -- push an existing local directory to the new repo

cd /path/to/existing/project

git init

git add .

git commit -m "Initial commit"

git remote add origin https://github.com/$GH_USER/my-new-project.git

git push -u origin main

`

To create under an organization:

`bash

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:

`bash

gh repo create my-new-app --template owner/template-repo --public --clone

`

With curl:

`bash

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:

`bash

gh repo fork owner/repo-name --clone

`

With git + curl:

`bash

Create the fork via API

curl -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 clone

sleep 3

git clone https://github.com/$GH_USER/repo-name.git

cd repo-name

Add the original repo as "upstream" remote

git remote add upstream https://github.com/owner/repo-name.git

`

Keeping a Fork in Sync

`bash

Pure git — works everywhere

git fetch upstream

git checkout main

git merge upstream/main

git push origin main

`

With gh (shortcut):

`bash

gh repo sync $GH_USER/repo-name

`

4. Repository Information

With gh:

`bash

gh repo view owner/repo-name

gh repo list --limit 20

gh search repos "machine learning" --language python --sort stars

`

With curl:

`bash

View repo details

curl -s \

-H "Authorization: token $GITHUB_TOKEN" \

https://api.github.com/repos/$OWNER/$REPO \

| python3 -c "

import sys, json

r = 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 repos

curl -s \

-H "Authorization: token $GITHUB_TOKEN" \

"https://api.github.com/user/repos?per_page=20&sort=updated" \

| python3 -c "

import sys, json

for 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 repos

curl -s \

"https://api.github.com/search/repositories?q=machine+learning+language:python&sort=stars&per_page=10" \

| python3 -c "

import sys, json

for 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:

`bash

gh repo edit --description "Updated description" --visibility public

gh repo edit --enable-wiki=false --enable-issues=true

gh repo edit --default-branch main

gh repo edit --add-topic "machine-learning,python"

gh repo edit --enable-auto-merge

`

With curl:

`bash

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 topics

curl -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

`bash

View current protection

curl -s \

-H "Authorization: token $GITHUB_TOKEN" \

https://api.github.com/repos/$OWNER/$REPO/branches/main/protection

Set up branch protection

curl -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:

`bash

gh secret set API_KEY --body "your-secret-value"

gh secret set SSH_KEY < ~/.ssh/id_rsa

gh secret list

gh secret delete API_KEY

`

With curl:

Secrets require encryption with the repo's public key — more involved via API:

`bash

Get the repo's public key for encrypting secrets

curl -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 b64encode

from nacl import encoding, public

import json, sys

Get the public key

key_id = ''

public_key = ''

Encrypt

sealed = 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 secret

curl -s -X PUT \

-H "Authorization: token $GITHUB_TOKEN" \

https://api.github.com/repos/$OWNER/$REPO/actions/secrets/API_KEY \

-d ''

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, json

for 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:

`bash

gh release create v1.0.0 --title "v1.0.0" --generate-notes

gh release create v2.0.0-rc1 --draft --prerelease --generate-notes

gh release create v1.0.0 ./dist/binary --title "v1.0.0" --notes "Release notes"

gh release list

gh release download v1.0.0 --dir ./downloads

`

With curl:

`bash

Create a release

curl -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 releases

curl -s \

-H "Authorization: token $GITHUB_TOKEN" \

https://api.github.com/repos/$OWNER/$REPO/releases \

| python3 -c "

import sys, json

for 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=

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:

`bash

gh workflow list

gh run list --limit 10

gh run view

gh run view --log-failed

gh run rerun

gh run rerun --failed

gh workflow run ci.yml --ref main

gh workflow run deploy.yml -f environment=staging

`

With curl:

`bash

List workflows

curl -s \

-H "Authorization: token $GITHUB_TOKEN" \

https://api.github.com/repos/$OWNER/$REPO/actions/workflows \

| python3 -c "

import sys, json

for w in json.load(sys.stdin)['workflows']:

print(f\" {w['id']:10} {w['name']:30} {w['state']}\")"

List recent runs

curl -s \

-H "Authorization: token $GITHUB_TOKEN" \

"https://api.github.com/repos/$OWNER/$REPO/actions/runs?per_page=10" \

| python3 -c "

import sys, json

for r in json.load(sys.stdin)['workflow_runs']:

print(f\" Run {r['id']} {r['name']:30} {r['conclusion'] or r['status']}\")"

Download failed run logs

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.zip

cd /tmp && unzip -o ci-logs.zip -d ci-logs

Re-run a failed workflow

curl -s -X POST \

-H "Authorization: token $GITHUB_TOKEN" \

https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/rerun

Re-run only failed jobs

curl -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=

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:

`bash

gh gist create script.py --public --desc "Useful script"

gh gist list

`

With curl:

`bash

Create a gist

curl -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 gists

curl -s \

-H "Authorization: token $GITHUB_TOKEN" \

https://api.github.com/gists \

| python3 -c "

import sys, json

for 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

Actionghgit + curl
------------------------
Clonegh repo clone o/rgit clone https://github.com/o/r.git
Create repogh repo create name --publiccurl POST /user/repos
Forkgh repo fork o/r --clonecurl POST /repos/o/r/forks + git clone
Repo infogh repo view o/rcurl GET /repos/o/r
Edit settingsgh repo edit --...curl PATCH /repos/o/r
Create releasegh release create v1.0curl POST /repos/o/r/releases
List workflowsgh workflow listcurl GET /repos/o/r/actions/workflows
Rerun CIgh run rerun IDcurl POST /repos/o/r/actions/runs/ID/rerun
Set secretgh secret set KEYcurl PUT /repos/o/r/actions/secrets/KEY (+ encryption)