UI copy polish
You are the orchestrator. Do not rewrite copy yourself. Discover shards, launch the engine once, report.
SKILL_DIR is the directory that contains this SKILL.md.
| File | Path |
|---|---|
| Copy bar | SKILL_DIR/references/copy-bar.md |
| Roles | SKILL_DIR/references/roles.md |
| Discover | SKILL_DIR/scripts/discover-copy-shards.py |
| Catalog gaps | SKILL_DIR/scripts/catalog-gaps.py |
| Engine (Grok) | SKILL_DIR/workflows/ui-copy-polish.rhai |
| Engine (Claude Code) | SKILL_DIR/workflows/ui-copy-polish.js |
Read the copy bar once so you can brief the user. Do not restyle strings in the parent session.
Arguments
Parse $ARGUMENTS:
--no-commit→commit: false--no-push→push: false--locales a,b→ passed to discover (overrides catalog detection and setsstrict_locales, so every catalog must carry every listed locale)--max-shards N→ passed to discover- Every other token is passed through to
discover-copy-shards.py(dest classifiers and/or paths). Dest aliases live in that script's docstring:codewebapidoccatalogall. - Empty → discover from the current working directory, dest
code.
Defaults: commit: true, push: true.
Step 1 — Discover
python3 "<SKILL_DIR>/scripts/discover-copy-shards.py" --cwd "<PWD>" <roots-and-dests...>
The script prints JSON: workspace, dests, roots, shards (each with paths and exclude), catalogs, git_roots, locales, source_locale, strict_locales, checks.
It works on any layout — a single Xcode app, an npm package, a Cargo workspace, a Go module, a Django site, an Android or Flutter app, a monorepo of several — because it classifies by suffix and well-known directory names, reads locales out of whatever catalogs exist (.xcstrings, .lproj, values-*/strings.xml, locales/*.json|yml, .arb, .po, .resx, .properties, .xliff, .ftl), and picks a cheap check per git root (make check, swift build, the typecheck/lint npm script, cargo check, go build, …).
If shards is empty, stop and say nothing user-facing was found. Do not launch agents.
Tell the user in one line: how many shards, which locales were detected (locales — if the project ships none, only the source locale is edited), and which checks will run. If the detected locales look wrong, they can re-run with --locales.
Stay in the git repos the script named.
Step 2 — Launch the engine once
Build args = the discover JSON plus:
{
"copy_bar_path": "<SKILL_DIR>/references/copy-bar.md",
"roles_path": "<SKILL_DIR>/references/roles.md",
"gaps_script": "<SKILL_DIR>/scripts/catalog-gaps.py",
"commit": true,
"push": true,
"commit_trailers": "<any trailer lines your host requires, else omit>"
}
Override commit / push from the flags. Then pick the engine for the host you are running in:
Grok — copy the rhai script into the trusted workflow home and launch by name (agent_budget: 256):
mkdir -p "$HOME/.grok/workflows"
cp "<SKILL_DIR>/workflows/ui-copy-polish.rhai" "$HOME/.grok/workflows/ui-copy-polish.rhai"
Launch with name: "ui-copy-polish" and the args above. Do not pass a Desktop script_path — that path is not trusted.
Claude Code — call the Workflow tool once with scriptPath: "<SKILL_DIR>/workflows/ui-copy-polish.js" and the args above. The user invoking this skill is the opt-in the tool requires. Set read_only_agent_type in args if your session's read-only agent is not called Explore.
Any other host — use the fallback below.
After launching, stop spawning your own finders/fixers. Do not poll. Tell the user the workflow display name and that Ship commits with explicit pathspec, then pushes the current branch. Never force-push. Never git add -A.
The engine is:
find → verify → fix → review → fix (loop, max 3) → localize (plan → translate → merge) → commit → push
Each shard runs its own chain; fixers never edit outside their shard (or inside its exclude list). Translators never edit catalogs. Only mergers write catalogs.
Fallback (only if no workflow engine is available or it errors)
Reproduce the same phases with subagents. Cold-start every child: it must read the copy bar and the matching section of roles.md before judging a string, and every prompt carries SOURCE, LOCALES, the shard's paths, and its exclude list.
- Find — one read-only subagent per shard. Prompt = Finder section + shard dest + shard paths/exclude. Empty findings only after grep.
- Verify — one read-only subagent per shard that returned findings. Keep only items with quoted evidence. Drop out-of-shard paths.
- Fix — one read-write subagent per shard with confirmed items. No worktree isolation. Confirmed replacements only. Non-catalog shards do not edit catalogs.
- Review → fix loop — one read-only reviewer per edited shard. If
remainingis non-empty, fix those shards again. Stop after 3 rounds or when a round returns nothing new. - Localize — do not fill catalogs in one agent.
- Run
catalog-gaps.py --locales <locales> --source <source> [--strict] --emit-jobs --chunk-size 100on every catalog. That writes one job file per locale chunk. - One read-only translator per job (one locale, ≤100 keys). Each returns JSON
{ locale, items: [{ catalog, key, text }] }. They do not edit catalogs. - One read-write merger per catalog. Apply every translator item for that file (all locales merge into one
.xcstrings), delete the empty""key, addnew_keys, re-run the gaps script.
- Run
- Ship — one agent with shell access. Intersect this run's files with
git status --porcelain. Run thecheckscommands for each git root that changed (plus the gaps script).git commit -m "…" -- <paths>. PushHEADifpushis true.
Wait for each panel to finish before starting the next phase. Do not repair unrelated build breakage. Do not touch dirty files this run did not change.
Hard rules
- User-visible copy only. The copy bar is the only style guide.
- Every locale a catalog ships, complete. Never add a locale a catalog does not ship unless the user passed
--locales. - Keep interpolation tokens.
- Pathspec commits. Leave other sessions' dirty files alone.
- One repo at a time at git time; the engine already splits by
git_roots.