Claude
Skills
Sign in
Back

contribute

Included with Lifetime
$97 forever

Local-only OSS contribution command center. Auto-refreshes the user's in-flight PR and issue state on invoke so conversations start with full context — no need to brief Claude on what's in flight. Helps the user find issues to contribute to on GitHub, builds per-repo dossiers of what each upstream expects (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates), runs deterministic gates before any external action so AI-assisted contributions don't reach maintainers as slop. State is markdown-only: candidate files at ~/.contribute-system/candidates/, repo dossiers at ~/.contribute-system/research/, append-only event log at ~/.contribute-system/log.jsonl. No database, no cloud calls. Use when the user asks about their PRs / issues / contributions, wants to find new work to take on, claim an issue, build/refresh a repo's dossier, or draft a Design Issue or PR. Trigger with "/contribute", "what's my PR status", "find a contribution", "claim issue X", "draft a Design Issue for Y", "refresh dossier for Z".

Designosscontributionsgithubcontributing-clankerai-slop-preventionscriptsassets

What this skill does


# Contribute Command Center

## Overview

Local-only OSS contribution workflow. The skill itself is the system — there is no separate CLI binary, dashboard, or cloud backend. State lives in three places:

1. **GitHub itself** — fetched live via `gh` for any PR/issue state question. Never cached long-term.
2. **Markdown candidate files** at `~/.contribute-system/candidates/<owner>__<repo>__issue<N>.md` — one per issue we're tracking. Frontmatter is the queryable layer (status, scout_score, repo, research_path, overrides). Body holds claim drafts, PR drafts, scope notes.
3. **Markdown repo dossiers** at `~/.contribute-system/research/<owner>__<repo>.md` — one per upstream repo we contribute to. Built by the `@researcher` subagent. Frontmatter is canonical for every gate (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates). Body holds curated knowledge: pet peeves, failure log, free-form notes that survive refresh.
4. **Append-only event log** at `~/.contribute-system/log.jsonl` — every gate run, transition attempt, override, scout/researcher invocation lands here with a UTC timestamp. Filterable via `jq`.

Use this skill when the user wants to:

- Know what's in flight (open PRs, claimed issues, candidate queue)
- Find a new issue to contribute to on GitHub
- Build or refresh a per-repo dossier (delegates to `@researcher`)
- Run gate-checked transitions (claim, work, submit) — every external action passes through `transition.sh` first
- Draft a claim comment, Design Issue, or PR description (default: Design Issue, NOT a PR)
- Run an upstream repo's test suite

The pre-2026-04-30 version of the skill used a SQLite tracker (`~/.contribute-system/contribute.db`, 32 tables) plus a separate `contribute-system/` monorepo (Next.js dashboard, TS CLI, Cloud Functions). Both were deleted because they were never used in practice. The skill now reads markdown directly. That tradeoff is deliberate: human-readable, greppable, git-trackable, survives any tool, no daemon process.

## Prerequisites

- **`gh` CLI**, authenticated as the user (`gh auth status` should show "Logged in")
- **`jq`** on PATH (used by gates + log filtering)
- **Workspace** at `~/000-projects/contributing-clanker/` containing upstream clones (each clone has its own `CLAUDE.md` for project conventions)
- **Runtime state dir** at `~/.contribute-system/` — created on first scout/researcher run if missing

Run this DCI check at activation (output is auto-injected into the prompt):

```!
gh auth status >/dev/null 2>&1 && echo "gh: ok" || echo "gh: NOT logged in"
[ -d ~/.contribute-system/gates ] && echo "gates: $(ls ~/.contribute-system/gates/*.sh 2>/dev/null | wc -l) installed" || echo "gates: not yet installed"
[ -d ~/.contribute-system/candidates ] && echo "candidates: $(ls ~/.contribute-system/candidates/*.md 2>/dev/null | wc -l) tracked" || echo "candidates: empty"
[ -d ~/.contribute-system/research ] && echo "dossiers: $(ls ~/.contribute-system/research/*.md 2>/dev/null | wc -l) built" || echo "dossiers: empty"
[ -f ~/.contribute-system/profile.md ] && echo "profile: ok" || echo "profile: missing — edit ~/.contribute-system/profile.md"
[ -f ~/.contribute-system/log.jsonl ] && echo "log: $(wc -l < ~/.contribute-system/log.jsonl) events" || echo "log: empty"
```

## Instructions

### Step 0 — Refresh state (run first, every time)

Before answering anything contribution-related, surface current state. Run these in **parallel** with the Bash tool:

