From harness-claude
Audits microcopy, error messages, and UI strings for voice/tone consistency, clarity, and actionability. Produces structured reports with rewrites and voice guides. Use for PR reviews of user-facing text or establishing product voice.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Audit microcopy, error messages, and UI strings for voice/tone consistency, clarity, and actionability. Produces a structured report with specific rewrites and a project voice guide when none exists.
Extracts writing system specs from codebases using multi-signal analysis: NNg tone dimensions, UI copy classification, i18n maturity, terminology consistency. Use for auditing content systems.
Improves unclear UX copy, error messages, microcopy, labels, and instructions for better interface clarity. Useful when refining confusing text or bad UX writing.
Produces voice and tone guides, microcopy for UI features, and content audits of product copy. Use to define product voice, write interface text, or review existing microcopy.
Share bugs, ideas, or general feedback.
Audit microcopy, error messages, and UI strings for voice/tone consistency, clarity, and actionability. Produces a structured report with specific rewrites and a project voice guide when none exists.
Resolve project root. Use provided path or cwd.
Locate voice/tone guide. Search for VOICE.md, STYLE.md, docs/voice-guide.md, docs/tone.md, or a voice section in harness.config.json. If no guide is found, flag this as a gap and use sensible defaults (clear, concise, respectful, action-oriented).
Identify string sources. Scan the project for UI text using multiple strategies:
src/**/components/**/*.{tsx,jsx,vue,svelte} for inline textsrc/**/strings*, src/**/messages*, src/**/copy* for centralized copysrc/**/i18n/**, locales/, translations/ for translation keysthrow new Error, toast.error, setError, addNotificationlabel=, placeholder=, aria-label=, helperText=Determine audit scope. If --scope is provided, filter to the specified category. If triggered by a PR, scope to changed files only using git diff --name-only.
Build string inventory. Extract all user-facing strings with their source location, category (error, label, help, onboarding, confirmation, empty-state), and surrounding context.
Report discovery summary. Output the count of strings found by category and source type:
Discovery: 142 strings found
Errors: 23 | Labels: 48 | Help text: 31 | Onboarding: 12 | Empty states: 8 | Other: 20
Sources: 18 components, 3 string files, 2 i18n bundles
Check error messages against quality rules. Every error message must satisfy:
Check labels and form text. Evaluate:
Check voice/tone alignment. Compare strings against the voice guide (or defaults):
Check empty states and onboarding. Evaluate:
Check confirmation dialogs. Evaluate:
Classify findings by severity:
Generate specific rewrites. For every error and warning finding, provide:
Produce consistency patches. When terminology is inconsistent (e.g., "Sign in" vs "Log in"), recommend a single canonical term and list all locations that need updating.
Generate voice guide draft. If no voice guide was found in Phase 1, produce a draft VOICE.md covering:
Produce error message template. Generate a reusable template for error messages:
[What happened]. [Why / context]. [What to do next].
Example: "We couldn't save your changes. The file may have been modified by someone else. Try refreshing the page and saving again."
Prioritize recommendations. Order by impact: error-severity findings first, then warnings grouped by frequency (most repeated patterns first), then informational suggestions.
Check rewrites preserve meaning. Verify each recommended rewrite conveys the same information as the original. Flag any rewrite that changes the semantic meaning.
Check i18n compatibility. If the project uses i18n:
{count}, {{name}})Check length constraints. Verify rewrites fit within UI constraints:
Output structured report. Present findings in a format suitable for PR review:
UX Copy Audit: [PASS/NEEDS_ATTENTION/FAIL]
Strings audited: N
Findings: E errors, W warnings, I info
ERRORS:
[UXC-ERR-001] src/components/LoginForm.tsx:42
Current: "Invalid credentials"
Recommended: "That email and password combination didn't match. Please try again or reset your password."
Rule: error-missing-recovery-step
WARNINGS:
[UXC-WARN-001] Inconsistent terminology: "Sign in" (4 occurrences) vs "Log in" (2 occurrences)
Recommendation: Standardize on "Sign in" across all 6 locations.
Verify voice guide completeness. If a voice guide was generated, confirm it covers all required sections and includes at least 3 examples per section.
harness skill run harness-ux-copy -- Primary command for running the UX copy audit.harness validate -- Run after applying recommended changes to verify project health.Glob -- Used to locate string sources, component files, and voice guides.Grep -- Used to extract inline strings, error patterns, and label attributes from source files.Read -- Used to read voice guides, component files, and string constant files.Write -- Used to generate voice guide drafts when none exists.emit_interaction -- Used to present findings and request confirmation on bulk terminology changes.Phase 1: DISCOVER
Scanned: 34 components, 2 string files, 1 i18n bundle
Found: 89 strings (18 errors, 32 labels, 14 help text, 25 other)
Voice guide: not found (will generate draft)
Phase 2: AUDIT
[UXC-ERR-001] src/components/CheckoutForm.tsx:78
"Payment failed" -- missing context and recovery step
[UXC-ERR-002] src/components/SignupForm.tsx:33
"Invalid email" -- blame language, no guidance
[UXC-WARN-001] Terminology inconsistency:
"Shopping cart" (3 files) vs "Cart" (5 files) vs "Basket" (1 file)
[UXC-WARN-002] src/components/EmptyOrders.tsx:12
"No orders" -- empty state missing guidance on what to do
Phase 3: GUIDE
Rewrite: "Payment failed" ->
"Your payment didn't go through. Please check your card details and try again, or use a different payment method."
Rewrite: "Invalid email" ->
"Please enter a valid email address, like name@example.com."
Terminology: Standardize on "Cart" (most frequent, shortest)
Generated: VOICE.md draft with friendly-professional tone
Phase 4: VALIDATE
All rewrites preserve original meaning: YES
i18n interpolation variables intact: YES
Length constraints met: 1 warning (payment rewrite exceeds toast limit, suggest truncated variant)
Result: NEEDS_ATTENTION -- 2 errors, 2 warnings
Phase 1: DISCOVER
Voice guide found: docs/VOICE.md (professional, empathetic, action-oriented)
Scanned: 52 components, 4 string files
Scope: PR diff (8 changed files, 14 new/modified strings)
Phase 2: AUDIT
[UXC-ERR-001] src/views/Settings.vue:145
"Error: 403 Forbidden" -- exposes HTTP status, no user context
[UXC-WARN-001] src/views/Dashboard.vue:67
"Click here to learn more" -- vague CTA, accessibility concern
[UXC-INFO-001] src/components/Sidebar.vue:23
"Organisations" -- British spelling, rest of app uses American English
Phase 3: GUIDE
Rewrite: "Error: 403 Forbidden" ->
"You don't have permission to change these settings. Ask your workspace admin to update your role."
Rewrite: "Click here to learn more" ->
"Learn how to configure integrations"
Consistency: Standardize on American English per voice guide
Phase 4: VALIDATE
All rewrites align with VOICE.md tone: YES
Result: NEEDS_ATTENTION -- 1 error, 1 warning, 1 info
Phase 1: DISCOVER
i18n framework: next-intl (detected via next.config.js and messages/ directory)
Locales: en, es, fr, de
Scanned: messages/en.json (312 keys)
Scope: --scope errors
Phase 2: AUDIT
[UXC-ERR-001] messages/en.json -> errors.generic
"Something went wrong" -- no context, no recovery
[UXC-ERR-002] messages/en.json -> errors.network
"Network error" -- technical, no user action
[UXC-ERR-003] messages/en.json -> checkout.cardDeclined
"Your card was declined" -- blame language
Phase 3: GUIDE
Rewrite: errors.generic ->
"Something unexpected happened on our end. Please try again, or contact support if the problem continues."
Rewrite: errors.network ->
"We're having trouble connecting. Please check your internet connection and try again."
Rewrite: checkout.cardDeclined ->
"This card couldn't be processed. Please try a different card or contact your bank."
Note: All rewrites use {variable} interpolation compatible with next-intl
Phase 4: VALIDATE
Interpolation variables preserved: YES (no variables in affected keys)
Translator review needed: YES (3 keys modified, flag for es/fr/de update)
Result: NEEDS_ATTENTION -- 3 errors requiring translator coordination
| Rationalization | Reality |
|---|---|
"There's no voice guide, but the existing strings have a consistent tone — I can infer the voice from them and skip generating VOICE.md." | Inferring voice from existing strings that may themselves have quality problems is circular. The GUIDE phase must produce a VOICE.md draft when none exists. Without a written guide, the audit has no stable reference for subsequent runs. |
| "This error message says 'Invalid credentials' — the rewrite is obvious, so I'll apply it without waiting for confirmation." | The gates require no semantic changes and no bulk changes without confirmation. Even obvious rewrites must be presented in the structured report format with the UXC-ERR code, current string, recommendation, rule, and rationale — not applied directly. |
"The {count} interpolation variable is in the original string — my rewrite restructured the sentence so the variable moved to a different position. That's still compatible." | Rewrites must preserve interpolation variables exactly as they appear. If restructuring a sentence moves a variable to a position where the resulting translation would be grammatically wrong in target locales, the rewrite is invalid. Flag it for translator review instead. |
| "There are 8 occurrences of 'Sign in' and 3 of 'Log in' — I'll just update all 11 to 'Sign in' since that's clearly the majority term." | Terminology standardization affecting more than 5 files requires presenting the full change list and waiting for human confirmation before recommending. The majority term is a reasonable default recommendation, but the human must approve the batch. |
| "This empty state just says 'No results' — that's a warning, not an error, so I can deprioritize it and skip the rewrite." | Every warning finding requires a specific rewrite, not just a note that one is needed. The GUIDE phase produces rewrites for all error and warning findings. Skipping the rewrite for any classified finding produces an incomplete report. |
{count} or renames {{userName}} is invalid.