skills/naming-cheatsheet/SKILL.md
Apply language-agnostic naming conventions using the A/HC/LC pattern. Use when naming variables, functions, or reviewing code for naming consistency.
npx skillsauth add Thomashighbaugh/opencode naming-cheatsheetInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Comprehensive guidelines for naming variables and functions in any programming language, based on the A/HC/LC pattern.
Names must be:
| Principle | Description | | --------------- | -------------------------------------------------------- | | Short | Not take long to type and remember | | Intuitive | Read naturally, close to common speech | | Descriptive | Reflect what it does/possesses in the most efficient way |
/* Bad */
const a = 5 // "a" could mean anything
const isPaginatable = a > 10 // sounds unnatural
const shouldPaginatize = a > 10 // made-up verb
/* Good */
const postCount = 5
const hasPagination = postCount > 10
const shouldPaginate = postCount > 10
The core pattern for naming functions:
prefix? + action (A) + high context (HC) + low context? (LC)
| Name | Prefix | Action (A) | High Context (HC) | Low Context (LC) |
| ---------------------- | -------- | ---------- | ----------------- | ---------------- |
| getUser | | get | User | |
| getUserMessages | | get | User | Messages |
| handleClickOutside | | handle | Click | Outside |
| shouldDisplayMessage | should | Display | Message | |
Context order matters: shouldUpdateComponent means you update the component, while shouldComponentUpdate means component updates itself.
getAccesses data immediately (shorthand getter). Also used for async operations.
function getFruitCount() {
return this.fruits.length
}
async function getUser(id) {
const user = await fetch(`/api/user/${id}`)
return user
}
setSets a variable declaratively, from value A to value B.
let fruits = 0
function setFruits(nextFruits) {
fruits = nextFruits
}
resetSets a variable back to its initial value or state.
const initialFruits = 5
let fruits = initialFruits
function resetFruits() {
fruits = initialFruits
}
remove vs delete| Action | Use Case | Opposite |
| ---------- | ------------------------------------- | -------- |
| remove | Removes something from a collection | add |
| delete | Completely erases from existence | create |
// remove - from a collection (paired with add)
function removeFilter(filterName, filters) {
return filters.filter((name) => name !== filterName)
}
// delete - permanent erasure (paired with create)
function deletePost(id) {
return database.find({ id }).delete()
}
Key insight: add needs a destination, create does not. Pair remove with add, delete with create.
composeCreates new data from existing data.
function composePageUrl(pageName, pageId) {
return pageName.toLowerCase() + '-' + pageId
}
handleHandles an action, often used for callback methods.
function handleLinkClick() {
console.log('Clicked a link!')
}
link.addEventListener('click', handleLinkClick)
| Prefix | Usage | Example |
| -------- | ----------------------------------------------- | ------------------------------------------ |
| is | Describes characteristic or state | isBlue, isPresent, isEnabled |
| has | Describes possession of value or state | hasProducts, hasPermission |
| should | Positive conditional coupled with action | shouldUpdateUrl, shouldDisplayMessage |
/* Bad */
const isProductsExist = productsCount > 0
const areProductsPresent = productsCount > 0
/* Good */
const hasProducts = productsCount > 0
| Prefix | Usage | Example |
| ------------ | ------------------------------- | ---------------------------- |
| min/max | Minimum or maximum value | minPosts, maxRetries |
| prev/next| Previous or next state | prevPosts, nextPosts |
function renderPosts(posts, minPosts, maxPosts) {
return posts.slice(0, randomBetween(minPosts, maxPosts))
}
async function getPosts() {
const prevPosts = this.state.posts
const latestPosts = await fetch('...')
const nextPosts = concat(prevPosts, latestPosts)
this.setState({ posts: nextPosts })
}
/* Bad */
const primerNombre = 'Gustavo'
const amigos = ['Kate', 'John']
/* Good */
const firstName = 'Gustavo'
const friends = ['Kate', 'John']
Pick one convention (camelCase, PascalCase, snake_case) and stick to it.
/* Bad - inconsistent */
const page_count = 5
const shouldUpdate = true
/* Good - consistent */
const pageCount = 5
const shouldUpdate = true
/* Bad */
const onItmClk = () => {}
/* Good */
const onItemClick = () => {}
class MenuItem {
/* Bad - duplicates context */
handleMenuItemClick = (event) => { ... }
/* Good - reads as MenuItem.handleClick() */
handleClick = (event) => { ... }
}
/* Bad */
const isEnabled = itemCount > 3
return <Button disabled={!isEnabled} />
/* Good */
const isDisabled = itemCount <= 3
return <Button disabled={isDisabled} />
/* Bad */
const friends = 'Bob'
const friend = ['Bob', 'Tony', 'Tanya']
/* Good */
const friend = 'Bob'
const friends = ['Bob', 'Tony', 'Tanya']
| Pattern | Example |
| -------------------- | -------------------------------- |
| Get single item | getUser, getPost |
| Get collection | getUsers, getPosts |
| Get nested | getUserMessages |
| Set value | setUser, setTheme |
| Reset to initial | resetForm, resetFilters |
| Add to collection | addItem, addFilter |
| Remove from collection| removeItem, removeFilter |
| Create new entity | createUser, createPost |
| Delete permanently | deleteUser, deletePost |
| Compose/build | composeUrl, buildQuery |
| Handle event | handleClick, handleSubmit |
| Boolean state | isActive, hasItems, shouldRender |
| Boundaries | minCount, maxRetries |
| State transitions | prevState, nextState |
use Prefix is Reserved for HooksThe use prefix in React is reserved for hooks. Don't use it for non-hook utilities:
// Bad - use prefix on non-hook
function useHasDifferentBillingAddress(formData) {
return formData.billingAddress !== formData.shippingAddress;
}
// Good - descriptive name without use prefix
function hasDifferentBillingAddress(formData) {
return formData.billingAddress !== formData.shippingAddress;
}
// Good - this is actually a hook (calls other hooks)
function useUserProfile(userId) {
const [user, setUser] = useState(null);
useEffect(() => { /* ... */ }, [userId]);
return user;
}
When functions return objects (especially result objects), use verb prefix:
// Bad - noun makes it unclear it's a function
const cartError = (errors) => ({
success: false,
error: { message: 'Failed', errors }
});
// Good - verb prefix indicates it's a factory function
const createCartErrorResult = (errors) => ({
success: false,
error: { message: 'Failed', errors }
});
// Usage is now self-documenting
const result = createCartErrorResult(validationErrors);
Distinguish between Error instances and error messages:
// Bad - error suggests Error instance, but it's a string
const error = 'Failed to fetch user';
throw new Error(error);
// Good - errorMessage clearly indicates it's a string
const errorMessage = 'Failed to fetch user';
throw new Error(errorMessage);
// Good - error is an Error instance
const error = new Error('Failed to fetch user');
console.error(error.message); // Access message property
// Good - errors array of Error instances
const errors = [
new Error('Network failed'),
new Error('Timeout'),
];
throw new AggregateError(errors, 'Multiple failures');
Source: kettanaito/naming-cheatsheet
tools
Create valid, type-safe TypeScript tools for OpenCode — generates correct boilerplate, typed interfaces, and handler stubs. Use when building new tools for global config or per-project .opencode/tools/.
testing
Explore multiple solution branches in parallel, evaluate each, and recommend the best path. Use when the user explicitly invokes /ideation tree-of-thoughts or asks for "tree of thought" / "branching exploration".
testing
Run multiple independent reasoning passes and find consensus. Use when the decision is critically important, the stakes are high, or the user explicitly requests "run it multiple times" / "check consistency" / "self-consistency".
testing
Optimization by PROmpting — generate candidate prompt variations, test each against a benchmark, and report the best performer. Use when the user invokes /ideation opro or asks for "prompt optimization" / "OPRO".