Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!--
Title: prefix it with the type of change, e.g.
feat: add postgres-migrations skill
fix: correct verify-evals.mjs id uniqueness check
docs: clarify fork workflow in CONTRIBUTING.md
cicd: add markdownlint to the verify workflow
chore: bump dependabot schedule
-->

## Description

<!-- What does this PR do and why? One or two sentences. -->

## Implementation

<!-- What changed, and why this approach. Call out any tradeoffs or files
a reviewer should look at first. -->

## Testing

<!-- How you verified this works. For a skill change, include the output of:
node scripts/verify-skills.mjs
node scripts/verify-manifests.mjs
node scripts/check-internal-links.mjs
node scripts/verify-evals.mjs
-->

## Checklist

- [ ] PR title is prefixed with a change type (`feat:`, `fix:`, `docs:`, `cicd:`, `chore:`, `refactor:`, `test:`)
- [ ] `SKILL.md` documents existing behavior only — no invented commands, endpoints, or flags
- [ ] New/changed skill has both `## Validation commands` and `## Realistic usage boundaries` sections
- [ ] `evals/evals.json` has at least two cases (new or changed skills)
- [ ] README updated with a row for the skill (new skills)
- [ ] Verification suite passes locally (see Testing above)
32 changes: 32 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,38 @@

Thank you for contributing a skill to the community repo!

## Fork first — this is the normal flow

Nobody pushes branches directly to this repository, maintainers included.
`main` is protected, and the only way in is a fork plus a pull request. This
isn't a special hoop for outside contributors to jump through — it's how
every change lands here.

```bash
gh repo fork ForgeUtah/Skills --clone --remote
cd Skills
git checkout -b my-skill-name
# make your changes
git add <files>
git commit -m "add my-skill-name"
git push -u origin my-skill-name
gh pr create --fill --base main
```

`gh repo fork` clones the fork, sets it as your `origin` remote, and adds the
original repo as `upstream`. For a full walkthrough — including checking PR
status and pushing follow-up commits after review — see the
[`contribute-via-gh-cli`](skills/skills/contribute-via-gh-cli/) skill.

### PR title and description

Prefix the PR title with the type of change: `feat:`, `fix:`, `docs:`,
`cicd:`, `chore:`, `refactor:`, or `test:`. The description follows the
template in `.github/PULL_REQUEST_TEMPLATE.md`: a short **Description**, an
**Implementation** section explaining what changed and why, and a
**Testing** section showing how you verified it (for a skill change, the
output of the verification suite below).

## Ground rules

- **Skills document existing behavior.** If a skill names a command, endpoint,
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ Skills are organized by category:
| Databases | [`skills/db/`](skills/db/) | SQL, NoSQL, data modeling, migrations |
| Tools | [`skills/tools/`](skills/tools/) | General-purpose development tools and utilities |

## Available skills

| Skill | Category | What it does |
|-------|----------|---------------|
| [`contribute-via-gh-cli`](skills/skills/contribute-via-gh-cli/) | Skills | Fork a repo and open a pull request entirely with `gh`, for repos where you don't have push access. |

## Installing

### Copyable setup prompt
Expand Down
4 changes: 4 additions & 0 deletions skills/skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
Skills about skill development, meta-skills, and agent skill tooling.

Add your skill as a subdirectory with a `SKILL.md` and `evals/evals.json`.

| Skill | What it does |
|-------|---------------|
| [`contribute-via-gh-cli`](contribute-via-gh-cli/) | Fork a repo and open a pull request entirely with `gh`, for repos where you don't have push access. |
191 changes: 191 additions & 0 deletions skills/skills/contribute-via-gh-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
---
name: contribute-via-gh-cli
description: Walks a contributor through forking a GitHub repository and opening a pull request entirely with the gh CLI, for repos where the contributor has no direct push access (protected main branch, PR-only workflow, e.g. ForgeUtah/Skills). Use whenever the user wants to contribute a change but doesn't have write access, asks "how do I submit a PR to this repo", mentions forking a repo, or hits a push rejection like "Permission to X denied" or "protected branch" on a repo they don't own. Also use when a maintainer asks how outside contributors should submit changes.
---

