One-click contribution flow for Open Design (nexu-io/open-design) โ even for non-coders. Pick one of four cards (ship a Skill or Design System you made with OD; translate docs; fix a typo / write a blog; report a bug), the agent validates and opens a PR (or issue) for you.
Installs just this skill. Get the whole plugin for auto-invocation.
โก How it fires
How this skill gets triggered: by you, by Claude, or both.
Fires itselfClaude auto-loads it when your prompt matches the work.
You can call itInvoke it directly when you want it.
Slash command/od-contribute
๐๏ธ Context preview
The summary Claude sees to decide when to auto-load this skill.
One-click contribution flow for Open Design (nexu-io/open-design) โ even for non-coders. Pick one of four cards (ship a Skill or Design System you made with OD; translate docs; fix a typo / write a blog; report a bug), the agent validates and opens a PR (or issue) for you.
๐ Stats
Stars80,924
Forks9,350
LanguageTypeScript
LicenseApache-2.0
๐ฆ Ships with open-design
</> SKILL.md
od-contribute.SKILL.md
---name: od-contribute
description: One-click contribution flow for Open Design (nexu-io/open-design) โ even for non-coders. Pick one of four cards (ship a Skill or Design System you made with OD; translate docs; fix a typo / write a blog; report a bug), the agent validates and opens a PR (or issue) for you. Trigger words contribute to open design, ship my OD skill, ship my OD design system, translate OD docs, report an OD bug, od-contribute.
allowed-tools:
- Bash
- Read
- Write
- Edit
- AskUserQuestion
- TaskCreate
- TaskUpdate
- WebFetch
---# od-contribute โ first-contribution flow for Open Design
Locked to `nexu-io/open-design`. Branches by **contribution type**, not by issue. Replaces the dev-loop with type-specific no-code validators. Designed so a product user with zero coding background can ship a real PR.
## Language
Mirror the user's language in every user-facing message โ `AskUserQuestion` labels and descriptions, status updates, error explanations. Detect from their first message; when uncertain, default to English.
**Generated artifacts (PR titles, commit messages, PR/issue body files, branch names) MUST be English** regardless of the user's chat language. GitHub conventions, maintainer review, and search all assume English. The templates under `templates/` are already English โ keep them that way when rendering.
Scripts live under `scripts/`. Source the shared helpers from any script:
`SKILL_DIR` below = the directory that contains this `SKILL.md`.
---
## Step 1 โ Prereq check (always first)
```bash
bash "$SKILL_DIR/scripts/check-prereqs.sh"
```
- Exit 0: capture `GH_USER=<login>` from stdout. Default `TARGET_FORK="${GH_USER}/open-design"`.
- Exit 2: surface the printed install / auth hint **verbatim** and stop. Do not attempt token workarounds.
If `gh repo view "$TARGET_FORK"` fails, ask the user (one `AskUserQuestion`) whether to fork now via `gh repo fork nexu-io/open-design --clone=false`. Default to yes.
## Step 2 โ Pick contribution type
Single `AskUserQuestion` (header: "Contribution", multiSelect: false), four options. Translate option labels/descriptions into the user's chat language; the branch routing is unchanged.
1. **๐จ Ship something I made with OD** โ _a Skill, Design System, HyperFrame, or template I want to contribute upstream_ โ branch `3a`
2. **๐ Translate OD docs** โ _README / QUICKSTART / CONTRIBUTING into a new language_ โ branch `3b`
3. **๐ Fix docs / write a blog / fix a typo** โ _typo fix, dead link, use-case writeup_ โ branch `3c`
4. **๐ Report a bug** โ _something broke; I'll help turn it into a high-quality issue_ โ branch `3d` (issue path, no PR)
Each branch below is self-contained. Steps 7โ8 (preview + push) are shared across branches `3a`/`3b`/`3c`. Branch `3d` skips them entirely.
**3a.1** Ask user: "What's the local path to the artifact you want to ship?" (single free-text, translated into the user's chat language). Common: a folder path (Skill) or a single `DESIGN.md` file (Design System).
**3a.2** Sniff type:
```bash
# Skill: folder containing SKILL.md with frontmatter.
- `status: "missing"` first (missing language is highest leverage)
- then `status: "stale"` ordered by `english_commits_since_translation` desc
- README family before QUICKSTART before CONTRIBUTING
**3b.3** Take the top 3โ4 gaps and present via `AskUserQuestion` (header: "Translation target"). Each option label like: `README โ ํ๊ตญ์ด (Korean)` / `QUICKSTART (zh-CN) refresh โ 12 commits behind`. Translate the header text into the user's chat language but keep the option labels descriptive (the language names belong in their native script).
**3b.4** Once user picks, **rename branch** to be specific:
(or pre-set the slug in step 3b.1 if the user confirmed earlier.)
**3b.5** Translate. Read the English source. Translate **structure-preserving**:
- Code blocks: leave untranslated
- Brand / product names: leave untranslated
- Filenames in inline code: leave untranslated
- Image / link targets: leave untranslated; if a localized version of a linked doc exists, swap the link to the localized file
- Headings: translate, keep the heading depth identical
- Tables: translate cell text only, keep alignment / pipes
Write the result to `$WORKDIR/<TRANSLATED_PATH>` (e.g. `QUICKSTART.es.md`). Show user a unified diff vs. the English source for visual sanity-check (line-count delta within ยฑ15% is a healthy signal).
**3b.6** Validate the translated file against the English source. The `--reference` flag tells the validator to ignore relative refs that were already broken in the source โ OD docs frequently link to website route slugs (e.g. `skills/blog-post/`) that aren't files on disk; we don't want a structure-preserving translation to fail because of pre-existing dead refs.
```bash
bash "$SKILL_DIR/scripts/validate-markdown.sh" \
"$WORKDIR/<TRANSLATED_PATH>" \
--reference "$WORKDIR/<ENGLISH_PATH>"
```
If FAIL โ surface verbatim, fix, retry.
**3b.7** Render `templates/PR-BODY-i18n.md` with `{{DOC_NAME}}`, `{{LANG_DISPLAY_NAME}}`, `{{LANG_CODE}}`, `{{TRANSLATED_PATH}}`, `{{ENGLISH_PATH}}`, `{{STATUS}}`, `{{TRANSLATION_NOTES}}` (one paragraph from the agent: anything tricky, untranslated terms it kept, etc.), `{{DISCORD_INVITE}}`.
Group by `kind` (typo / deadlink / todo). Show the user up to 6 candidates via `AskUserQuestion`. Once picked, apply the fix in code (typo: replace word; deadlink: ask user for the new URL; todo: that's a proper task, ask user to write the missing prose).
**3c.4 (Specific-fix branch)** Read the file, apply user's described change. Confirm via diff.
**3c.5 (Blog branch)** First check whether OD has a blog directory:
```bash
ls "$WORKDIR/docs" 2>/dev/null
```
If a `docs/blog/` or similar exists, place the new post there. If not, ask the user where it should live, defaulting to `docs/<slug>.md`. Generate an outline โ user fills in user-specific bits (their use case, screenshots, the prompt they used, the rendered output) โ agent stitches into a final Markdown.
**3c.6** Validate every changed/added file. For files that already exist in the repo (typo fix, dead-link fix, doc edit), pass `--reference` pointing at HEAD's version so we only fail on relative refs the user *introduced*, not on pre-existing route slugs:
```bash
# For modifications to existing files:
git -C "$WORKDIR" show "HEAD:<path>" > "/tmp/od-contrib-orig-<basename>" 2>/dev/null
bash "$SKILL_DIR/scripts/validate-markdown.sh" \
"$WORKDIR/<changed-path>" \
--reference "/tmp/od-contrib-orig-<basename>"
# For brand-new files (e.g. a blog post the user is creating from scratch),
# omit --reference. The validator will skip the relative-ref check entirely
# (since it can't tell route slugs from real paths in isolation).
```
**3c.7** Render `templates/PR-BODY-docs.md` with `{{ONE_LINE_SUMMARY}}`, `{{DETAILS}}`, `{{FILES_LIST}}`, `{{DISCORD_INVITE}}`.
โ **Step 7**.
---
### Step 3d โ Bug report (issue path, no PR)
**3d.1** Read OD's actual schema at runtime to make sure we mirror it:
```bash
gh api "repos/${TARGET_REPO}/contents/.github/ISSUE_TEMPLATE/bug-report.yml" --jq .content | base64 -d > /tmp/od-bug-report.yml
```
If the schema has drifted from the template (`templates/ISSUE-BODY-bug.md`), regenerate the body to match.
**3d.2** Ask the user via `AskUserQuestion`, one structured prompt per critical field. Use **plain language**, not the YAML field names:
| Bug-report field | Prompt to user |
|---|---|
| `description` | "What went wrong? One sentence is fine." |
| `steps` | "How can I reproduce it? Walk me through step by step." |
| `expected` | "What did you expect to happen?" |
| `version` | "Which OD version are you running? (About menu, or `od --version`)" |
| `platform` | dropdown: macOS (Apple Silicon) / macOS (Intel) / Windows / Linux / Other |
| `logs` | "Any error logs you can paste? Skip if you don't have them." |
| `screenshots` | "Path to a screenshot? Skip if you don't have one." |
Translate every prompt above into the user's chat language at runtime.
**3d.3** Auto-collect what we can (these don't need to ask the user):
- OS family from `uname`
- Node version from `node -v` if relevant
**3d.4** Dedupe: extract 3โ5 keywords from the description, run:
If matches exist, present them to the user via `AskUserQuestion` (translate to user's language): "These existing issues look related. Do you want to: (a) comment on an existing one, (b) open a new issue anyway, (c) cancel?"
**3d.5** If proceeding with new issue, render `templates/ISSUE-BODY-bug.md` and submit:
Open PR: nexu-io/open-design:main โ <fork>:<branch>
```
Then `git -C "$WORKDIR" diff --stat` and a `head -40` of the rendered PR body for visual sanity.
Required `AskUserQuestion` confirmation (translate to user's language): **"Push this PR?"** with three options:
- **Ship it** โ proceed to Step 8
- **Let me revise** โ return to the relevant Step 3 sub-step
- **Cancel** โ leave the workspace on disk, tell the user the path so they can return later, exit
Never push without an explicit "Ship it".
## Step 8 โ Push & open PR
```bash
bash "$SKILL_DIR/scripts/create-pr.sh" \
--workdir "$WORKDIR" \
--type "<skill|design-system|i18n|docs>" \
--title "<PR title from references/newcomer-tone.md>" \
--body-file "$WORKDIR/.od-contrib/PR-BODY.md"
```
Print the PR URL on its own line. Done.
---
## Safety rails (mandatory)
- Never push to `main` / `master` / `develop`. The push scripts refuse.
- Never `--force` push. Just don't.
- All workspace activity stays under `$OD_WORK_ROOT` (default `$HOME/od-contrib-work`). `od::assert_in_workroot` enforces this.
- Bug-report path **always** runs the dedupe search before `gh issue create`.
- Honor user memory: skip GitHub user `xxiaoxiong` from any contributor lookup ([[feedback_no_outreach_xxiaoxiong]]).
## When NOT to use this skill
- The user wants to fix a daemon / web bug or add a feature with code changes โ use `auto-github-contributor` instead (it has the TDD loop). This skill deliberately doesn't run lint/typecheck/tests because content paths don't need them.
- The user wants to *generate* a Skill / Design System from scratch โ that's Open Design itself. Run OD first, get an artifact, then come back here to ship it.