Name it better
Purpose
Produce better name candidates for anything that needs one: an
identifier, file, module, skill, repo, or domain term. Then hand the
human a scored shortlist to choose from. The dominant trigger is a
reactive retry: a name was just suggested and rejected, and the same
context that produced it will only produce more of the same. So the
generators run BLIND to the conversation, from distinct lenses, to break
the anchor. A blank-slate naming request is the same machinery without a
rejected incumbent.
The human always picks. This skill narrows and recommends; it never
auto-locks a name.
Criteria. Cite the source of truth, do not copy it
Score against the consuming organization's naming criteria, resolved from
its own context, never from a baked-in path:
Declared conventions win. When the consuming project names where its
naming and domain-language conventions live, its CLAUDE.md,
.claude/rules/, or a shared standards source it points to, score against
THAT. Read the criteria there; do not restate them here. A criterion the
user wants that is missing from those conventions flows UP into them
(their standards change), not hardcoded into this skill.
None declared → the general criteria grounded in
context/sources.md, applied in this
research-ordered priority. A higher tier breaks ties over every tier
below it:
- Semantic accuracy (anti-misleading). The name must not lie about
what the thing does. A misleading name is empirically worse than a
vague or meaningless one, so this outranks everything below.
- Scope fit. Length and detail scale with the thing's scope and
lifetime; never repeat information the surrounding context (package,
type, module) already supplies.
- Comprehensibility. Prefer full, intention-revealing words over
abbreviations, bounded: established idioms and conventionally short
names (loop
i, a receiver) are not penalised.
- Trigger / evocative utility. How well the name cues recall at the
moment of use. That is a genuine tiebreaker, but the lowest-priority one.
This ordering governs the scoring and judging steps. It is the fallback
only: a consuming project's declared criteria (rule 1) override it
wherever the two differ.
Semantic vs syntactic. The modality layer
Naming criteria split in two. The semantic layer covers accuracy, scope
fit, no collisions, and noun-for-a-thing / verb-for-an-action. It carries across
every modality, and is what the generators and judges optimise. The
syntactic layer covers casing, length budgets, and separator and affix
conventions. It is modality- and vendor-specific; apply it as a final
shaping pass over the semantic winners, never as a scoring axis that
overrides meaning. Shaping can change the string, so RE-RUN the full
merge-step filter set on the shaped forms: dedupe, collision, reject-list,
word-blocklist. Two distinct candidates can normalize to one string
(SessionStore and session-store → session_store), a normalization
can recreate an existing sibling or a rejected incumbent, and a required
affix can introduce a blocked word (Order → OrderManager) that the
pre-scoring filters could not match.
- Route documented conflicts out; do not pick a side. Where authorities
genuinely disagree on abbreviation policy, acronym casing, or camelCase vs
snake_case, this skill takes no house position. Defer to the consuming
ecosystem's own style guide (rule 1's declared conventions); the
conflicting primaries are catalogued in
context/sources.md.
- Claude Code skills are the sharp special case. For a skill, the
DESCRIPTION, not the name, is what drives model-side discovery. So
optimise the name for human semantic accuracy, and put the trigger
phrases and example requests in the description, not the name. A skill
loadable as primed context at conversation start must also be
temporally neutral: the name has to read valid before any work
exists, so a candidate that presupposes completed output ("critique your
run") fails for a skill that can fire cold.
Default pass
Build the structured context brief. This brief, NOT the
conversation, is all the generators receive, so it must carry every
field they need, each captured by name:
- Target modality. What KIND of thing is being named (function,
type, module, file, CLI command, skill, domain term): it fixes
noun-for-a-thing vs verb-for-an-action and tells the final shaping
pass which syntactic conventions apply.
- Responsibility. What the thing DOES, in one line.
- Firing / usage context. When it is reached for, and how it reads
at the call site.
- Scope boundaries. What it is NOT: the adjacent things it must not
be confused with or blur into.
- Collision vocabulary. The existing sibling names it must not
duplicate.
- Terms of art. The established names the field or domain already
uses for this act or thing, with their ACTUAL researched meanings, not
recalled ones. Research them before the fan-out: a term whose field
meaning diverges from this target is misleading (criterion 1) and the
divergence belongs in the brief so generators neither borrow it blindly
nor miss the honest established term.
- Word-level blocklist. Individual words ruled out, each WITH its
reason (overloaded, misleading, collides, already rejected) AND its
provenance: user-stated or agent-inferred. An agent-inferred entry is a
proposal to confirm with the user, never a silently hard constraint. An
assumed blocklist word can eliminate the honest winner.
Rejected incumbent NAMES deliberately stay out of the brief. The main
thread holds them as its reject list and disqualifies matches at merge
time (anti-anchoring: a generator shown a rejected name re-derives it).
Only the abstracted REASON a name failed enters the brief, as a
blocklist entry or scope-boundary correction.
The brief mirrors the replicated concept → word → structure naming model
(grounded in context/sources.md): the named
fields fix the concepts and constraints; the generators then choose the
words per concept and arrange the structure.
Fan out blind generators. Spawn ~3 fresh-context subagents, each
seeded ONLY with the brief (blind to this conversation and to each
other), each working a distinct lens:
- responsibility-literal. Name exactly what it does;
- moment-of-use. Name for how it reads at the call site;
- domain-lore. Name from the domain's ubiquitous language.
Running them blind and independent is deliberate anti-anchoring; the
method grounding is in context/sources.md.
Merge and score. For a name used as an utterance, a skill, command,
or anything invoked by saying it, apply the sentence-form test as an
early filter before scoring: is the candidate the imperative you would
actually say, readable cold with no context? Contentless idioms (a bare
"check", "take stock") fail it even when they score well on the criteria
below. For a skill loadable as primed context, apply the
temporal-neutrality test in the same early filter: a candidate that
presupposes completed work fails before scoring, however accurate it is
once work exists. Then pool the candidates, dedupe, and disqualify any
candidate that matches the rejected incumbent (if any), that contains a
USER-STATED word-level blocklist entry (a
generator can miss the brief's constraint; the merge step enforces it),
or that collides with the existing vocabulary. The rejected-incumbent list
is carried by the main thread as an explicit reject list, never shared with
the generators. A candidate containing
only an AGENT-INFERRED blocklist word is not disqualified. It stays in,
flagged with the inferred concern, so the user's pick confirms or
overrides the inference (provenance rule above). Score every
surviving candidate against the criteria resolved above, breaking ties
by their declared priority order.
Shortlist + recommend. Present a short ranked list with a
one-line rationale per candidate and a single RECOMMENDED pick, marked
and listed first.
Human picks. Stop and let the user choose. Do not apply the name.
Iterate on the rejection reason
If the human rejects the shortlist or a specific candidate, the rejection
is data, not a dead end. Capture the REASON as an explicit new constraint
and fold it into the next round's brief before regenerating:
- a word that drew the objection becomes a word-level blocklist entry,
carrying that reason;
- a "wrong scope / wrong thing" objection becomes a scope-boundary
correction;
- a "these all miss what matters" objection reweights the criteria for
the next round, but only within the space the consuming project's
declared conventions leave open. Declared conventions still win: a
rejection that contradicts them routes upstream as a proposed convention
change, never a silent local reweighting.
Rejected names and rejected words never re-enter. The reject list and the
word-level blocklist only grow across rounds. Each new round is a fresh
blind fan-out seeded with the corrected brief, never a patch of the last
round's candidates.
tournament action
When $ARGUMENTS contains tournament, run this in place of the default
pass.
/naming:name-it-better tournament is for a high-stakes name that will be
hard to refactor later. Widen to ~5 generators (optionally different
models), then run elimination rounds with independent scoring judges until
one candidate remains, and present it plus the runners-up for the human
choice.
The default pass's merge filters still apply BEFORE the elimination rounds
begin, including the sentence-form and temporal-neutrality tests for
utterance and cold-loadable names and the blocklist provenance rule: pool
the widened candidates, fail contentless idioms and
completed-work-presupposing names early, and disqualify any that match the rejected incumbent, contain
a user-stated blocklisted word, or collide with the existing vocabulary
(agent-inferred blocklist matches enter the bracket flagged, not
disqualified).
Settle the scoring criteria before the generators return, and write them
down. The criteria are still resolved from the consuming project's own
declared standards, not chosen here. Which of them decide this name,
and how they rank, is a judgement, and it must be made while the pool is
still unknown. A rubric fixed after the candidates land gets shaped by
them, and one that already fits the pool cannot eliminate anything: the
independent judges then score against a standard the pool itself authored.
A criterion found missing mid-bracket still routes upstream, and adding it
means re-scoring the round it changes.
HONEST FRAMING: a "naming tournament / bracket" is NOT a documented
software-naming technique. This mode ADAPTS elimination brackets plus
pairwise social-choice scoring as a convergence mechanism. See
context/sources.md. Present it as such, not as an
established standard.
Adjacent skills. Hand off, do not overlap
- The target is a domain concept. Naming a domain term well depends on
first settling what the concept IS, not just its label. Route that to a
domain-modelling capability, then name the settled concept once it
returns. Pointer only. This skill does not do the domain modelling.
- A rename is already decided. Sweeping references after the fact →
a rename-references capability. This skill picks the name; that one
propagates it.
Invoke an adjacent capability through its slash command when present;
degrade to prose guidance when it is absent.
What this skill does NOT do
- Never auto-locks a name. It always ends at a human choice.
- Does not apply the rename. Propagating a chosen name across call
sites is a rename-references capability's job.
- Does not copy or invent criteria. It scores against the resolved
source of truth; missing criteria route upstream, not into the skill.
- Does not claim tournament mode is a documented technique. It is an
adaptation, flagged as one.
- Does not pick a house side on documented style conflicts.
Abbreviation policy, acronym casing, and casing style route to the
consuming ecosystem's own style guide, never a baked-in verdict.
Gotchas
- If the generators are fed the conversation instead of just the brief,
the anti-anchoring purpose is defeated. They will re-derive the
rejected name. Seed them with the brief ONLY.
- A blind generator can still independently re-derive the rejected
incumbent (common for generic labels like
Manager or Context). That
is not a blinding failure. The main thread's reject list disqualifies
it at merge time regardless of how a candidate was produced.
- A candidate that scores well but collides with existing vocabulary is
disqualified, not shortlisted. Collision-check before scoring.
- A rejected candidate's REASON must become a brief constraint (a blocklist
word, a scope correction, a criteria reweight) before the next round, or
the blind fan-out re-derives the same reject.
tournament costs several generators plus judges; reserve it for names
that are genuinely expensive to change, not routine locals.
1---2name: name-it-better3description: Generate and evaluate fresh name candidates for anything: a variable, function, file, module, skill, repo, or domain term. Then let the human pick. Use when the target name is still UNDECIDED, whether the ask is a fresh name ('suggest names', 'what should I call this') or a retry on one just rejected ('name it better', 'that name is wrong', 'help me rename this to something better'). Not for an already-decided rename ('rename X to Y', 'I renamed X'). That routes to the rename-references sweep. Spawns blind fresh-context generators from distinct lenses; never auto-locks a name. Optional 'tournament' arg for high-stakes, hard-to-refactor names.4---56# Name it better78## Purpose910Produce better name candidates for anything that needs one: an11identifier, file, module, skill, repo, or domain term. Then hand the12human a scored shortlist to choose from. The dominant trigger is a13reactive retry: a name was just suggested and rejected, and the same14context that produced it will only produce more of the same. So the15generators run BLIND to the conversation, from distinct lenses, to break16the anchor. A blank-slate naming request is the same machinery without a17rejected incumbent.1819**The human always picks.** This skill narrows and recommends; it never20auto-locks a name.2122## Criteria. Cite the source of truth, do not copy it2324Score against the consuming organization's naming criteria, resolved from25its own context, never from a baked-in path:26271. **Declared conventions win.** When the consuming project names where its28 naming and domain-language conventions live, its `CLAUDE.md`,29 `.claude/rules/`, or a shared standards source it points to, score against30 THAT. Read the criteria there; do not restate them here. A criterion the31 user wants that is missing from those conventions flows UP into them32 (their standards change), not hardcoded into this skill.332. **None declared → the general criteria** grounded in34 [`context/sources.md`](context/sources.md), applied in this35 research-ordered priority. A higher tier breaks ties over every tier36 below it:37 1. **Semantic accuracy (anti-misleading).** The name must not lie about38 what the thing does. A misleading name is empirically worse than a39 vague or meaningless one, so this outranks everything below.40 2. **Scope fit.** Length and detail scale with the thing's scope and41 lifetime; never repeat information the surrounding context (package,42 type, module) already supplies.43 3. **Comprehensibility.** Prefer full, intention-revealing words over44 abbreviations, bounded: established idioms and conventionally short45 names (loop `i`, a receiver) are not penalised.46 4. **Trigger / evocative utility.** How well the name cues recall at the47 moment of use. That is a genuine tiebreaker, but the lowest-priority one.4849 This ordering governs the scoring and judging steps. It is the fallback50 only: a consuming project's declared criteria (rule 1) override it51 wherever the two differ.5253## Semantic vs syntactic. The modality layer5455Naming criteria split in two. The **semantic layer** covers accuracy, scope56fit, no collisions, and noun-for-a-thing / verb-for-an-action. It carries across57every modality, and is what the generators and judges optimise. The58**syntactic layer** covers casing, length budgets, and separator and affix59conventions. It is modality- and vendor-specific; apply it as a final60shaping pass over the semantic winners, never as a scoring axis that61overrides meaning. Shaping can change the string, so RE-RUN the full62merge-step filter set on the shaped forms: dedupe, collision, reject-list,63word-blocklist. Two distinct candidates can normalize to one string64(`SessionStore` and `session-store` → `session_store`), a normalization65can recreate an existing sibling or a rejected incumbent, and a required66affix can introduce a blocked word (`Order` → `OrderManager`) that the67pre-scoring filters could not match.6869- **Route documented conflicts out; do not pick a side.** Where authorities70 genuinely disagree on abbreviation policy, acronym casing, or camelCase vs71 snake_case, this skill takes no house position. Defer to the consuming72 ecosystem's own style guide (rule 1's declared conventions); the73 conflicting primaries are catalogued in74 [`context/sources.md`](context/sources.md).75- **Claude Code skills are the sharp special case.** For a skill, the76 DESCRIPTION, not the name, is what drives model-side discovery. So77 optimise the name for human semantic accuracy, and put the trigger78 phrases and example requests in the description, not the name. A skill79 loadable as primed context at conversation start must also be80 **temporally neutral**: the name has to read valid before any work81 exists, so a candidate that presupposes completed output ("critique your82 run") fails for a skill that can fire cold.8384## Default pass85861. **Build the structured context brief.** This brief, NOT the87 conversation, is all the generators receive, so it must carry every88 field they need, each captured by name:89 - **Target modality.** What KIND of thing is being named (function,90 type, module, file, CLI command, skill, domain term): it fixes91 noun-for-a-thing vs verb-for-an-action and tells the final shaping92 pass which syntactic conventions apply.93 - **Responsibility.** What the thing DOES, in one line.94 - **Firing / usage context.** When it is reached for, and how it reads95 at the call site.96 - **Scope boundaries.** What it is NOT: the adjacent things it must not97 be confused with or blur into.98 - **Collision vocabulary.** The existing sibling names it must not99 duplicate.100 - **Terms of art.** The established names the field or domain already101 uses for this act or thing, with their ACTUAL researched meanings, not102 recalled ones. Research them before the fan-out: a term whose field103 meaning diverges from this target is misleading (criterion 1) and the104 divergence belongs in the brief so generators neither borrow it blindly105 nor miss the honest established term.106 - **Word-level blocklist.** Individual words ruled out, each WITH its107 reason (overloaded, misleading, collides, already rejected) AND its108 provenance: user-stated or agent-inferred. An agent-inferred entry is a109 proposal to confirm with the user, never a silently hard constraint. An110 assumed blocklist word can eliminate the honest winner.111112 Rejected incumbent NAMES deliberately stay out of the brief. The main113 thread holds them as its reject list and disqualifies matches at merge114 time (anti-anchoring: a generator shown a rejected name re-derives it).115 Only the abstracted REASON a name failed enters the brief, as a116 blocklist entry or scope-boundary correction.117118 The brief mirrors the replicated concept → word → structure naming model119 (grounded in [`context/sources.md`](context/sources.md)): the named120 fields fix the concepts and constraints; the generators then choose the121 words per concept and arrange the structure.1222. **Fan out blind generators.** Spawn ~3 fresh-context subagents, each123 seeded ONLY with the brief (blind to this conversation and to each124 other), each working a distinct lens:125 - **responsibility-literal.** Name exactly what it does;126 - **moment-of-use.** Name for how it reads at the call site;127 - **domain-lore.** Name from the domain's ubiquitous language.128129 Running them blind and independent is deliberate anti-anchoring; the130 method grounding is in [`context/sources.md`](context/sources.md).1313. **Merge and score.** For a name used as an utterance, a skill, command,132 or anything invoked by saying it, apply the **sentence-form test** as an133 early filter before scoring: is the candidate the imperative you would134 actually say, readable cold with no context? Contentless idioms (a bare135 "check", "take stock") fail it even when they score well on the criteria136 below. For a skill loadable as primed context, apply the137 **temporal-neutrality test** in the same early filter: a candidate that138 presupposes completed work fails before scoring, however accurate it is139 once work exists. Then pool the candidates, dedupe, and disqualify any140 candidate that matches the rejected incumbent (if any), that contains a141 USER-STATED word-level blocklist entry (a142 generator can miss the brief's constraint; the merge step enforces it),143 or that collides with the existing vocabulary. The rejected-incumbent list144 is carried by the main thread as an explicit reject list, never shared with145 the generators. A candidate containing146 only an AGENT-INFERRED blocklist word is not disqualified. It stays in,147 flagged with the inferred concern, so the user's pick confirms or148 overrides the inference (provenance rule above). Score every149 surviving candidate against the criteria resolved above, breaking ties150 by their declared priority order.1514. **Shortlist + recommend.** Present a short ranked list with a152 one-line rationale per candidate and a single RECOMMENDED pick, marked153 and listed first.1545. **Human picks.** Stop and let the user choose. Do not apply the name.155156## Iterate on the rejection reason157158If the human rejects the shortlist or a specific candidate, the rejection159is data, not a dead end. Capture the REASON as an explicit new constraint160and fold it into the next round's brief before regenerating:161162- a word that drew the objection becomes a **word-level blocklist** entry,163 carrying that reason;164- a "wrong scope / wrong thing" objection becomes a **scope-boundary**165 correction;166- a "these all miss what matters" objection **reweights the criteria** for167 the next round, but only within the space the consuming project's168 declared conventions leave open. Declared conventions still win: a169 rejection that contradicts them routes upstream as a proposed convention170 change, never a silent local reweighting.171172Rejected names and rejected words never re-enter. The reject list and the173word-level blocklist only grow across rounds. Each new round is a fresh174blind fan-out seeded with the corrected brief, never a patch of the last175round's candidates.176177## `tournament` action178179When `$ARGUMENTS` contains `tournament`, run this in place of the default180pass.181182`/naming:name-it-better tournament` is for a high-stakes name that will be183hard to refactor later. Widen to ~5 generators (optionally different184models), then run elimination rounds with independent scoring judges until185one candidate remains, and present it plus the runners-up for the human186choice.187188The default pass's merge filters still apply BEFORE the elimination rounds189begin, including the sentence-form and temporal-neutrality tests for190utterance and cold-loadable names and the blocklist provenance rule: pool191the widened candidates, fail contentless idioms and192completed-work-presupposing names early, and disqualify any that match the rejected incumbent, contain193a user-stated blocklisted word, or collide with the existing vocabulary194(agent-inferred blocklist matches enter the bracket flagged, not195disqualified).196197**Settle the scoring criteria before the generators return, and write them198down.** The criteria are still resolved from the consuming project's own199declared standards, not chosen here. *Which* of them decide this name,200and how they rank, is a judgement, and it must be made while the pool is201still unknown. A rubric fixed after the candidates land gets shaped by202them, and one that already fits the pool cannot eliminate anything: the203independent judges then score against a standard the pool itself authored.204A criterion found missing mid-bracket still routes upstream, and adding it205means re-scoring the round it changes.206207HONEST FRAMING: a "naming tournament / bracket" is NOT a documented208software-naming technique. This mode ADAPTS elimination brackets plus209pairwise social-choice scoring as a convergence mechanism. See210[`context/sources.md`](context/sources.md). Present it as such, not as an211established standard.212213## Adjacent skills. Hand off, do not overlap214215- **The target is a domain concept.** Naming a domain term well depends on216 first settling what the concept IS, not just its label. Route that to a217 domain-modelling capability, then name the settled concept once it218 returns. Pointer only. This skill does not do the domain modelling.219- **A rename is already decided.** Sweeping references after the fact →220 a rename-references capability. This skill picks the name; that one221 propagates it.222223Invoke an adjacent capability through its slash command when present;224degrade to prose guidance when it is absent.225226## What this skill does NOT do227228- **Never auto-locks a name.** It always ends at a human choice.229- **Does not apply the rename.** Propagating a chosen name across call230 sites is a rename-references capability's job.231- **Does not copy or invent criteria.** It scores against the resolved232 source of truth; missing criteria route upstream, not into the skill.233- **Does not claim tournament mode is a documented technique.** It is an234 adaptation, flagged as one.235- **Does not pick a house side on documented style conflicts.**236 Abbreviation policy, acronym casing, and casing style route to the237 consuming ecosystem's own style guide, never a baked-in verdict.238239## Gotchas240241- If the generators are fed the conversation instead of just the brief,242 the anti-anchoring purpose is defeated. They will re-derive the243 rejected name. Seed them with the brief ONLY.244- A blind generator can still independently re-derive the rejected245 incumbent (common for generic labels like `Manager` or `Context`). That246 is not a blinding failure. The main thread's reject list disqualifies247 it at merge time regardless of how a candidate was produced.248- A candidate that scores well but collides with existing vocabulary is249 disqualified, not shortlisted. Collision-check before scoring.250- A rejected candidate's REASON must become a brief constraint (a blocklist251 word, a scope correction, a criteria reweight) before the next round, or252 the blind fan-out re-derives the same reject.253- `tournament` costs several generators plus judges; reserve it for names254 that are genuinely expensive to change, not routine locals.