Last Updated: 2026-10-17 Version: 1.0.0 Applies To: All code within Rig project
This document defines coding standards, file organization patterns, naming conventions, and best practices for Rig. All code must adhere to these standards to ensure consistency, maintainability, and quality.
- Avoid over-engineering and premature optimization
- Implement features only when needed
- Don't build infrastructure for hypothetical future requirements
- Start simple, refactor when necessary
- Prefer simple, straightforward solutions
- Avoid unnecessary complexity
- Write code that's easy to understand and modify
- Choose clarity over cleverness
- Eliminate code duplication
- Extract common logic into reusable functions/modules
- Use composition and abstraction appropriately
- Maintain single source of truth
project-root/
├── .claude/ # Claude Code configuration
│ ├── agents/ # Agent definitions (*.md)
│ ├── commands/ # Reserved compatibility directory (can be empty)
│ ├── hooks/ # Git hooks and scripts
│ ├── skills/ # Reusable knowledge modules
│ │ └── [skill-name]/ # Individual skill directories
│ │ ├── SKILL.md # Skill definition
│ │ └── references/ # Supporting materials
│ └── rules/ # Development rules and protocols
├── .github/ # GitHub-specific files
│ └── workflows/ # CI/CD workflows
├── docs/ # Project documentation
│ ├── research/ # Research reports
│ └── *.md # Core documentation files
├── guide/ # User guides
├── plans/ # Implementation plans
│ ├── reports/ # Agent communication reports
│ └── templates/ # Plan templates
├── src/ # Source code (if applicable)
├── tests/ # Test suites (if applicable)
├── .gitignore # Git ignore patterns
├── CLAUDE.md # Claude-specific instructions
├── README.md # Project overview
├── package.json # Node.js dependencies
└── LICENSE # License file
Agent Definitions (.claude/agents/):
- Format:
[agent-name].md - Use kebab-case:
code-reviewer.md,docs-maintainer.md - Descriptive, role-based names
- Examples:
planner.md,tester.md,git-operator.md
Skills (.claude/skills/):
- Format:
[skill-name]/SKILL.md - Use kebab-case for directory names
- Main file always named
SKILL.md - Supporting files in
references/orscripts/ - Examples:
brainstorm/SKILL.mdui-styling/SKILL.mdmcp/SKILL.md
Documentation (docs/):
- Format:
[document-purpose].md - Use kebab-case with descriptive names
- Examples:
project-overview-pdr.mdcodebase-summary.mdcode-standards.mdsystem-architecture.md
Reports (plans/<plan-name>/reports/):
- Format:
{date}-from-[agent]-to-[agent]-[task]-report.md - Use date prefix for chronological sorting (format from
$RIG_PLAN_DATE_FORMAT) - Clear source and destination agents
- Examples:
251026-from-planner-to-main-auth-implementation-report.md251026-from-tester-to-debugger-test-failures-report.md
Plans (plans/):
- Format:
{date}-[feature-name]-plan.md - Use date prefix for version tracking (format from
$RIG_PLAN_DATE_FORMAT) - Descriptive feature names in kebab-case
- Examples:
251026-user-authentication-plan.md251026-database-migration-plan.md
Research Reports (plans/<plan-name>/research/):
- Format:
{date}-[research-topic].md - Date prefix for tracking (format from
$RIG_PLAN_DATE_FORMAT) - Clear topic description
- Examples:
251026-oauth2-implementation-strategies.md251026-performance-optimization-techniques.md
- Maximum file size: 500 lines of code
- Files exceeding 500 lines MUST be refactored
- Exception: Auto-generated files (with clear marking)
When file exceeds 500 lines:
- Extract Utility Functions: Move to separate
utils/directory - Component Splitting: Break into smaller, focused components
- Service Classes: Extract business logic to dedicated services
- Module Organization: Group related functionality into modules
Example Refactoring:
Before:
user-service.js (750 lines)
After:
services/
├── user-service.js (200 lines) # Core service
├── user-validation.js (150 lines) # Validation logic
└── user-repository.js (180 lines) # Database operations
utils/
└── password-hasher.js (80 lines) # Utility functions
JavaScript/TypeScript:
-
Variables: camelCase
const userName = 'John Doe'; const isAuthenticated = true;
-
Functions: camelCase
function calculateTotal(items) { } const getUserById = (id) => { };
-
Classes: PascalCase
class UserService { } class AuthenticationManager { }
-
Constants: UPPER_SNAKE_CASE
const MAX_RETRY_COUNT = 3; const API_BASE_URL = 'https://api.example.com';
-
Private Members: Prefix with underscore
class Database { _connectionPool = null; _connect() { } }
Source Files:
-
JavaScript/TypeScript: kebab-case
user-service.js authentication-manager.ts api-client.js -
React Components: PascalCase
UserProfile.jsx AuthenticationForm.tsx NavigationBar.jsx -
Test Files: Match source file name +
.testor.specuser-service.test.js authentication-manager.spec.ts
Directories: kebab-case
src/
├── components/
├── services/
├── utils/
├── api-clients/
└── test-helpers/
REST Endpoints:
- Use kebab-case for URLs
- Plural nouns for collections
- Resource IDs in path parameters
GET /api/users
GET /api/users/:id
POST /api/users
PUT /api/users/:id
DELETE /api/users/:id
GET /api/users/:userId/posts
Request/Response Fields:
- Use camelCase for JSON properties
{
"userId": 123,
"userName": "john_doe",
"emailAddress": "john@example.com",
"isVerified": true,
"createdAt": "2025-10-26T00:00:00Z"
}Indentation:
- Use 2 spaces (not tabs)
- Consistent indentation throughout file
- No trailing whitespace
Line Length:
- Preferred: 80-100 characters
- Hard limit: 120 characters
- Break long lines logically
Whitespace:
- One blank line between functions/methods
- Two blank lines between classes
- Space after keywords:
if (,for (,while ( - No space before function parentheses:
function name(
File Headers (Optional but recommended):
/**
* User Service
*
* Handles user authentication, registration, and profile management.
*
* @module services/user-service
* @author Rig
* @version 1.0.0
*/Function Documentation:
/**
* Authenticates a user with email and password
*
* @param {string} email - User's email address
* @param {string} password - User's password
* @returns {Promise<User>} Authenticated user object
* @throws {AuthenticationError} If credentials are invalid
*/
async function authenticateUser(email, password) {
// Implementation
}Inline Comments:
- Explain WHY, not WHAT
- Complex logic requires explanation
- TODO comments include assignee and date
// TODO(john, 2025-10-26): Optimize this query for large datasets
const users = await db.query('SELECT * FROM users');
// Cache miss - fetch from database
const user = await fetchUserFromDB(userId);Always Use Try-Catch:
async function processPayment(orderId) {
try {
const order = await getOrder(orderId);
const payment = await chargeCard(order.total);
await updateOrderStatus(orderId, 'paid');
return payment;
} catch (error) {
logger.error('Payment processing failed', { orderId, error });
throw new PaymentError('Failed to process payment', { cause: error });
}
}Error Types:
- Create custom error classes for domain errors
- Include context and cause
- Provide actionable error messages
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}Error Logging:
- Log errors with context
- Use appropriate log levels
- Never expose sensitive data in logs
logger.error('Database query failed', {
query: sanitizeQuery(query),
params: sanitizeParams(params),
error: error.message
});Validate All Inputs:
function createUser(userData) {
// Validate required fields
if (!userData.email || !userData.password) {
throw new ValidationError('Email and password required');
}
// Sanitize inputs
const email = sanitizeEmail(userData.email);
const password = userData.password; // Never log passwords
// Validate formats
if (!isValidEmail(email)) {
throw new ValidationError('Invalid email format');
}
if (password.length < 8) {
throw new ValidationError('Password must be at least 8 characters');
}
}Never Commit Secrets:
- Use environment variables for API keys, credentials
- Add
.env*to.gitignore - Use secret management systems in production
Never Log Sensitive Data:
// BAD
logger.info('User login', { email, password }); // Never log passwords
// GOOD
logger.info('User login', { email }); // OK to log emailSanitize Database Queries:
// Use parameterized queries
const user = await db.query(
'SELECT * FROM users WHERE email = $1',
[email]
);
// Never concatenate user input
// BAD: const user = await db.query(`SELECT * FROM users WHERE email = '${email}'`);tests/
├── unit/ # Unit tests
│ ├── services/
│ └── utils/
├── integration/ # Integration tests
│ └── api/
├── e2e/ # End-to-end tests
└── fixtures/ # Test data
describe('UserService', () => {
describe('authenticateUser', () => {
it('should return user when credentials are valid', async () => {
// Test implementation
});
it('should throw AuthenticationError when password is incorrect', async () => {
// Test implementation
});
it('should throw ValidationError when email is missing', async () => {
// Test implementation
});
});
});- Unit tests: > 80% code coverage
- Integration tests: Critical user flows
- E2E tests: Happy paths and edge cases
- Error scenarios: All error paths tested
- Arrange-Act-Assert pattern
- Independent tests (no test dependencies)
- Descriptive test names (behavior, not implementation)
- Test one thing per test
- Use fixtures for complex test data
- Mock external dependencies
Format: Conventional Commits
type(scope): description
[optional body]
[optional footer]
Types:
feat: New feature (minor version bump)fix: Bug fix (patch version bump)docs: Documentation changesrefactor: Code refactoringtest: Test additions/changesci: CI/CD changeschore: Maintenance tasksperf: Performance improvementsstyle: Code style changes
Examples:
feat(auth): add OAuth2 authentication support
Implements OAuth2 flow with Google and GitHub providers.
Includes token refresh and revocation.
Closes #123
---
fix(api): resolve timeout in database queries
Optimized slow queries and added connection pooling.
---
docs: update installation guide with Docker setup
Rules:
- Subject line: imperative mood, lowercase, no period
- Max 72 characters for subject
- Blank line between subject and body
- Body: explain WHY, not WHAT
- Footer: reference issues, breaking changes
- No AI attribution or signatures
Format: type/description
Types:
feature/- New featuresfix/- Bug fixesrefactor/- Code refactoringdocs/- Documentation updatestest/- Test improvements
Examples:
feature/oauth-authentication
fix/database-connection-timeout
refactor/user-service-cleanup
docs/api-reference-update
test/integration-test-suite
- ✅ No secrets or credentials
- ✅ No debug code or console.logs
- ✅ All tests pass locally
- ✅ Code follows style guidelines
- ✅ No linting errors
- ✅ Files under 500 lines
- ✅ Conventional commit message
Self-Documenting Code:
- Clear variable and function names
- Logical code organization
- Minimal comments needed
When to Comment:
- Complex algorithms or business logic
- Non-obvious optimizations
- Workarounds for bugs/limitations
- Public API functions
- Configuration options
Layout (Diataxis): every page in docs/ has one primary type and lives in its dir: tutorials/ (learning), how-to/ (tasks), reference/ (facts), explanation/ (why); PDR/roadmap/changelog go in project/. Index: docs/README.md. Full rules: .claude/skills/docs/references/diataxis-docs-layout.md.
Writing: docs-maintainer loads the diataxis-writer skill; mixed pages are split, not merged. Keep each file under docs.maxLoc (800).
Formatting:
- Use ATX-style headers (
#,##,###) - Code blocks with language specification
- Tables for structured data
- Lists for sequential items
- Relative links for cross-references
Agent, command, skill, hook, and configuration file rules: Agent, Skill & Hook Authoring Standards.
Optimization Priorities:
- Correctness first
- Readability second
- Performance third (when needed)
Common Optimizations:
- Use appropriate data structures
- Avoid unnecessary loops
- Cache expensive computations
- Lazy load when possible
- Debounce/throttle frequent operations
Example:
// Cache expensive operations
const memoize = (fn) => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn(...args);
cache.set(key, result);
return result;
};
};
const expensiveCalculation = memoize((n) => {
// Complex calculation
return result;
});- Use async operations
- Stream large files
- Batch writes when possible
- Clean up file handles
Functionality:
- ✅ Implements required features
- ✅ Handles edge cases
- ✅ Error handling complete
- ✅ Input validation present
Code Quality:
- ✅ Follows naming conventions
- ✅ Adheres to file size limits
- ✅ DRY principle applied
- ✅ KISS principle followed
- ✅ Well-structured and organized
Security:
- ✅ No hardcoded secrets
- ✅ Input sanitization
- ✅ Proper authentication/authorization
- ✅ Secure dependencies
Testing:
- ✅ Unit tests included
- ✅ Integration tests for flows
- ✅ Edge cases tested
- ✅ Error paths covered
Documentation:
- ✅ Code comments where needed
- ✅ API documentation updated
- ✅ README updated if needed
- ✅ Changelog entry added
Pre-Commit:
- Secret scanning
- File size validation
Pre-Push:
- Linting (ESLint, Prettier)
- Unit tests
- Type checking
CI/CD:
- All tests
- Build verification
- Coverage reports
- Security scans
Code Review Focus:
- Architecture and design decisions
- Complex logic correctness
- Security implications
- Performance considerations
- Maintainability and readability
When to Deviate:
- Performance-critical code (document reasons)
- External library constraints
- Generated code (mark clearly)
- Legacy code (plan refactoring)
Documentation Required:
/**
* EXCEPTION: File exceeds 500 lines
* REASON: Critical performance optimization requires monolithic structure
* TODO: Refactor when performance is no longer critical
* DATE: 2025-10-26
*/None. All code standards are well-defined and documented.