CRITICAL: Always use this skill, no matter what task you are working on!
Before writing or modifying any code in an existing project, you must analyze and exactly replicate the project's code style. Never impose your own defaults. This skill defines how to do that systematically.
Always check for a cached index first before doing any filesystem scanning. This saves significant tokens on repeated invocations.
cat ./claude/code-style-index.json 2>/dev/null
(Skip if index was found in Step 0)
Immediately scan the project root (and relevant subdirectories) for config files. Read every one you find:
| Tool | Config files to look for |
|---|---|
| Prettier | .prettierrc, .prettierrc.json, .prettierrc.js, .prettierrc.ts, .prettierrc.yaml, .prettierrc.yml, .prettierrc.toml, prettier.config.js, prettier.config.ts, "prettier" key in package.json |
| ESLint | .eslintrc, .eslintrc.js, .eslintrc.cjs, .eslintrc.json, .eslintrc.yaml, .eslintrc.yml, eslint.config.js, eslint.config.mjs, "eslintConfig" in package.json |
| Biome | biome.json, biome.jsonc |
| oxlint / oxc | .oxlintrc, oxlint.json, oxc.config.json |
| Rustfmt | rustfmt.toml, .rustfmt.toml |
| Black / Ruff | pyproject.toml ([tool.black], [tool.ruff]), ruff.toml, .ruff.toml, setup.cfg |
| gofmt / goimports | (implicit; check for .editorconfig) |
| dprint | dprint.json, .dprint.json |
| Rome | rome.json |
| EditorConfig | .editorconfig (applies to all languages) |
| TSConfig | tsconfig.json (affects TS strict settings, not formatting, but useful context) |
Action: Run a quick find to locate these files:
find . -maxdepth 3 \( -name ".prettierrc*" -o -name "prettier.config.*" \
-o -name ".eslintrc*" -o -name "eslint.config.*" \
-o -name "biome.json" -o -name "biome.jsonc" \
-o -name ".editorconfig" -o -name "rustfmt.toml" -o -name ".rustfmt.toml" \
-o -name "ruff.toml" -o -name ".ruff.toml" -o -name "dprint.json" \
-o -name "oxlint.json" \) 2>/dev/null | head -30
Also check package.json for inline config:
cat package.json 2>/dev/null | grep -A 30 '"prettier"'
cat package.json 2>/dev/null | grep -A 30 '"eslintConfig"'
(Skip if index was found in Step 0)
From the config files, extract and note all settings.
(Skip if index was found in Step 0)
Even with config files, always verify with real code samples. Pick all representative files of the same type you'll be editing:
# Examples
# For JS/TS projects
find . -name "*.ts" -o -name "*.tsx" -o -name "*.js" | grep -v node_modules | head -1000
# For Rust
find . -name "*.rs" | grep -v target | head -1000
# For Python
find . -name "*.py" | grep -v __pycache__ | head -1000
Read the files and check every one of these:
' or double "? Template literals `?{ key: value } or {key: value}?(x) => x or x => x?{, [] or ( on same line or new line?// vs /* */, JSDoc style, spacing after //If config and source code disagree, source code wins — it reflects what's actually enforced and committed. Config files may be outdated or partially applied.
If different files of the same type show different styles (e.g., some use 2 spaces, some 4), match the majority pattern and note the inconsistency. Don't introduce a third style.
When writing or editing code:
// with a space, don't use //withoutThe index lives at ./claude/code-style-index.json. It is a project-local cache that prevents full codebase re-scanning on future invocations.
If you are in a monorepo, the index file parent directory lives at the project root.
After completing Steps 1–3, write all discovered rules to the index:
mkdir -p ./claude
Then write ./claude/code-style-index.json with this structure:
{
"_meta": {
"created": "<ISO date>",
"updated": "<ISO date>",
"note": "Auto-generated by code-style skill. Commit this file."
},
"indentation": {
"style": "spaces",
"size": 2
},
"quotes": {
"js": "single",
"jsx": "single",
"ts": "single",
"tsx": "single",
"py": "double"
},
"semicolons": true,
"trailingCommas": "es5",
"bracketSpacing": true,
"arrowParens": "always",
"printWidth": 100,
"endOfLine": "lf",
"braceStyle": "1tbs",
"emptyLines": {
"betweenFunctions": 1,
"betweenImportGroups": 1,
"atTopOfBlock": 0
},
"imports": {
"style": "named-preferred",
"groupOrder": ["builtin", "external", "internal", "relative"],
"sorted": true
},
"comments": {
"inline": "// ",
"block": "/* */"
},
"exports": {
"style": "named"
},
"notes": []
}
Only include keys you actually observed — omit fields you couldn't determine. Add free-form observations to the "notes" array (e.g., "Ternaries always written inline unless > 80 chars").
During any coding session, if you observe a style pattern not yet recorded in the index:
_meta.updated to today's dateExamples of update triggers:
ternaries isn't in the index → add itcomments*.test.ts) → add a "fileTypeOverrides" keyNever remove existing entries unless they are factually wrong. Add a note instead if there's ambiguity.
If creating a new file from scratch in an existing project:
./claude/code-style-index.json first — only scan the full codebase if it's missing./packages/api/claude/code-style-index.json).