# Naming Conventions

> Use when naming a new file, function, variable, type, route, database column, environment variable, or any other code or system artifact. Covers identifier morphology (verb-noun choice, plural vs singular, prefix/suffix conventions), kebab-case vs camelCase vs snake_case vs PascalCase per artifact kind, abbreviation rules, name-vs-path semantics, the rename-coordination workflow, and detection of names that lie. Do NOT use for content writing (use `documentation`), for restructuring already-named code (use `refactor`), or for human-language copy in product UI (separate skill, not in this library).

- Skill: `jacob-balslev/naming-conventions-2` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add jacob-balslev/naming-conventions-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jacob-balslev/naming-conventions-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- License: MIT
- Author: jacob-balslev (https://skillmd.com/u/jacob-balslev)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/jacob-balslev/naming-conventions-2

---

## Concept of the skill

**What it is:** Naming conventions are the rules that make artifact names truthful, predictable, and searchable across code, routes, data, configuration, and documentation-adjacent developer surfaces.

**Mental model:** A name is a compact contract: artifact kind decides casing, grammar decides the role of each word, and verbs/nouns promise behavior. A good name lets the reader infer what the artifact does before opening the implementation.

**Why it exists:** Names are read far more often than they are written. Choosing them deliberately prevents hidden cost: stale domain words, false verb promises, casing inconsistency, and missed references during renames.

**What it is NOT:** It is not whole-code refactoring, whole-diff code review, prose style guidance, product microcopy, or debugging a failed behavior after the name has already misled someone.

**Adjacent concepts:** Semantics, linguistics, refactor, code-review, debugging, version-control, and information architecture.

**One-line analogy:** Naming is like labeling circuit breakers: a short label is useful only when it truthfully names the circuit it controls.

**Common misconception:** Naming is not cosmetic. A misleading identifier creates a wrong model in every caller and reader, even when the code compiles.

# Naming Conventions

## Coverage

- Identifier morphology: verb-noun selection (`get` vs `fetch` vs `load`), plural vs singular for collections, prefix/suffix conventions (`is` / `has` / `should` for booleans, `use` for React hooks)
- Casing per artifact kind: kebab-case (file names, URL paths, CLI flags), camelCase (JavaScript/TypeScript variables and functions), PascalCase (types, classes, components, React JSX), snake_case (Python, SQL columns, environment variables when convention demands), SCREAMING_SNAKE_CASE (constants, env-var keys)
- Abbreviation rules: when an abbreviation is universally known (`url`, `id`, `api`), when it requires expansion (`cust` → `customer`), and when team-internal jargon must be avoided in public-facing names
- Name-vs-path semantics: the difference between *what an artifact is called* and *where it lives*; when name and path agree (file system) vs when they diverge (TypeScript module re-exports, npm-published package paths)
- Rename coordination: how to update every reference in the same commit, when to ship a deprecation alias, and how to detect missed call sites with grep
- Names that lie: identifiers whose words promise a behaviour the code does not deliver, and how to detect them (the function called `getX` that also writes; the boolean called `isReady` that means "should be ready"; the column called `created` that stores the ship date)
- Cross-cutting consistency: when a naming choice in one part of the codebase forces a related choice elsewhere (table column `customer_id` and TypeScript type `Customer.id`)

## Philosophy of the skill

Names are the most-read part of any codebase. Every reader pays the cost of a bad name; only the author pays the cost of choosing well. The single most valuable property of a name is *truthfulness*: a name that lies — about what an artifact does, returns, or means — is more harmful than a name that is merely unclear. The second-most-valuable property is *consistency with sibling names*: a function called `getOrders` should sit alongside `getCustomers`, not `loadCustomers`. The third is *brevity*, and only the third — short names that mislead are not a virtue.

When a name does not fit, the answer is almost always to rename, not to add a comment explaining what the name "really" means. Comments rot; renames travel with the code.

## Casing per Artifact Kind

Casing is project-convention-driven for the artifacts where languages don't enforce it, and language-mandated for the rest. Pick the convention once, document it in the project's CONTRIBUTING or AGENTS file, and apply it everywhere.

| Artifact | Convention | Example |
|---|---|---|
| File name (any) | kebab-case | `order-pricing.ts`, `webhook-handler.py` |
| URL path segment | kebab-case | `/api/order-pricing` |
| CLI flag | kebab-case | `--include-template` |
| JS/TS variable, function, parameter | camelCase | `orderTotal`, `calculateMargin()` |
| JS/TS type, class, interface, React component | PascalCase | `Order`, `OrderPricing`, `<OrderRow/>` |
| Python variable, function | snake_case | `order_total`, `calculate_margin` |
| Python class | PascalCase | `Order`, `OrderPricing` |
| SQL table name | snake_case (lowercase) | `orders`, `order_line_items` |
| SQL column name | snake_case | `created_at`, `customer_id` |
| Environment variable | SCREAMING_SNAKE_CASE | `STRIPE_SECRET_KEY`, `NODE_ENV` |
| Constant in code | SCREAMING_SNAKE_CASE | `MAX_RETRIES`, `DEFAULT_TIMEOUT_MS` |
| Boolean variable / function | `is*` / `has*` / `should*` / `can*` prefix | `isAdmin`, `hasReceipt`, `shouldRetry` |
| React hook | `use*` prefix (mandatory) | `useOrders`, `useDebounce` |
| Predicate function | verb in interrogative form | `validateEmail()`, `isValidEmail()` |

## Identifier Morphology

The verb you pick encodes a contract. Choose deliberately.

| Verb | Implies | Wrong when |
|---|---|---|
| `get` | Pure read; cheap; never mutates; idempotent | The function writes, calls an API, or has any side effect |
| `fetch` | Network or I/O read; may fail; may be slow | The function reads from local memory or never crosses a boundary |
| `load` | Read-and-cache, or read-from-disk; one-shot | The function returns synchronously from already-loaded data |
| `compute` / `calculate` | Pure transformation of inputs | The function takes no inputs or returns I/O |
| `validate` | Returns boolean OR throws; no side effects | The function modifies the input or has hidden side effects |
| `assert` | Throws on failure; void return on success | The function returns a value or has a happy non-throwing path |
| `parse` | String → structured data; may throw on malformed input | The function takes structured data or never throws |
| `format` | Structured data → string | The function returns structured data |
| `create` | Allocates/persists a new entity; returns its identity | The function returns a transient value with no persisted identity |
| `update` | Modifies an existing entity by identity | The function inserts or replaces |
| `delete` / `remove` | Removes an entity from the system | The function only removes from a transient view |

The single most common naming bug is `getX` that also writes. If the function has a side effect, the verb must be one that *implies* side effects (`save`, `apply`, `commit`, `flush`, `record`).

## Names That Lie

A name lies when its words promise behaviour the code does not deliver. Detecting these costs nothing at authoring time and saves real debugging time later.

- **Verb mismatch**: `getThing()` that calls a remote API, `validate()` that throws, `parse()` that returns null on failure (it should throw or be renamed `tryParse`).
- **Boolean polarity inversion**: `isInvalid` set to `true` to mean valid; the codebase will eventually have `if (!isInvalid)` and someone will read it backwards. Use `isValid` and invert the value.
- **Optional collapse**: `getOrder()` that returns `Order | undefined`. The caller has no way to know the function can return undefined without reading the implementation. Either rename to `findOrder()` (convention: "find" allows null return) or change to `getOrderOrThrow()`.
- **Stale meaning after refactor**: a column originally named `created` that, after a migration, now stores the ship date. The name predates the meaning. Rename the column AND all of its callers in the same commit.
- **Domain-language drift**: code says `User` but the domain glossary says `Account`. Pick one in the glossary and rename in code.

## Rename Coordination

Renaming is a small change that touches many places. Do all of them in one commit; ship none of them piecemeal.

1. **Pick the new name** by the rules above.
2. **Find every call site**: `grep -rn "OldName" --include="*.ts" --include="*.tsx" --include="*.md"` (and equivalent for your language). Don't trust IDE rename — it misses dynamic references and string literals.
3. **Update all references** in one diff. The diff stat should show the rename and nothing else. If you find yourself fixing other things along the way, split the commits.
4. **Decide on a deprecation alias** when external consumers may have pinned to the old name. Export both names for one minor version; remove the old name in the next minor.
5. **Run the lint and test suite** to catch dynamic references the grep missed (e.g., reflection, template strings, JSON config).
6. **Update docs** in the same commit. Stale docs are a naming bug.

## Verification

- [ ] The name is *truthful* — every word in the name describes behaviour the code actually delivers
- [ ] The casing matches the artifact-kind convention (file kebab, type PascalCase, env SCREAMING_SNAKE)
- [ ] The verb implies the right cost class (`get` is cheap, `fetch` may fail, `compute` is pure)
- [ ] Boolean prefix is positive polarity (`isValid` not `isInvalid`)
- [ ] Sibling artifacts use the same verb stem (don't mix `getOrders` with `loadCustomers`)
- [ ] No team-internal jargon in public-facing names (file names, route paths, error messages)
- [ ] Rename diffs touch ALL references in one commit, including docs and tests

## Do NOT Use When

| Use instead | When |
|---|---|
| `refactor` | Restructuring already-named code (extract function, inline variable, split file) — naming may change as a side effect of the refactor |
| `documentation` | Writing prose explanation of a naming convention — this skill makes the choice; documentation explains it |
| `code-review` | Evaluating a whole PR — naming is one of many concerns the reviewer covers |
| `debugging` | Investigating why a misnamed identifier produces wrong behaviour — debugging chases the bug; naming-conventions prevents the next one |

