repo-polish
把一个仓库对外的那一面建起来或修好——README、首屏横幅、LICENSE、SECURITY.md、CONTRIBUTING.md、托管平台上的一句话简介,以及 GitHub 或 GitLab 的 topics,全部依据仓库自己的文件写。默认七项全做,也可以只点其中几项。不适用于 API 参考文档、更新日志、发版说明、营销落地页,或仓库本身的源码。
- 分组
- 文档
- 版本
- 0.10.0
- 许可证
- MIT
- 参数
- [--readme] [--banner] [--license] [--security] [--contributing] [--description] [--topics] [--audit] [--dry-run]
安装
/plugin install docs@misoto22然后这样调用:
/docs:repo-polish这个技能的前提是:一个仓库该怎么对外介绍自己,答案在它自己的文件里,而不在它的名字里。所以每一项都先读证据再动笔——构建配置和锁文件给出技术栈与版本,任务运行器给出上手命令,CI 配置给出贡献者必须跑通的检查,提交历史给出这个项目实际在用的提交规范。查不到的事实留方括号占位符,不猜。它把七件事当成一件事来做,因为它们回答的是同一个问题:这是什么、我能不能用、接下来去哪。所以“这是什么”只定一次,README 的居中那行、平台上的仓库简介、包清单里的 description,用的是同一句话,而不是三种说法。两条硬规矩:许可证从不替你选——它只把已有的声明理顺,发现 LICENSE 和 package.json 各说各话就停下来报给你;写到托管平台的仓库简介和 topics 会离开本地、diff 里看不见,所以先把要写的值原样打印出来,等你点头再发。
什么时候会触发
CI 实际用来评测这个技能的 prompt——所以它们不会和技能的真实行为脱节。
会触发
- 帮我把这个仓库装修一下
- This repo's README is out of date. Can you fix it?
- Add a LICENSE and a security policy to this project.
- Set the GitHub description and topics for this repository.
- Is this repository presentable enough to share?
不会触发
- Write the API reference for these endpoints.
- Update the CHANGELOG for this release.
- Write the marketing copy for the product page.
- Design a logo and a light and dark banner image for this project.
- Tidy up this repo — delete the branches whose PRs already merged.
A repository's public face is seven artefacts, and they are one job because they all answer the same question for a stranger: what is this, may I use it, and where do I go next. Written separately they contradict each other — a README that says MIT beside a LICENSE that says Apache-2.0, a forge description two rewrites behind the first line of the README.
Every pass runs by default. With any of --readme, --banner, --license, --security, --contributing, --description, --topics, only those. --audit reports without writing. --dry-run stops after the plan table.
| Pass | Artefact | Reference |
|---|---|---|
--readme | README.md | readme.md, skeleton.md |
--banner | the hero image the README opens with | banner.md |
--license | LICENSE, and the SPDX id agreeing everywhere | community-files.md |
--security | SECURITY.md | community-files.md |
--contributing | CONTRIBUTING.md | community-files.md |
--description | the forge's one-line About text | forge-metadata.md |
--topics | GitHub topics · GitLab project topics | forge-metadata.md |
One sentence, said once
Before any pass writes, settle the sentence: what this is and what it runs on, in one line under about 120 characters. It is the same text in the README's centred block, in the forge's About field, and in the description of package.json, pyproject.toml, Cargo.toml, or a plugin manifest. Not paraphrases of each other — the same sentence.
That agreement is the whole reason these passes travel together. A reader meets the repository through whichever one their search returned, and three descriptions mean two of them are stale.
The same holds for the licence: one SPDX identifier, in LICENSE and in every manifest that declares one. Where they already disagree, say so and stop — see the licence pass.
0. Read the repository before writing a line
Never describe a project from its name. Every claim in the output must come from a file you read.
| To write | Read |
|---|---|
| The sentence, tech stack, versions | package.json, pyproject.toml, Cargo.toml, lockfile |
| Getting started | the task runner (justfile, Makefile, package.json scripts), .env.example |
| Project structure | the actual tree, two levels deep |
| Features | routes, entry points, CI workflow names — not the previous README |
| Deployment | .github/workflows/, compose.yaml, Dockerfile |
| Licence | LICENSE, manifest license fields, file headers |
| Contribution conventions | git log --format=%s -50, the CI workflow's own steps |
| Topics and About | everything above, plus what the forge already has set |
Where a fact is unavailable, leave a bracketed placeholder — [Node.js 24+], [Module A] — for the author to complete. An invented version number is worse than a blank.
A placeholder belongs in prose, never inside an attribute that renders. src="[hero image URL]" does not read as a note to the author; it renders as a broken-image icon, as the first thing on the page. When an asset does not exist, drop the element.
Read what is already there before adding. Most stale repositories are over-decorated, not under-decorated — the pass that deletes a badge wall is doing as much work as the pass that writes a file.
Print the plan, then work
Nothing is written until it is printed. One markdown table, never a fixed-width block — findings are written in the reader's language and any column width computed here is wrong in their terminal.
Polish
<repo>— 7 passes
Pass Target Finding Action readme README.md412 lines, no runnable Getting Started rewrite banner assets/hero-*.svgabsent draft · skip: reason license LICENSEabsent; package.jsonsaysMITadd MIT security SECURITY.mdabsent add contributing CONTRIBUTING.mdnames npm run check, which is gonefix description forge About empty set topics forge topics 0 of 20 set 8
Stop here on --dry-run.
A pass with no evidence is skipped, not guessed. Say which fact was missing. A skipped pass reported is worth more than a file full of placeholders.
The two forge passes leave the repository. --description and --topics write to a live public page, and no local diff records them. Print the exact values, and get a yes before sending them. The local passes are ordinary file edits and need no confirmation beyond the plan table.
1. README
The full house style is in readme.md: the canonical section order, what GitHub renders natively, the section-by-section rules, and the render check to run before calling it done. skeleton.md is the copy-pasteable version.
In short: three questions — what is this, can I run it, where do I go next — in that order, ### headings, --- between sections, two screens before the first <details>, and every command copied from the task runner rather than paraphrased.
2. Banner
The hero image is the only real design surface GitHub gives you, and the only one worth spending on. banner.md covers what it has to survive: two themes, a phone's width, and a renderer that honours less SVG than you expect.
Two rules override everything else there. Commit the asset; a hotlinked banner is someone else's uptime. Drop the element when there is no asset; a broken-image icon at the top of the page is worse than a page with no image, and worse than any placeholder you were tempted to leave in src.
Where the artwork itself has to be made rather than laid out, that is a brand job and a different skill — this pass sizes it, wires up the <picture> block, and checks it renders.
3. Licence
Never choose a licence. Which one a project carries is the owner's decision, with consequences this skill cannot weigh. What this pass does is make the existing decision consistent and legible:
- Collect every declaration —
LICENSE,LICENSE.md, manifestlicensefields, SPDX headers, what the README's footer claims. - All agreeing, file present → nothing to do. Confirm the copyright line names someone and a year that is not in the future.
- All agreeing, file missing → write the full canonical text of that SPDX identifier, with the copyright holder and year filled from the manifest and
git log. - Disagreeing → stop and report both. Do not pick the more permissive one, the more common one, or the one in the newer file. Two declarations is a question for the owner, not a formatting defect.
- Nothing declares one at all → ask. State plainly that no licence means no permission to use the code, and offer the shortlist in community-files.md with one line each on what it costs. Do not write a file until answered.
The README carries one line at the bottom, or nothing. A licence section that restates LICENSE is one more copy to go stale.
4. Security policy
SECURITY.md exists to give someone holding a vulnerability a channel that is not a public issue. Everything else in it is optional.
- Name a private channel that exists. On GitHub, private vulnerability reporting is the default answer, and the file should say so and link to the repository's own advisory page. On GitLab, a confidential issue. An email address goes in only when the owner supplies one — never invent a contact.
- Supported versions, only where they are real. A table listing 2.x supported and 1.x not is useful. A single-branch project has no such table, and inventing one promises maintenance nobody agreed to.
- Response expectations, only where they are honest. "We aim to acknowledge within 90 days" from a solo maintainer is a promise that will be broken in public. Silence is better than an SLA nobody owns.
- Say what is out of scope where the repository has an obvious non-issue — a demo credential in a fixture, a deliberately vulnerable example.
Template in community-files.md.
5. Contributing
Only write this file where the repository actually takes outside contributions. On one that does not, it is a form nobody will fill in, and README plus a line in the About field is the honest configuration.
Where it is warranted:
- Link to the README's Getting Started; do not restate it. Two install paths drift within a release.
- Every check a pull request must pass, copied from CI. Read
.github/workflows/. If the workflow runsuvx ruff check ., the file saysuvx ruff check .— not "run the linter". - The conventions the history actually uses.
git log --format=%s -50tells you whether this project writes Conventional Commits, sentence-case subjects, or issue-number prefixes. Match what is there. Do not import a convention the repository has never used. - Where to ask — issues, discussions, or a link. One line.
CODE_OF_CONDUCT.md and the issue and pull-request templates under .github/ belong to the same decision. Where the repository takes contributions and lacks them, offer them in the same pass and write them only on a yes; where it does not, leave all of it alone.
6. Forge description
The one-line About text, on the repository's own page and in every search result and list that names it. Use the sentence settled above, unchanged.
- GitHub's hard limit is 350 characters; the useful limit is far shorter, because a repository list truncates it. Under 120.
- Do not open with the repository's name. It is rendered directly above.
- No marketing adjectives, no trailing period on a fragment, no emoji as the first character.
- A link belongs in the website field beside it, not inside the sentence.
Commands, and the GitLab equivalents, are in forge-metadata.md.
7. Topics
Topics are how a stranger who does not know the repository exists finds it. That is the only test a candidate has to pass.
- Terms someone would search, not terms that describe the codebase to its author.
reactandpostgresql, notwell-architectedorpersonal-project. - Ceiling 20 on GitHub; eight to twelve is usually the honest count. A repository claiming twenty topics is claiming twenty audiences.
- Lowercase, hyphenated, ≤50 characters each, starting with a letter or digit — GitHub normalises anything else, so write them normalised and know what you sent.
- Do not repeat the repository's own name; it already matches on name.
- Drop what is no longer true. Read the existing set first; a
python2topic on a repository that dropped it is worse than no topic.
Where the repository is a library or a plugin published to a directory, one topic is usually that directory's own convention. Read what comparable repositories in it use rather than inventing one.
Voice
Every artefact this skill writes shares one voice. It is the same rule seven times: describe, do not sell.
No marketing adjectives. Blazing, seamless, powerful, robust, cutting-edge, beautiful, delightful, effortless. Strip them without replacement — the sentence is almost always better shorter.
| Before | After |
|---|---|
| A blazing-fast, modern web framework with a delightful developer experience | Next.js 16 · Turbopack |
| Powerful and flexible configuration options | Configuration lives in config.toml |
No filler openers. "Welcome to", "This project is a", "In today's world". Start with the noun.
State boundaries as facts. "This site owns no database credential, schema, migration, or local Postgres lifecycle" closes a question instead of opening one.
Point at runbooks, do not inline them. A file that contains a procedure goes stale the first time the procedure changes.
Separator is ·, not | or ,, when joining peer items on one line. Em dash for explanation after a bold term, not a colon.
Every command must run as written. Copy it from the task runner or the workflow; do not paraphrase it.
The repository's language, not the conversation's. Report back to the user in whatever language they are writing in, and write the files in the language the repository's existing prose, code comments, and commit history already use. Ask only when there is no prose to read. A README rewritten into the language of whoever happened to request it is a README the next contributor cannot maintain.
Topics and the SPDX identifier are the two exceptions: both are machine-matched vocabularies and stay in their own form regardless of the repository's language.
Audit mode
When asked whether a repository is presentable rather than to fix it, run the plan table and stop. Report per pass, worst first, with the line and the fix. Do not write anything.
Within the README pass, answer these in order and stop at the first that fails:
- Does the first screen render — every image loading, nothing centred wrapped?
- Does the first screen say what this is and what it runs on?
- Can a newcomer get it running from the Getting Started block alone?
- Does every command still exist in the task runner?
- Does every version match the lockfile?
- Is anything described that no longer ships?
Across the other passes, the failures worth reporting are: a licence that two files disagree about, a SECURITY.md naming a channel that does not exist, a CONTRIBUTING.md whose commands are gone, an empty or stale About field, and topics that describe something the repository no longer does.
When a request names several repositories
Treat every explicitly named repository as its own scope. Record its exact path or URL, which passes apply, available evidence, and verification state before editing. If a name cannot be resolved to one repository, ask; never widen the scope by searching an unspecified parent directory.
Inspect, write, and render-check independent repositories concurrently when the host supports concurrent work. Keep their commands, versions, licences, deployment facts, assets, and reader language separate unless the user supplies evidence that a fact is shared. An inaccessible or blocked repository does not delay safe work on another one.
Give one combined handoff with a clearly labelled result for each repository: changed files, forge fields written, evidence and rendering checks, then any remaining blocker. A single successful repository never stands in for the rest.
Worked examples
See examples.md for a full seven-pass polish of a neglected repository, a rewrite of a bloated README, a from-scratch build for a CLI tool with no hero image, and an audit report.