Awesome-omni-skill casing-law
This skill should be used when the user is writing code with mixed casing conventions, choosing casing for identifiers, enforcing casing consistency across a codebase, or when camelCase and snake_case appear in the same file. Covers per-context casing rules, acronym handling, and the absolute prohibition of mixed conventions.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/casing-law" ~/.claude/skills/diegosouzapw-awesome-omni-skill-casing-law && rm -rf "$T"
skills/development/casing-law/SKILL.mdCasing Is Law, Not Preference
Mixed casing in a codebase is not a style disagreement. It is a defect. When
getUserName sits next to get_user_email in the same file, the reader cannot predict the shape of the next function. Predictability is the foundation of readable code. Every language has established casing conventions. Follow them absolutely, enforce them mechanically, and treat violations the same way you treat failing tests.
The Universal Casing Table
Every identifier in your codebase falls into one of these categories. The casing is determined by the language and the identifier's role. There is no room for personal preference.
Python
| Identifier Type | Convention | Example |
|---|---|---|
| Variables | | , |
| Functions | | , |
| Method names | | |
| Function parameters | | |
| Classes | | , |
| Exceptions | | , |
| Constants | | , |
| Modules (files) | | , |
| Packages (directories) | (short, no underscores preferred) | , |
| Type aliases | | , |
| Enum members | | |
Python enforces this by convention (PEP 8), and tools like
flag violations automatically.ruff
TypeScript
| Identifier Type | Convention | Example |
|---|---|---|
| Variables | | , |
| Functions | | , |
| Method names | | |
| Function parameters | | |
| Classes | | , |
| Interfaces | | , |
| Type aliases | | , |
| Enums | (name), (members) | |
| Constants | | , |
| React components | | , |
| Hooks | with prefix | , |
| Files (general) | | , |
| Files (React components) | | |
| Files (tests) | Match source + | |
Do not prefix interfaces with
. I
IUserProfile is a C# convention that has no place in TypeScript. Use UserProfile for the interface. If you need to distinguish an interface from a class, the class gets the more specific name: UserProfileImpl, InMemoryUserProfile.
Go
| Identifier Type | Convention | Example |
|---|---|---|
| Exported (public) anything | | , , |
| Unexported (private) anything | | , , |
| Constants | (exported) / (unexported) | / |
| Packages | (single word, no underscores, no hyphens) | , , |
| Files | | , |
| Interfaces | , often suffix | , , |
| Struct fields | (exported) / (unexported) | , |
| Receivers | 1-2 letter abbreviation of the type | |
| Test files | Match source + | |
Go has one absolute rule: no underscores in identifiers (except file names and test functions).
max_retries is wrong in Go. Always. maxRetries or MaxRetries depending on export visibility.
Acronym Handling
Acronyms are the most common source of casing inconsistency. Each language handles them differently, and those differences are non-negotiable.
Python: Acronyms Follow Normal Casing
In Python, treat acronyms like regular words:
| Context | Correct | Wrong |
|---|---|---|
| Variable | | , |
| Function | | |
| Class | | |
| Class | | |
| Class | | |
| Constant | | |
Exception: Two-letter acronyms in class names stay uppercase:
IOError, OSError. This follows stdlib convention. But for your own classes, prefer IoHandler for consistency.
TypeScript: Acronyms Follow Normal Casing
Same as Python -- treat acronyms as regular words in PascalCase and camelCase:
| Context | Correct | Wrong |
|---|---|---|
| Variable | | , |
| Function | | |
| Class/Interface | | |
| Class/Interface | | |
| Type | | |
| Constant | | |
Why not
? Because when two acronyms collide, readability collapses: HTTPClient
XMLHTTPRequest vs XmlHttpRequest. The latter is instantly parseable. The former requires the reader to mentally split XMLHTTP.
Go: Acronyms Stay Uppercase
Go is the exception. Go's official convention keeps well-known acronyms fully uppercase:
| Context | Correct | Wrong |
|---|---|---|
| Exported | | |
| Exported | | |
| Exported | | |
| Exported | | |
| Unexported | | |
| Unexported | | |
Go recognizes these acronyms:
API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS.
When an unexported identifier starts with an acronym, the entire acronym is lowercase:
httpClient, jsonParser, urlValidator. Never hTTPClient.
File Naming Casing
File names follow language-specific conventions. Mixing file name casing within a project is a codebase smell visible from the directory listing.
| Language | Convention | Example |
|---|---|---|
| Python | | , |
| TypeScript (general) | | , |
| TypeScript (React) | | , |
| Go | | , |
Never mix. If your project has
userProfile.ts, payment-processor.ts, and OrderService.ts, the project has three conventions and zero discipline.
The Cardinal Sin: Mixed Conventions in One File
This is the single most important rule in this entire skill. Never mix casing conventions within a file. A file that contains both
getUserName and get_user_email is broken. It does not matter which convention is "better." Pick one. Apply it everywhere. Enforce it with a linter.
// CARDINAL SIN: Three conventions in one file const user_name = "Alice"; // snake_case variable in TypeScript const userEmail = "alice@test.com"; // camelCase variable const UserAge = 30; // PascalCase variable (not a class) function get_profile() { ... } // snake_case function in TypeScript function getUserOrders() { ... } // camelCase function
Every one of these is a defect. In TypeScript, variables and functions are
camelCase. Period.
Cross-Boundary Consistency
When data crosses a boundary -- API to frontend, database to application, service to service -- casing conventions collide. The rule: map at the boundary, never mix in the interior.
API Returns snake_case, Frontend Uses camelCase
// The API response (snake_case -- standard for JSON APIs) // { // "user_id": "usr_abc123", // "first_name": "Alice", // "created_at": "2024-01-15T10:30:00Z" // } // BAD: Mixing snake_case from the API with camelCase in application code function UserCard({ user }: { user: any }) { return ( <div> <h2>{user.first_name}</h2> {/* snake_case leaked into component */} <span>{user.created_at}</span> {/* snake_case leaked into component */} <span>{user.phoneNumber}</span> {/* camelCase from somewhere else */} </div> ); } // GOOD: Map at the boundary, use camelCase everywhere internally interface User { userId: string; firstName: string; createdAt: string; } function mapApiUserToUser(apiUser: Record<string, unknown>): User { return { userId: apiUser.user_id as string, firstName: apiUser.first_name as string, createdAt: apiUser.created_at as string, }; } function UserCard({ user }: { user: User }) { return ( <div> <h2>{user.firstName}</h2> <span>{user.createdAt}</span> </div> ); }
Database Uses snake_case, Go Uses PascalCase/camelCase
// GOOD: Struct tags map the boundary, Go code uses Go conventions type UserProfile struct { UserID string `db:"user_id" json:"user_id"` FirstName string `db:"first_name" json:"first_name"` CreatedAt time.Time `db:"created_at" json:"created_at"` } // BAD: Leaking database casing into Go code type UserProfile struct { user_id string // Wrong: underscores in Go identifiers first_name string // Wrong: underscores in Go identifiers created_at time.Time // Wrong: underscores in Go identifiers }
Good/Bad Examples
Python
# BAD: Mixed casing, inconsistent conventions class userProfile: # class should be PascalCase firstName = "" # attribute should be snake_case LastName = "" # attribute should be snake_case def GetFullName(self): # method should be snake_case return f"{self.firstName} {self.LastName}" maxRetries = 3 # constant should be UPPER_SNAKE_CASE default_timeout = 30 # constant should be UPPER_SNAKE_CASE # GOOD: Consistent Python conventions class UserProfile: first_name = "" last_name = "" def get_full_name(self): return f"{self.first_name} {self.last_name}" MAX_RETRIES = 3 DEFAULT_TIMEOUT_SECONDS = 30
TypeScript
// BAD: Mixed casing nightmare interface user_profile { // interface should be PascalCase First_Name: string; // field should be camelCase last_name: string; // field should be camelCase Email: string; // field should be camelCase } const MAX_RETRIES = 3; // OK: constant let User_Name = "Alice"; // variable should be camelCase function Process_Order(order_id: string) {} // function and param should be camelCase // GOOD: Consistent TypeScript conventions interface UserProfile { firstName: string; lastName: string; email: string; } const MAX_RETRIES = 3; let userName = "Alice"; function processOrder(orderId: string) {}
Go
// BAD: Underscores and wrong casing type user_profile struct { // No underscores in Go identifiers first_name string // No underscores user_Id string // Inconsistent: should be userID } func get_user_name(user_id string) string { // No underscores in function names return "" } const max_retries = 3 // No underscores in constants // GOOD: Go conventions followed exactly type userProfile struct { firstName string userID string // ID is a recognized acronym: fully uppercase } func getUserName(userID string) string { return "" } const maxRetries = 3
Examples
Working implementations in
examples/:
-- Comprehensive multi-language examples showing correct casing conventions in Python, TypeScript, and Go, including acronym handling, file naming, and cross-boundary mappingexamples/casing-conventions.md
Review Checklist
When reviewing code for casing consistency:
- Every identifier follows the language's casing convention (see Universal Casing Table)
- No mixed casing conventions within any single file
- Acronyms follow language-specific rules (lowercase in Python/TypeScript PascalCase, uppercase in Go)
- File names follow language conventions:
,snake_case.py
,kebab-case.ts
,PascalCase.tsxsnake_case.go - No
prefix on TypeScript interfaces (I
notUserProfile
)IUserProfile - Constants use
in Python and TypeScript,UPPER_SNAKE_CASE
/PascalCase
in GocamelCase - Cross-boundary casing is mapped at the boundary (API snake_case to frontend camelCase, database to application)
- No snake_case leaking into TypeScript/Go application code from API responses or database columns
- Enum members follow language conventions:
in Python,UPPER_SNAKE_CASE
in TypeScript,PascalCase
in GoPascalCase - React components use
file names; non-component TypeScript files usePascalCasekebab-case - Go identifiers contain zero underscores (except file names and test function names)
- Go struct tags handle the mapping between Go casing and JSON/database casing