{"id":"d5a422eb-597e-46a6-85d7-9ec75caa885f","shortId":"fRXCSp","kind":"skill","title":"lovstudio:gh-contribute","tagline":"Contribute a clean, professional pull request to someone else's GitHub repository: fork → clone → branch → commit → push → open PR, with smart splitting into one or multiple PRs based on the scope of changes. Trigger when the user says \"给这个 repo 提 PR\"、\"贡献代码\"、\"fork 然后改再 PR\"、 \"cont","description":"# gh-contribute — Clean PRs to Upstream Repos\n\nTurn local changes into a clean, professional pull request against an upstream repo\nyou don't own. Handles the full fork → branch → commit → push → PR pipeline, and\nsplits work into multiple PRs when the changes span unrelated concerns.\n\n## When to Use\n\n- User wants to contribute to an open-source project they don't have write access to\n- User already has local edits and needs them shipped as a PR upstream\n- User asks to \"fork this repo and send a PR\"\n- User has mixed changes (e.g. docs + feature + refactor) and wants them split properly\n\n## Non-Goals\n\n- Does **not** write code changes — assumes the user (or a prior step) already has\n  the desired modifications in the working tree or in their head\n- Does **not** review the project's own PRs (see `gh-tidy`)\n- Does **not** mirror to GitLab/Gitea — GitHub only\n\n## Workflow (MANDATORY)\n\nExecute steps in order. Do not skip confirmations.\n\n### Step 1: Identify the target repo\n\nDetermine the upstream `owner/repo`:\n\n1. If the user pasted a URL or `owner/repo` string → use it\n2. Otherwise run `git remote -v` in the current directory and pick the `origin`\n   (if origin is already the user's fork, find the upstream via\n   `gh repo view --json parent`)\n\nRecord three facts:\n- `UPSTREAM` — e.g. `ZenMux/zenmux-doc`\n- `DEFAULT_BRANCH` — from `gh repo view $UPSTREAM --json defaultBranchRef -q .defaultBranchRef.name`\n- `USER_LOGIN` — from `gh api user -q .login`\n\n### Step 2: Read the contribution rules\n\nFetch `CONTRIBUTING.md` and `CODE_OF_CONDUCT.md` from upstream (if present) and\nskim for: commit message format, DCO/CLA requirements, branch naming, PR template.\nCarry these constraints into subsequent steps.\n\n```bash\ngh api repos/$UPSTREAM/contents/CONTRIBUTING.md -q .content 2>/dev/null | base64 -d\n```\n\nIf the repo has `.github/PULL_REQUEST_TEMPLATE.md`, use it as the PR body skeleton.\n\n### Step 3: Survey the changes\n\nGather the change set that needs to become PR(s):\n\n```bash\ngit status --porcelain\ngit diff --stat $DEFAULT_BRANCH...HEAD        # committed\ngit diff --stat                                # unstaged\ngit diff --stat --cached                       # staged\n```\n\nClassify files into logical groups. Typical axes:\n- **By concern**: docs / feature / bugfix / refactor / test / chore\n- **By subsystem**: unrelated top-level directories usually = separate PRs\n- **By dependency**: if PR B needs PR A merged first, split and note the dependency\n\n### Step 4: Propose a PR plan and confirm\n\n**Use `AskUserQuestion`** to present the plan. Options must include at least:\n\n- **Single PR** — all changes together. Recommended when changes are cohesive.\n- **Split into N PRs** — show the proposed titles and file groupings.\n- **Abort** — something is off, let the user redirect.\n\nShow the plan like:\n\n```\nPR #1 (docs): Update CLAUDE.md to reflect current scripts\n  - CLAUDE.md\nPR #2 (feat): Add gh-contribute skill bootstrap\n  - scripts/new.ts\n  - .prompts/contribute.xml\n```\n\nDo not proceed until the user picks an option.\n\n### Step 5: Fork (idempotent)\n\n```bash\ngh repo view $USER_LOGIN/$REPO_NAME >/dev/null 2>&1 \\\n  || gh repo fork $UPSTREAM --clone=false --remote=false\n```\n\nEnsure a `fork` remote exists in the local clone:\n\n```bash\ngit remote get-url fork 2>/dev/null \\\n  || git remote add fork git@github.com:$USER_LOGIN/$REPO_NAME.git\n```\n\nIf origin already points at the user's fork, skip the `fork` remote and use `origin`.\n\n### Step 6: Create branches and commits per PR\n\nFor each PR in the plan:\n\n1. Start from a clean, up-to-date base:\n   ```bash\n   git fetch origin $DEFAULT_BRANCH\n   git checkout -b $BRANCH_NAME origin/$DEFAULT_BRANCH\n   ```\n2. Apply only the files belonging to this PR (use `git checkout <sha> -- <paths>`\n   or `git stash` + selective `git checkout` from a working branch).\n3. Commit with a conventional message. If upstream uses Conventional Commits,\n   match: `<type>(<scope>): <subject>`. Otherwise mirror the style of the\n   last 10 commits on `$DEFAULT_BRANCH`.\n4. Sign off if `CONTRIBUTING.md` requires DCO: `git commit -s ...`.\n\nBranch naming (when upstream doesn't dictate): `<type>/<short-slug>`, e.g.\n`docs/update-claude-md`, `feat/add-contribute-skill`.\n\n### Step 7: Push to fork\n\n```bash\ngit push -u fork $BRANCH_NAME\n```\n\nIf origin is already the fork, use `origin` instead.\n\n### Step 8: Open the PR\n\n```bash\ngh pr create \\\n  --repo $UPSTREAM \\\n  --base $DEFAULT_BRANCH \\\n  --head $USER_LOGIN:$BRANCH_NAME \\\n  --title \"$TITLE\" \\\n  --body \"$BODY\"\n```\n\nPR body template (adapt to PR template if present):\n\n```markdown\n## Summary\n\n<1-3 bullets explaining what and why>\n\n## Changes\n\n- <bullet per logical change>\n\n## Test plan\n\n- [ ] <how to verify>\n\n## Related\n\n<!-- Link follow-up PRs if split, e.g. \"Depends on #123\" or \"Part 2 of 3\" -->\n```\n\nWhen opening multiple PRs, cross-link them in each body:\n\n```markdown\n## Related\n- PR 1/3: #<url>\n- PR 2/3: (this PR)\n- PR 3/3: #<url>\n```\n\n### Step 9: Report back\n\nOutput a compact summary:\n\n```\nOpened 2 PRs against ZenMux/zenmux-doc:\n  #201 docs: update CLAUDE.md            → https://github.com/.../pull/201\n  #202 feat: add gh-contribute skill      → https://github.com/.../pull/202\n```\n\n## Splitting Heuristics\n\nPrefer **one PR** when:\n- All changes serve a single user-visible outcome\n- Total diff < ~300 lines across ≤ 5 files\n- The changes would be awkward to review in isolation\n\nPrefer **multiple PRs** when:\n- Docs-only changes sit alongside code changes (docs PR lands fast)\n- Refactor + feature — land the refactor first, feature on top\n- Unrelated subsystems touched (e.g. `scripts/` + `docs_source/`)\n- One change is trivially correct and another needs discussion\n\nWhen in doubt, ask the user.\n\n## What NOT to Do\n\n- **Never force-push** to a branch that already has a PR with review comments\n  unless the user explicitly asks\n- **Never edit upstream's default branch** directly — always branch first\n- **Never push to upstream** — always to the user's fork\n- **Never bypass hooks** (`--no-verify`) or skip signing (`--no-gpg-sign`)\n  unless CONTRIBUTING.md says to or the user explicitly says so\n- **Never batch unrelated concerns** into one PR just to \"ship faster\"\n- **Never fabricate** a PR body — if you can't describe the change, ask the user\n\n## Dependencies\n\n```bash\n# gh CLI (https://cli.github.com/)\nbrew install gh      # macOS\ngh auth login        # one-time\n```\n\nNo Python dependencies. This skill is pure `gh` + `git` orchestration.","tags":["contribute","skills","lovstudio","agent-skills","ai-coding-assistant","cjk","claude-code","cursor","gemini-cli","markdown-to-docx","markdown-to-pdf"],"capabilities":["skill","source-lovstudio","skill-gh-contribute","topic-agent-skills","topic-ai-coding-assistant","topic-cjk","topic-claude-code","topic-cursor","topic-gemini-cli","topic-markdown-to-docx","topic-markdown-to-pdf"],"categories":["skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/lovstudio/skills/gh-contribute","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add lovstudio/skills","source_repo":"https://github.com/lovstudio/skills","install_from":"skills.sh"}},"qualityScore":"0.469","qualityRationale":"deterministic score 0.47 from registry signals: · indexed on github topic:agent-skills · 39 github stars · SKILL.md body (6,467 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-21T01:36:45.278Z","embedding":null,"createdAt":"2026-04-18T22:19:00.316Z","updatedAt":"2026-04-21T01:36:45.278Z","lastSeenAt":"2026-04-21T01:36:45.278Z","tsv":"'-3':726 '/)':964 '/.../pull/201':776 '/.../pull/202':786 '/dev/null':329,513,541 '1':212,221,472,515,580,725 '1/3':750 '10':645 '2':233,290,328,482,514,540,604,766 '2/3':752 '201':770 '202':777 '3':345,626 '3/3':756 '300':804 '4':420,650 '5':502,807 '6':567 '7':671 '8':692 '9':758 'abort':459 'access':116 'across':806 'adapt':717 'add':484,544,779 'alongsid':827 'alreadi':119,169,250,552,685,877 'alway':896,903 'anoth':856 'api':285,323 'appli':605 'ask':132,862,888,955 'askuserquest':428 'assum':162 'auth':970 'awkward':813 'axe':385 'b':408,598 'back':760 'base':32,589,702 'base64':330 'bash':321,359,505,533,590,675,696,959 'batch':933 'becom':356 'belong':609 'bodi':342,712,713,715,746,947 'bootstrap':489 'branch':19,81,271,311,367,569,595,599,603,625,649,660,680,704,708,875,894,897 'brew':965 'bugfix':390 'bullet':727 'bypass':910 'cach':377 'carri':315 'chang':37,62,94,144,161,348,351,441,445,732,794,810,825,829,851,954 'checkout':597,615,621 'chore':393 'classifi':379 'claude.md':475,480,773 'clean':7,55,65,584 'cli':961 'cli.github.com':963 'cli.github.com/)':962 'clone':18,520,532 'code':160,828 'code_of_conduct.md':298 'cohes':447 'comment':883 'commit':20,82,306,369,571,627,636,646,658 'compact':763 'concern':97,387,935 'confirm':210,426 'constraint':317 'cont':51 'content':327 'contribut':4,5,54,104,293,487,782 'contributing.md':296,654,923 'convent':630,635 'correct':854 'creat':568,699 'cross':741 'cross-link':740 'current':241,478 'd':331 'date':588 'dco':656 'dco/cla':309 'default':270,366,594,602,648,703,893 'defaultbranchref':278 'defaultbranchref.name':280 'depend':405,418,958,977 'describ':952 'desir':172 'determin':217 'dictat':666 'diff':364,371,375,803 'direct':895 'directori':242,400 'discuss':858 'doc':146,388,473,771,823,830,848 'docs-on':822 'docs/update-claude-md':668 'doesn':664 'doubt':861 'e.g':145,268,667,846 'edit':122,890 'els':13 'ensur':524 'execut':203 'exist':528 'explain':728 'explicit':887,929 'fabric':944 'fact':266 'fals':521,523 'fast':833 'faster':942 'feat':483,778 'feat/add-contribute-skill':669 'featur':147,389,835,840 'fetch':295,592 'file':380,457,608,808 'find':255 'first':413,839,898 'forc':871 'force-push':870 'fork':17,48,80,134,254,503,518,526,539,545,558,561,674,679,687,908 'format':308 'full':79 'gather':349 'get':537 'get-url':536 'gh':3,53,192,259,273,284,322,486,506,516,697,781,960,967,969,982 'gh-contribut':2,52,485,780 'gh-tidi':191 'git':236,360,363,370,374,534,542,591,596,614,617,620,657,676,983 'git@github.com':546 'github':15,199 'github.com':775,785 'github.com/.../pull/201':774 'github.com/.../pull/202':784 'github/pull_request_template.md':336 'gitlab/gitea':198 'goal':156 'gpg':920 'group':383,458 'handl':77 'head':181,368,705 'heurist':788 'hook':911 'idempot':504 'identifi':213 'includ':435 'instal':966 'instead':690 'isol':817 'json':262,277 'land':832,836 'last':644 'least':437 'let':463 'level':399 'like':470 'line':805 'link':742 'local':61,121,531 'logic':382 'login':282,288,510,548,707,971 'lovstudio':1 'maco':968 'mandatori':202 'markdown':723,747 'match':637 'merg':412 'messag':307,631 'mirror':196,639 'mix':143 'modif':173 'multipl':30,90,738,819 'must':434 'n':450 'name':312,512,600,661,681,709 'need':124,354,409,857 'never':869,889,899,909,932,943 'no-gpg-sign':918 'no-verifi':912 'non':155 'non-goal':154 'note':416 'one':28,790,850,937,973 'one-tim':972 'open':22,108,693,737,765 'open-sourc':107 'option':433,500 'orchestr':984 'order':206 'origin':246,248,551,565,593,601,683,689 'otherwis':234,638 'outcom':801 'output':761 'owner/repo':220,229 'parent':263 'past':225 'per':572 'pick':244,498 'pipelin':85 'plan':424,432,469,579,734 'point':553 'porcelain':362 'pr':23,46,50,84,129,140,313,341,357,407,410,423,439,471,481,573,576,612,695,698,714,719,749,751,754,755,791,831,880,938,946 'prefer':789,818 'present':302,430,722 'prior':167 'proceed':494 'profession':8,66 'project':110,186 'prompts/contribute.xml':491 'proper':153 'propos':421,454 'prs':31,56,91,189,403,451,739,767,820 'pull':9,67 'pure':981 'push':21,83,672,677,872,900 'python':976 'q':279,287,326 'read':291 'recommend':443 'record':264 'redirect':466 'refactor':148,391,834,838 'reflect':477 'relat':735,748 'remot':237,522,527,535,543,562 'repo':44,59,72,136,216,260,274,324,334,507,511,517,700 'repo_name.git':549 'report':759 'repositori':16 'request':10,68 'requir':310,655 'review':184,815,882 'rule':294 'run':235 'say':42,924,930 'scope':35 'script':479,847 'scripts/new.ts':490 'see':190 'select':619 'send':138 'separ':402 'serv':795 'set':352 'ship':126,941 'show':452,467 'sign':651,917,921 'singl':438,797 'sit':826 'skeleton':343 'skill':488,783,979 'skill-gh-contribute' 'skim':304 'skip':209,559,916 'smart':25 'someon':12 'someth':460 'sourc':109,849 'source-lovstudio' 'span':95 'split':26,87,152,414,448,787 'stage':378 'start':581 'stash':618 'stat':365,372,376 'status':361 'step':168,204,211,289,320,344,419,501,566,670,691,757 'string':230 'style':641 'subsequ':319 'subsystem':395,844 'summari':724,764 'survey':346 'target':215 'templat':314,716,720 'test':392,733 'three':265 'tidi':193 'time':974 'titl':455,710,711 'togeth':442 'top':398,842 'top-level':397 'topic-agent-skills' 'topic-ai-coding-assistant' 'topic-cjk' 'topic-claude-code' 'topic-cursor' 'topic-gemini-cli' 'topic-markdown-to-docx' 'topic-markdown-to-pdf' 'total':802 'touch':845 'tree':177 'trigger':38 'trivial':853 'turn':60 'typic':384 'u':678 'unless':884,922 'unrel':96,396,843,934 'unstag':373 'up-to-d':585 'updat':474,772 'upstream':58,71,130,219,257,267,276,300,519,633,663,701,891,902 'upstream/contents/contributing.md':325 'url':227,538 'use':100,231,337,427,564,613,634,688 'user':41,101,118,131,141,164,224,252,281,286,465,497,509,547,556,706,799,864,886,906,928,957 'user-vis':798 'usual':401 'v':238 'verifi':914 'via':258 'view':261,275,508 'visibl':800 'want':102,150 'work':88,176,624 'workflow':201 'would':811 'write':115,159 'zenmux/zenmux-doc':269,769 '提':45 '然后改再':49 '给这个':43 '贡献代码':47","prices":[{"id":"88362e72-84a9-4267-b010-7df27c0244ae","listingId":"d5a422eb-597e-46a6-85d7-9ec75caa885f","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"lovstudio","category":"skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:19:00.316Z"}],"sources":[{"listingId":"d5a422eb-597e-46a6-85d7-9ec75caa885f","source":"github","sourceId":"lovstudio/skills/gh-contribute","sourceUrl":"https://github.com/lovstudio/skills/tree/main/skills/gh-contribute","isPrimary":false,"firstSeenAt":"2026-04-18T22:19:00.316Z","lastSeenAt":"2026-04-21T01:36:45.278Z"}],"details":{"listingId":"d5a422eb-597e-46a6-85d7-9ec75caa885f","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"lovstudio","slug":"gh-contribute","github":{"repo":"lovstudio/skills","stars":39,"topics":["agent-skills","ai-coding-assistant","cjk","claude-code","cursor","gemini-cli","markdown-to-docx","markdown-to-pdf"],"license":"mit","html_url":"https://github.com/lovstudio/skills","pushed_at":"2026-04-20T21:40:57Z","description":"Agent skills for AI coding assistants — Markdown to PDF/DOCX with 14 themes, CJK support","skill_md_sha":"e54459fbd269bc6de2110a410f25cbcfb7535a9e","skill_md_path":"skills/gh-contribute/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/lovstudio/skills/tree/main/skills/gh-contribute"},"layout":"multi","source":"github","category":"skills","frontmatter":{"name":"lovstudio:gh-contribute","license":"MIT","description":"Contribute a clean, professional pull request to someone else's GitHub repository: fork → clone → branch → commit → push → open PR, with smart splitting into one or multiple PRs based on the scope of changes. Trigger when the user says \"给这个 repo 提 PR\"、\"贡献代码\"、\"fork 然后改再 PR\"、 \"contribute to this repo\", \"open a PR to upstream\", \"submit a PR to <owner>/<repo>\".","compatibility":"Requires `gh` CLI (authenticated via `gh auth login`) and `git`. Targets GitHub repositories only. Cross-platform: macOS, Windows, Linux."},"skills_sh_url":"https://skills.sh/lovstudio/skills/gh-contribute"},"updatedAt":"2026-04-21T01:36:45.278Z"}}