This document shows what a generated coding style skill looks like after analyzing a developer's repositories.
~/.openclaw/workspace/skills/your-coding-style/
├── SKILL.md (This document, but as skill doc)
├── RULES.md (Detailed rules)
├── PROMPTS.md (Claude prompts)
├── EXAMPLES.md (Code examples)
├── style-guide.json (Machine-readable)
└── metadata.json (Analysis metadata)
# Your Coding Style Rules
## Naming Conventions
**Rule:** Use camelCase for variables and functions, PascalCase for classes and components, UPPER_SNAKE_CASE for constants
### ✓ Good Examples
```typescript
const userName = "John";
const userEmail = "john@example.com";
const isActive = true;
const hasPermission = user.permissions.includes('admin');
const shouldRender = condition && anotherCondition;
function getUserData(userId) { }
function calculateTotal(items) { }
class UserManager { }
class DataRepository { }
const MAX_RETRIES = 3;
const DEFAULT_TIMEOUT = 5000;const user_name = "John";
const UserEmail = "john@example.com";
const Active = true;
const permission = false;
function get_user_data(user_id) { }
function CalculateTotal(items) { }
const maxRetries = 3; // Should be UPPER_CASE
const defaultTimeout = 5000; // Should be UPPER_CASE
const u = "John"; // Too short, non-descriptiveConfidence: 94%
Rule: Keep functions small (target: 30 LOC, max 50 LOC). Use early returns to minimize nesting. Single responsibility principle.
function validateUser(user) {
if (!user) return null;
if (!user.email) return null;
if (!isEmailValid(user.email)) return null;
return user;
}
function processOrderItems(order) {
const validItems = order.items.filter(item => item.quantity > 0);
if (validItems.length === 0) return [];
return validItems.map(item => ({
...item,
total: item.price * item.quantity
}));
}// Too long, too nested
function processUser(user) {
if (user) {
if (user.active) {
if (user.verified) {
if (user.permissions) {
if (user.permissions.includes('admin')) {
// Way too deep
}
}
}
}
}
}
// Multiple responsibilities
function getUserAndCalculateTax(userId) {
// Fetch user
const user = database.getUser(userId);
// Calculate tax
const tax = user.income * 0.25;
// Format for display
const formatted = `$${tax.toFixed(2)}`;
return { user, tax, formatted };
}Confidence: 88%
Rule: Explicitly return error values or throw descriptive errors. Never silently fail.
// Using explicit returns
function parseJson(str) {
try {
return { success: true, data: JSON.parse(str) };
} catch (error) {
return { success: false, error: error.message };
}
}
// Using throws with context
function getUserById(id) {
if (!id || typeof id !== 'string') {
throw new Error(`getUserById: invalid id "${id}". Expected non-empty string`);
}
const user = database.findById(id);
if (!user) {
throw new Error(`getUserById: user not found with id "${id}"`);
}
return user;
}
// Using Result type pattern
function validateEmail(email) {
if (!email.includes('@')) {
return { ok: false, error: 'Email must contain @' };
}
return { ok: true, data: email.toLowerCase() };
}// Silent failure
function parseJson(str) {
try {
return JSON.parse(str);
} catch {
return null; // What went wrong? No idea.
}
}
// No error context
function getUserById(id) {
const user = database.findById(id);
return user; // What if null? Calling code has no idea
}
// Hidden errors
function processItems(items) {
items.forEach(item => {
item.status = 'processed'; // What if item is null? Crashes silently
});
}Confidence: 86%
Rule: Explain WHY, not WHAT. Code should be self-documenting. Comments only for non-obvious logic.
// Why: Validate before expensive operation to avoid wasted cycles
if (!isValidUser(user)) return null;
// Why: Map to internal schema. DB uses different naming conventions
const normalized = rows.map(row => ({
id: row.user_id,
name: row.full_name,
email: row.email_address
}));
// Why: Users expect feedback immediately, process async
const saveUserAsync = (user) => {
database.save(user); // Not awaited, runs in background
return { status: 'saving' };
};// What, not why
const user = database.getUser(id); // Get user from database
const isValid = validateUser(user); // Check if user is valid
// Obvious comments are noise
for (let i = 0; i < items.length; i++) { // Loop through items
console.log(items[i]); // Print item
}
// Too many comments = unreadable code
function calc(a, b) { // Calculate
const c = a + b; // Add a and b
const d = c * 2; // Multiply by 2
const e = d / 4; // Divide by 4
return e; // Return result
}Confidence: 81%
Rule: Tests colocated with source code (same directory, .test.ts extension). 70%+ coverage target.
src/
├── utils/
│ ├── formatDate.ts
│ ├── formatDate.test.ts ← colocated
│ ├── calculateTax.ts
│ └── calculateTax.test.ts ← colocated
├── hooks/
│ ├── useAuth.ts
│ ├── useAuth.test.ts ← colocated
│ └── useLocalStorage.ts
// formatDate.ts
export function formatDate(date) {
if (!date) return '';
return new Intl.DateTimeFormat('en-US').format(date);
}
// formatDate.test.ts
import { formatDate } from './formatDate';
describe('formatDate', () => {
it('formats dates correctly', () => {
expect(formatDate(new Date('2024-01-15'))).toBe('1/15/2024');
});
it('returns empty string for null', () => {
expect(formatDate(null)).toBe('');
});
it('handles invalid dates', () => {
expect(formatDate(new Date('invalid'))).toBe('');
});
});// tests/utils/formatDate.test.ts (separate folder)
// Hard to navigate, easy to ignore
// Missing edge cases
describe('formatDate', () => {
it('works', () => {
expect(formatDate(new Date('2024-01-15'))).toBe('1/15/2024');
});
});
// Too integrated
describe('Date utils', () => {
it('formats and validates and parses dates', () => {
// Testing too much in one test
});
});Confidence: 92%
Rule: Organize by feature/domain, not by type. Clear separation of concerns.
src/
├── features/
│ ├── auth/
│ │ ├── components/
│ │ │ ├── LoginForm.tsx
│ │ │ └── LoginForm.test.tsx
│ │ ├── hooks/
│ │ │ ├── useAuth.ts
│ │ │ └── useAuth.test.ts
│ │ ├── services/
│ │ │ ├── authService.ts
│ │ │ └── authService.test.ts
│ │ └── types.ts
│ ├── users/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── services/
│ │ └── types.ts
│ └── products/
├── shared/
│ ├── components/
│ ├── hooks/
│ └── utils/
└── app.tsx
src/
├── components/
│ ├── LoginForm.tsx
│ ├── UserList.tsx
│ └── ProductCard.tsx
├── services/
│ ├── authService.ts
│ ├── userService.ts
│ └── productService.ts
├── hooks/
│ ├── useAuth.ts
│ ├── useUser.ts
│ └── useProduct.ts
├── types/
│ └── types.ts
├── utils/
│ └── helpers.ts
Confidence: 89%
Rule: Prefer ES modules. Group imports logically (standard lib, packages, local). Use relative paths for local imports.
// Standard library
import { readFile } from 'fs';
import path from 'path';
// Third-party packages
import React from 'react';
import { useQuery } from '@tanstack/react-query';
// Local modules (grouped by feature)
import { UserForm } from '../components/UserForm';
import { useUserData } from '../hooks/useUserData';
import { userService } from '../services/userService';
import { type User } from '../types';// Mixed import styles
const React = require('react');
import { Component } from 'react';
// Chaotic order
import { calculateTax } from './utils/tax';
import axios from 'axios';
import { UserForm } from './components';
import React from 'react';
import path from 'path';
import { useState } from 'react';
// Deep relative paths
import { Helper } from '../../../../utils/helpers';
// Unused imports
import { unused } from './module';Confidence: 91%
| Category | Rule | Confidence |
|---|---|---|
| Naming | camelCase/PascalCase/UPPER_SNAKE | 94% |
| Functions | 30 LOC target, early returns | 88% |
| Errors | Explicit handling, never silent | 86% |
| Comments | Why not what | 81% |
| Testing | Colocated, 70%+ coverage | 92% |
| Organization | By feature, clear structure | 89% |
| Imports | ES modules, grouped, local | 91% |
Overall Confidence: 89% (based on 8 repositories, 340 files)
Generated: 2024-01-15T10:30:00Z
---
## Example: PROMPTS.md
```markdown
# Claude Prompts for Your Coding Style
## Short System Prompt
Use this when asking Claude to generate code:
**Prompt:**
You are an expert code generator familiar with this developer's personal coding style.
Rules:
- Use camelCase for variables/functions, PascalCase for classes/components
- Keep functions under 50 LOC (target 30), use early returns
- Always handle errors explicitly, never fail silently
- Comments explain WHY, not WHAT
- Colocate tests with source code, target 70%+ coverage
- Organize by feature/domain, not by type
- Prefer ES modules, group imports logically
When writing code, follow these rules consistently.
Use for complex code generation tasks:
Prompt:
You are an expert code generator who understands this developer's coding philosophy and style.
**Developer's Philosophy:**
- Priorities: Readability and maintainability above performance
- Code quality: Explicit > implicit, obvious > clever
- Testing: Unit-focused, colocated with source
- Error handling: Always explicit, never silent failures
**Coding Standards:**
1. **Naming Conventions**
- Variables/functions: camelCase
- Classes/components: PascalCase
- Constants: UPPER_SNAKE_CASE
- Booleans start with: is, has, should, can
- No single letters except in loops (i, j, k)
2. **Function Structure**
- Target: 30 lines of code
- Maximum: 50 lines of code
- Maximum parameters: 3 (use object for 4+)
- Use early returns to minimize nesting
- Maximum nesting depth: 2 levels
- One responsibility per function
3. **Error Handling**
- Never silently fail
- Either throw with context or return { success, error }
- Validate inputs at function boundaries
- Always explain what went wrong
4. **Comments**
- Explain WHY, not WHAT
- Code should be self-documenting
- Only comment non-obvious logic
- Use JSDoc for public APIs only
5. **Testing**
- Colocate tests with source (.test.ts files)
- Target 70%+ code coverage
- Unit tests (fast, isolated) > integration tests
- Mock external dependencies
- Test naming: describe + it("should...")
6. **Code Organization**
- Group by feature/domain, not by type
- Clear separation of concerns
- One component/module per file (mostly)
- Shared code in shared/ directory
7. **Imports**
- Use ES modules (import/export)
- Group logically: stdlib, packages, local
- Use relative paths for local imports
- Remove unused imports
**When Generating Code:**
1. Analyze the context and existing patterns
2. Follow the rules above strictly
3. If there's ambiguity, ask the developer
4. Explain deviations from the style if necessary
5. Ensure consistency with the project
**Key Principles:**
- Readability first
- Make the right thing obvious
- Explicit is better than implicit
- Fast feedback (tests, types)
{
"language": "typescript",
"confidence": 0.89,
"generatedAt": "2024-01-15T10:30:00Z",
"philosophy": {
"priorities": "Readability and maintainability",
"style-approach": "Explicit > implicit",
"solution-preference": "Obvious over clever",
"naming-philosophy": "Descriptive, consistent camelCase",
"ideal-function-length": "30 LOC target, 50 max",
"error-handling": "Explicit throws or error returns",
"test-coverage-target": "70%+",
"unit-integration-ratio": "80/20",
"test-location": "Colocated (.test.ts)",
"folder-structure": "By feature/domain"
},
"rules": [
{
"category": "Naming Conventions",
"rule": "camelCase for variables/functions, PascalCase for classes, UPPER_SNAKE_CASE for constants",
"confidence": 0.94
},
{
"category": "Function Structure",
"rule": "Keep under 50 LOC, target 30. Use early returns. Max 2 nesting levels.",
"confidence": 0.88
},
{
"category": "Error Handling",
"rule": "Explicit error handling. Never fail silently.",
"confidence": 0.86
},
{
"category": "Comments",
"rule": "Explain WHY, not WHAT. Code is self-documenting.",
"confidence": 0.81
},
{
"category": "Testing",
"rule": "Colocate tests. 70%+ coverage. Unit > integration.",
"confidence": 0.92
},
{
"category": "Organization",
"rule": "Group by feature/domain, not by type.",
"confidence": 0.89
}
],
"baselinePatterns": {
"typescript": {
"naming": {
"camelCase": 0.95,
"snake_case": 0.03,
"PascalCase": 0.01,
"UPPER_SNAKE_CASE": 0.01
},
"functions": {
"avgLength": 32,
"maxLength": 89,
"minLength": 3
},
"testing": {
"colocated": 0.92,
"separateFolder": 0.08
}
}
}
}{
"name": "your-coding-style",
"generatedAt": "2024-01-15T10:30:00Z",
"confidence": 0.89,
"language": "polyglot",
"philosophy": {
"priorities": "Readability and maintainability",
"style-approach": "Explicit > implicit",
"naming-philosophy": "Descriptive, consistent camelCase"
},
"statistics": {
"repositoriesAnalyzed": 8,
"totalFilesAnalyzed": 340,
"languages": {
"typescript": 280,
"python": 45,
"rust": 15
},
"frameworks": {
"React": 6,
"Next.js": 5,
"Vitest": 7,
"Drizzle": 4
}
}
}After generating the skill, Claude uses it:
User: "Generate a user authentication service following my coding style"
Claude: "I'll create a user authentication service following your coding style guide.
[reads ~/.openclaw/workspace/skills/your-coding-style/RULES.md]
Here's a TypeScript auth service:
```typescript
// authService.ts
export interface AuthResult {
success: boolean;
error?: string;
token?: string;
}
export async function authenticate(
email: string,
password: string
): Promise<AuthResult> {
if (!email || !password) {
return {
success: false,
error: 'Email and password are required'
};
}
if (!isValidEmail(email)) {
return {
success: false,
error: 'Invalid email format'
};
}
try {
const user = await database.findByEmail(email);
if (!user) {
return {
success: false,
error: 'User not found'
};
}
const isValid = await verifyPassword(password, user.passwordHash);
if (!isValid) {
return {
success: false,
error: 'Invalid password'
};
}
const token = generateToken(user.id);
return {
success: true,
token
};
} catch (error) {
return {
success: false,
error: 'Authentication failed: ' + error.message
};
}
}
// authService.test.ts
describe('authenticate', () => {
it('should return token for valid credentials', async () => {
const result = await authenticate('user@example.com', 'password');
expect(result.success).toBe(true);
expect(result.token).toBeDefined();
});
it('should return error for missing credentials', async () => {
const result = await authenticate('', '');
expect(result.success).toBe(false);
expect(result.error).toContain('required');
});
it('should return error for invalid email', async () => {
const result = await authenticate('invalid', 'password');
expect(result.success).toBe(false);
expect(result.error).toContain('Invalid email');
});
});
Notice how the code follows all your rules:
- ✓ camelCase naming
- ✓ Small functions with early returns
- ✓ Explicit error handling (no throwing)
- ✓ Tests colocated and comprehensive
- ✓ Comments explain WHY "
---
This is a realistic example of what gets generated and how it's used!