# Contribute via gh CLI (fork + pull request)

## Why this is the normal flow, not a workaround

On a repo you don't have write access to — including this one,
`ForgeUtah/Skills` — there is no setting that grants the public direct push
access to branches. GitHub's permission model only ever grants push access to
specific people or teams. The standard, expected path for everyone who isn't
a collaborator is: fork the repo, push commits to your fork, open a pull
request from the fork back to the original. Maintainers use the same path.

Treat "I don't have push access" as the normal starting state, not an error
to route around. Never suggest disabling branch protection, adding the user
as a collaborator, or any other workaround — those are decisions only a repo
admin can make, and the fork workflow below is the actual intended path.

## Prerequisites

Confirm the `gh` CLI is installed and authenticated before starting:

```bash
gh auth status
```

If this reports no authenticated account, stop and tell the user to run
`gh auth login` themselves — do not attempt to authenticate on their behalf.

## Step 1 — Fork the repository

If you don't have a local clone yet, fork and clone in one step:

```bash
gh repo fork OWNER/REPO --clone --remote
cd REPO
```

If you already have a local clone of the upstream repo, run `gh repo fork`
with no arguments from inside it:

```bash
gh repo fork --remote
```

In both cases, `gh repo fork`:

- Creates the fork under your GitHub account (or an org, with `--org NAME`).
- Sets the new fork as your `origin` remote.
- Renames any existing `origin` remote to `upstream` and sets it as the
default remote repository.

Verify the remotes landed the way you expect:

```bash
git remote -v
```

`origin` should point at `github.com/<your-username>/REPO`, and `upstream`
(if you started from an existing clone) at the original repo.

## Step 2 — Branch, make changes, commit

Work on a feature branch, never directly on `main` — a PR from `main` on your
fork works, but a dedicated branch keeps your fork's `main` clean for future
contributions.

```bash
git checkout -b descriptive-branch-name
# edit files
git add <specific files>
git commit -m "concise summary of the change"
```

Follow this repository's own contribution rules (see `CONTRIBUTING.md`) for
what the change itself needs to contain and which verification scripts to
run before committing — this skill only covers the git/GitHub mechanics of
getting the change up for review, not the content requirements.

## Step 3 — Push to your fork

```bash
git push -u origin descriptive-branch-name
```

This pushes to your fork (`origin`), not the upstream repo — you don't have
push access to upstream, and that's expected. Pushing to `origin` cannot fail
with a permission or protected-branch error, since it's your own fork.

## Step 4 — Open the pull request

From inside the branch, with the fork's `origin` remote already set:

```bash
gh pr create --title "type: short summary" --body-file - --base main <<'EOF'
## Description

...

## Implementation

...

## Testing

...
EOF
```

- `--title` should start with the change type the target repo asks for —
check its `CONTRIBUTING.md` and `.github/PULL_REQUEST_TEMPLATE.md` if it
has one; this repo (`ForgeUtah/Skills`) uses `feat:`, `fix:`, `docs:`,
`cicd:`, `chore:`, `refactor:`, `test:`.
- `--body-file -` reads the body from stdin so you can fill in a structured
template (Description / Implementation / Testing, or whatever the repo's
own template specifies) instead of a single free-text blurb. If the repo
has no template, `--fill` (pull title/body from the commit message) is a
reasonable default instead.
- `--base main` targets the upstream repo's default branch explicitly; omit
it to fall back to the repo's configured default branch.
- `gh pr create` detects that your branch lives on a fork and automatically
opens the PR against the upstream repo — no need to pass `--repo` or spell
out the `user:branch` head syntax unless you're targeting a different base
repo than the one `upstream` points to.

Add `--draft` to open it as a draft, or `--web` to finish the flow in the
browser instead of the terminal.