```bash
# Upstream PRs in flight (filtered to outside-org repos only —
# the system tracks contributions INTO repos the user does not own;
# own-repo PRs are out of scope and must be excluded).
#
# OWN_ORGS is the prefix list of repos to exclude. Update if the user
# adds a new org. (Discoverable via `gh api user/orgs --jq '.[].login'`
# plus the user's own login from `gh api user --jq '.login'`.)
OWN_ORGS='jeremylongshore/ intent-solutions-io/'
gh search prs --author=@me --state=open --limit=50 \
  --json number,title,url,repository,isDraft,createdAt | \
  jq --arg own "$OWN_ORGS" '
    ($own | split(" ")) as $excl |
    map(select(.repository.nameWithOwner as $r |
               ($excl | map(. as $p | $r | startswith($p)) | any) | not))
  '

# Recently-merged + closed upstream PRs (last 30, same scope filter)
gh search prs --author=@me --state=closed --limit=30 \
  --json number,title,url,repository,closedAt,createdAt | \
  jq --arg own "$OWN_ORGS" '
    ($own | split(" ")) as $excl |
    map(select(.repository.nameWithOwner as $r |
               ($excl | map(. as $p | $r | startswith($p)) | any) | not))
  '

# Local candidate tracker — markdown frontmatter is the queryable layer.
# Candidates are upstream-only by construction (scout never enqueues
# own-repo issues), so no scope filter needed here.
for f in ~/.contribute-system/candidates/*.md; do
  awk -v f="$(basename "$f" .md)" '
    /^---$/ { fm = !fm ? 1 : 2; next }
    fm == 1 && /^(repo|issue_number|status|scout_score|research_path|pr_number):/ { print f, $0 }
  ' "$f"
done 2>/dev/null

# Recent activity from the event log
tail -50 ~/.contribute-system/log.jsonl 2>/dev/null \
  | jq -c "select(.event | test(\"transition_|gate_|researcher_|scout_\"))" 2>/dev/null
```

**Scope rule (non-negotiable)**: this skill applies *only* to contributions made INTO repos the user does not own. Own-org PRs (`jeremylongshore/*`, `intent-solutions-io/*`) are out of scope — they are personal-project work, not anti-slop OSS contributions. The whole architecture (gates, dossiers, lifecycle) exists because upstream maintainers need protection from low-quality AI work; that concern doesn't apply to the user's own repos. If a candidate file ever references an own-org repo, it's a scout bug — flag it.

Then summarize for the user:

- N open / draft PRs (and any blocked on review)
- N candidates in `claimed` or `working` status but not yet `submitted`
- N candidates in `open` / `shortlist` status (sorted by `scout_score` desc)
- Any contradictions between `gh` (PR state) and the candidate's `status:` field (e.g., PR merged but candidate still says `submitted`) — flag for cleanup
- N candidates whose `research_path:` is empty or stale (>14d) — flag for `@researcher` build/refresh
- Recent events worth surfacing (gate BLOCKs, overrides, dossier refreshes)

Skip Step 0 only when the user asks about something unrelated to their own contributions.

### Step 0.5 — Ensure dossier exists for any repo we'll touch

Every repo we contribute to needs a dossier at
`~/.contribute-system/research/<owner>__<repo>.md` — that's where every gate
in `~/.contribute-system/gates/` reads its rules from (branch convention,
CLA/DCO, AI policy, draft-first preference, review bots, etc.).

Before any lifecycle transition (claim, work, submit) for a candidate at
repo `<owner>/<repo>`:

```bash
DOSSIER=~/.contribute-system/research/$(echo <owner>/<repo> | tr '/' '_').md
DOSSIER=${DOSSIER/__/__}    # ensure double underscore
if [[ ! -f "$DOSSIER" ]]; then
  echo "no dossier — invoking @researcher"
  # delegate to the researcher subagent
fi
# Also check staleness — refresh if >14 days old
LAST=$(awk '/^last_refreshed:/{print $2; exit}' "$DOSSIER")
if [[ -n "$LAST" ]]; then
  AGE_DAYS=$(( ( $(date +%s) - $(date -d "$LAST" +%s) ) / 86400 ))
  [[ "$AGE_DAYS" -gt 14 ]] && echo "stale ($AGE_DAYS d) — invoking @researcher refresh"
fi
```

Delegate dossier build/refresh to the **`@researcher`** subagent (defined
at `${CLAUDE_SKILL_DIR}/agents/researcher.md`). It runs in its own context window so
the verbose CONTRIBUTING.md fetch + depth-1 link follows stay out of your
main conversation. It writes the dossier to disk and reports back a
one-paragraph summary.

If the user already invoked `@researcher` earlier in the session for this
repo, skip — don't re-build.

### Step 1 — Discover

Find issues worth contributing to. Sources, in priority order:

- **Existing candidates** with `status: open` or `status: shortlist` already

Related in Design