Skip to content
Development
Skill

/ui-copy

Copy rules for every user-visible string in riptide-ui, riptide-cloud, packages/ui, and server strings that reach a toast. ACTIVATE when adding, changing, or reviewing a button, menu item, dialog, toast, error, empty state, placeholder, tooltip, aria-label, setting, hotkey

BOOST
From plugin
humanlayer
12k56 skills
Install
$ npx -y skills add humanlayer/humanlayer --skill ui-copy --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/ui-copy

Context preview

The summary Claude sees to decide when to auto-load this skill.

Copy rules for every user-visible string in riptide-ui, riptide-cloud, packages/ui, and server strings that reach a toast. ACTIVATE when adding, changing, or reviewing a button, menu item, dialog, toast, error, empty state, placeholder, tooltip, aria-label, setting, hotkey

SKILL.md

ui-copy.SKILL.md
name: ui-copy
description: |
  Copy rules for every user-visible string in riptide-ui, riptide-cloud, packages/ui, and
  server strings that reach a toast. ACTIVATE when adding, changing, or reviewing a button,
  menu item, dialog, toast, error, empty state, placeholder, tooltip, aria-label, setting,
  hotkey description, banner, or onboarding text. Not for apps/docs, the CLI, or comments.

**First rule: write to the person, never about the system.** Every string answers "what does this mean for me and what can I do now?", never "what state is the code in?". A string that narrates internal state, preconditions, or implementation progress is a log line, not copy, even when it is accurate. Before any rule below, reread the string as the user and ask what they would do next. `Workspace setup is running independently. No session has started.` → `Setting up your workspace. Your session starts when it finishes.` `Worktree configuration is required to use "Now".` → `Add a workspace config to create worktrees now.` `Task creation sync timed out` → `Could not confirm the task was created. Check the task list before retrying.` `Comment sync still loading` → `Comments are loading`. `Workspace setup row is parked on an error` → `Workspace setup failed`. `Converging`, `Delivery rejected: …` → never.

Voice: a competent colleague at the next desk. Says the actual thing, names the key, admits limits. Never apologizes, sells, or shouts. Model string: `Updating will interrupt 3 active sessions on this device. Finish your work before updating, or choose` `Later`.

Changing a string that already ships

Writing a new string: apply everything below. **Changing one that exists: read this first.** A rule matching a line is not on its own a reason to rewrite it.

  • **Two kinds of finding.** *Mechanical* — a raw enum, Title Case, `...`, `ENTER`, `(s)`,

an internal name, `Failed to`, "please", a dead route. One right answer, no taste, fix it. *Voice* — hero lines, warnings, tips, empty states, anything with a deliberate point of view. Here the rule is a prompt to look, not a verdict.

  • **Change the defect, not the sentence.** If one word is wrong, fix that word.

`…how Riptide queries data… You probably don't want to mess with these.` needed Riptide → HumanLayer and nothing else.

  • **If the rewrite is only more conformant, stop.** It must be clearer, more honest, or more

useful *to the reader*. "Now it follows the guide" is not a benefit anyone experiences.

  • **Never bulk-rewrite voice.** Mechanical findings batch; voice findings go one at a time,

with the tension named, for a person to decide. An audit that proposes 180 rewrites has stopped reading and started matching.

  • **Hero and marketing copy is out of scope** unless it is factually wrong. The install page

and the composer headline are written on purpose.

  • When you are unsure which kind you have, it is voice. Leave it and say why you looked.

Mechanics

  • Sentence case everywhere: buttons, titles, headings, menu items, labels, badges, tabs, toasts.
  • Proper nouns keep casing: HumanLayer, HumanLayer Cloud, Claude Code, Codex, Fold, GitHub, Linear, Jira, Slack, Stripe, macOS, Starter/Pro/Enterprise, RPI, PRD, TDD.
  • Feature names are common nouns: fast mode, bypass permissions, auto-accept edits, multiplayer prompting, advanced metrics, commit tracking.
  • Never uppercase in the source string: write `Needs approval`, not `NEEDS_APPROVAL`; `DENY` → `Deny`. Rendering is then a CSS decision in one place, and **the default is not to uppercase**. The terminal-style caps on badges and eyebrows accreted rather than being designed, and the app reads better without them; keep them only where a surface earns it.
  • Never render a raw enum (`needs_approval`, `xhigh`). Add a label map first.
  • Full sentences end with a period. Fragments (buttons, labels, badges, placeholders, toast titles, headings, hotkey descriptions) do not.
  • Ellipsis is `…`, only on in-progress labels: `Saving…`. Never `...`, never on placeholders.
  • Em dash with spaces for a consequence. `·` between status facts (`This device · online`). `→` for sequences. `–` for ranges (`2–4×`). Oxford comma. Straight quotes.
  • No `!`. `&` only in a compact two-verb button (`Interrupt & send`); prose uses "and". No `+` in prose.
  • Address the user as "you".
  • Actor: **you** do what you click (install the GitHub App, connect Linear, start a daemon). **The agent** does the work in a session (fixes, implements, opens a pull request). **HumanLayer** only does what happens on its own with no click (syncs, checks this device, sends a notification). Otherwise no subject: `Could not save draft`. `Connect GitHub so the agent can open pull requests.` `HumanLayer checks this device before your first task.`
  • Never the **company "we"** — a faceless narrator reporting or apologising: `We couldn't fetch your organizations`, `Something went wrong on our end`, `we'll investigate`. Rewrite with no subject or with HumanLayer as the subject.
  • The **collaborative "we"** — you and the agent, as a pair — is allowed, and only in the composer where that pairing is literally what is happening: `What should we build today?` stays. Do not extend it to status, errors, or settings.
  • Never "please", "sorry", "successfully", "just", "simply", "Something went wrong", "Are you sure". No roadmap hedges: "currently", "not yet", "coming soon". `yet` in an empty-state fact (`No tasks yet`) is fine.
  • **Do not sand off personality.** A line with a point of view is not a defect. `You probably don't want to mess with these` is doing a real job; flattening it to `Change these only when asked to` is the machine talking. Fix what is wrong in a line (an internal name, a raw enum) and leave the rest alone. If a rewrite is only blander, do not make it.
  • Use contractions (`can't`, `don't`, `isn't`). The one exception is `cannot` in irreversibility warnings: `This action cannot be undone.`
  • No internal names (Riptide, CodeLaye
Read more
Ships withhumanlayer

HumanLayer runs coding agents (Claude Code, Codex, OpenCode, Pi) on your machines and lets your team steer them from one place: tasks, sessions, plans, and reviews, synced between a desktop app, a web app, and a daemon on each host. This repo holds all of it.

Get the whole plugin

Other skills on humanlayer.