## Step 5 — Track the PR and push follow-up commits

Check status and CI without leaving the terminal:

```bash
gh pr status
gh pr view --web
gh pr checks
```

After review feedback, keep committing on the same branch and push again —
no need to re-run `gh pr create`, the existing PR updates automatically:

```bash
git add <files>
git commit -m "address review feedback"
git push
```

## Keeping your fork in sync

Before starting a new contribution, or if `upstream` has moved on since you
forked, sync your fork's default branch:

```bash
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
```

## Validation commands

Confirm each step actually worked rather than assuming success from a lack
of error output:

```bash
gh auth status # confirms you're authenticated before starting
git remote -v # confirms origin = your fork, upstream = original repo
gh repo view --json parent --jq .parent.nameWithOwner # confirms this clone is a fork, and of what
gh pr view --json url,state,baseRefName,headRepositoryOwner # confirms the PR opened against the right base/head
```

## Realistic usage boundaries

This skill covers the git/GitHub mechanics of forking and opening a PR. It
does not cover:

- What content the change itself should contain, which verification scripts
to run, or where files belong in the target repo — that's the target
repo's own `CONTRIBUTING.md`.
- Resolving merge conflicts beyond a simple `git merge upstream/main`.
- Getting the PR approved or merged — that's up to the target repo's code
owners/reviewers (see that repo's `CODEOWNERS`), not something `gh` or this
skill can do for the contributor.
- Repos that genuinely do grant broad write access (internal/trusted-team
repos) — for those, a simple branch-and-push on the original repo is
correct and forking is unnecessary overhead.
- Non-GitHub remotes (GitLab, Bitbucket, self-hosted Git) — the concepts
transfer but the CLI commands here are `gh`-specific.
38 changes: 38 additions & 0 deletions skills/skills/contribute-via-gh-cli/evals/evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"skill_name": "contribute-via-gh-cli",
"evals": [
{
"id": 1,
"prompt": "I want to submit a fix to ForgeUtah/Skills but `git push` gave me a permission denied error. How do I actually get my change in?",
"expected_output": "Explains that push access isn't granted to outside contributors and this is expected/normal, then walks through: gh repo fork --clone --remote, creating a branch, committing, git push -u origin <branch>, and gh pr create --fill --base main.",
"expectations": [
"States that lacking push access is the normal/expected state, not an error to work around",
"Does not suggest disabling branch protection or requesting collaborator access as the solution",
"Includes the exact command 'gh repo fork' with --clone and --remote",
"Includes pushing to the 'origin' remote (the fork), not attempting to push to upstream",
"Includes 'gh pr create' with --base main"
]
},
{
"id": 2,
"prompt": "I already have ForgeUtah/Skills cloned locally and have write access to nothing. Walk me through forking it and opening a PR for a new skill I just wrote, using gh.",
"expected_output": "Since a clone already exists, runs `gh repo fork --remote` (no arguments) from inside it rather than cloning fresh, explains this renames the existing origin to upstream and sets the fork as origin, then branches, commits, pushes to origin, and runs gh pr create.",
"expectations": [
"Recommends 'gh repo fork --remote' with no repository argument, not a fresh clone, since a local clone already exists",
"Explains that origin becomes the fork and the prior origin becomes upstream",
"Includes creating a feature branch before committing",
"Includes 'gh pr create' to open the pull request"
]
},
{
"id": 3,
"prompt": "My PR to a forked repo got review comments. How do I check its status and push more changes with gh?",
"expected_output": "Explains you don't need to re-run gh pr create; just commit and git push on the same branch to update the existing PR, and shows gh pr status / gh pr view / gh pr checks for tracking status.",
"expectations": [
"States that pushing more commits to the same branch updates the existing PR automatically",
"Does not instruct re-running 'gh pr create' for the follow-up commits",
"Mentions at least one status-checking command such as 'gh pr status', 'gh pr view', or 'gh pr checks'"
]
}
]
}
Loading