askill
casing-law

casing-lawSafety 100Repository

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.

1 stars
1.2k downloads
Updated 2/22/2026

Package Files

Loading files...
SKILL.md

Casing 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 TypeConventionExample
Variablessnake_caseuser_count, max_retries
Functionssnake_casefetch_active_users, calculate_tax_rate
Method namessnake_casedef validate_email(self)
Function parameterssnake_casedef create_order(customer_id, line_items)
ClassesPascalCaseUserProfile, PaymentProcessor
ExceptionsPascalCaseInvalidTokenError, RateLimitExceeded
ConstantsUPPER_SNAKE_CASEMAX_RETRY_COUNT, DEFAULT_TIMEOUT_SECONDS
Modules (files)snake_caseuser_profile.py, payment_processor.py
Packages (directories)snake_case (short, no underscores preferred)payments, userprofiles
Type aliasesPascalCaseUserId = str, OrderItems = list[LineItem]
Enum membersUPPER_SNAKE_CASEclass Status(Enum): ACTIVE = "active"

Python enforces this by convention (PEP 8), and tools like ruff flag violations automatically.

TypeScript

Identifier TypeConventionExample
VariablescamelCaseuserCount, maxRetries
FunctionscamelCasefetchActiveUsers, calculateTaxRate
Method namescamelCasevalidateEmail()
Function parameterscamelCasefunction createOrder(customerId, lineItems)
ClassesPascalCaseUserProfile, PaymentProcessor
InterfacesPascalCaseUserProfile, OrderRequest
Type aliasesPascalCaseUserId, OrderItems
EnumsPascalCase (name), PascalCase (members)enum OrderStatus { Pending, Shipped }
ConstantsUPPER_SNAKE_CASEMAX_RETRY_COUNT, DEFAULT_TIMEOUT_MS
React componentsPascalCaseUserProfileCard, PaymentForm
HookscamelCase with use prefixuseUserProfile, usePaymentForm
Files (general)kebab-caseuser-profile.ts, payment-processor.ts
Files (React components)PascalCaseUserProfileCard.tsx
Files (tests)Match source + .testuser-profile.test.ts

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 TypeConventionExample
Exported (public) anythingPascalCaseUserProfile, FetchActiveUsers, MaxRetries
Unexported (private) anythingcamelCaseuserProfile, fetchActiveUsers, maxRetries
ConstantsPascalCase (exported) / camelCase (unexported)MaxRetryCount / maxRetryCount
Packageslowercase (single word, no underscores, no hyphens)payments, auth, httputil
Filessnake_caseuser_profile.go, payment_processor.go
InterfacesPascalCase, often -er suffixReader, Validator, OrderProcessor
Struct fieldsPascalCase (exported) / camelCase (unexported)UserID, createdAt
Receivers1-2 letter abbreviation of the typefunc (u *User) Validate()
Test filesMatch source + _testuser_profile_test.go

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:

ContextCorrectWrong
Variablehttp_clientHTTP_client, hTTPClient
Functionparse_json_responseparse_JSON_response
ClassHttpClientHTTPClient
ClassJsonParserJSONParser
ClassUrlValidatorURLValidator
ConstantDEFAULT_HTTP_TIMEOUTDEFAULT_Http_TIMEOUT

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:

ContextCorrectWrong
VariablehttpClientHTTPClient, hTTPClient
FunctionparseJsonResponseparseJSONResponse
Class/InterfaceHttpClientHTTPClient
Class/InterfaceJsonParserJSONParser
TypeUrlConfigURLConfig
ConstantDEFAULT_HTTP_TIMEOUTDEFAULT_Http_TIMEOUT

Why not HTTPClient? Because when two acronyms collide, readability collapses: 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:

ContextCorrectWrong
ExportedHTTPClientHttpClient
ExportedJSONParserJsonParser
ExportedURLValidatorUrlValidator
ExportedUserIDUserId
UnexportedhttpClienthTTPClient
UnexporteduserIDuserId

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.

LanguageConventionExample
Pythonsnake_case.pyuser_profile.py, payment_processor.py
TypeScript (general)kebab-case.tsuser-profile.ts, payment-processor.ts
TypeScript (React)PascalCase.tsxUserProfileCard.tsx, PaymentForm.tsx
Gosnake_case.gouser_profile.go, payment_processor.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/:

  • examples/casing-conventions.md -- Comprehensive multi-language examples showing correct casing conventions in Python, TypeScript, and Go, including acronym handling, file naming, and cross-boundary mapping

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.tsx, snake_case.go
  • No I prefix on TypeScript interfaces (UserProfile not IUserProfile)
  • Constants use UPPER_SNAKE_CASE in Python and TypeScript, PascalCase/camelCase in Go
  • 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: UPPER_SNAKE_CASE in Python, PascalCase in TypeScript, PascalCase in Go
  • React components use PascalCase file names; non-component TypeScript files use kebab-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

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

95/100Analyzed 2/25/2026

Comprehensive and authoritative skill covering casing conventions across Python, TypeScript, and Go. Includes detailed tables, code examples, and cross-boundary consistency patterns. Well-structured with clear triggers, good metadata, and high reusability. No safety concerns. Minor gap: truncated content ends mid-sentence but appears complete in available text.

100
95
90
95
95

Metadata

Licenseunknown
Version1.0.0
Updated2/22/2026
Publisheroborchers

Tags

apidatabaselintingsecuritytesting