code-style
Skill0 starsChanged 2 months agoMITView on GitHub
Bootstrap deterministic formatter/linter config for JS/TS, Go, or Python, and apply beyond-linting JS/TS conventions: get/find/list retrieval naming, Make… factory DI, and backend module/folder structure. Use when setting up a repo, standardizing style, naming accessors, writing injectable units, organizing src/modules, or scaffolding CONTRIBUTING/AGENTS guidance.
- Reads credentials
- Installs packages
20 other projects use a version of this.
Adopted by
Most recently taken up by
- JetBrains/intellij-communitytheir own version, first seen Nov 7, 2026
- JetBrains/MPStheir own version, first seen Nov 3, 2026
- 851-labs/codevisortheir own version, first seen Nov 1, 2026
- facebook/docusaurustheir own version, first seen Oct 17, 2026
- vainjs/skillstheir own version, first seen Oct 15, 2026
- lancegui/causal-powerstheir own version, first seen Oct 13, 2026
Used with
Projects with it also use ssr, actions and 4 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
JetBrainsSkillssr
Guide for using Structural Search and Replace in IntelliJ. Use when creating or modifying SSR inspections or search patterns.
Also in 3 projects that use this
JetBrainsSkillactions
Guidelines for implementing IntelliJ actions (AnAction). Use those rules when you need to create or change an action in the intellij platform.
Also in 3 projects that use this
BlockSkilldebugging
Debugging guidelines and best practices
Also in 3 projects that use this
NVIDIASkilltesting
Run Python and Rust tests for physicsnemo-curator using uv + pytest with coverage reporting via pytest-cov, and cargo-nextest for Rust tests. Includes benchmark workflows with pytest-benchmark and criterion.
Also in 4 projects that use this
- +2 more from JetBrains
Other versions20 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 20
- facebook/docusaurus★ 67ksame name
- JetBrains/intellij-community★ 21ksame name
- DetachHead/rebased★ 6.5ksame name
- latitude-dev/latitude-llm★ 4.7ksame name
- Pixeval/Pixeval★ 3.2ksame name
- JetBrains/MPS★ 1.7ksame name
- microsoft/semantic-link-labs★ 594same name
- Automattic/wordpress-activitypub★ 583same name
- meleantonio/ChernyCode★ 516same name
- RailtownAI/railtracks★ 235same name
10 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
Show its rules and text
We split this skill into the rules it gives an agent
36 rules. 0 are common, 21 are distinctive, and 15 are very specific to this project.
0
Common
Most of the 16 edited versions we read keep these.
21
Distinctive
This author's own choices. Worth a look.
15
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 22
When scaffolding a repo, do both: emit tool configs and put the conventions in CONTRIBUTING.md with a pointer from AGENTS.md.
- Distinctive: line 82
When invoked for bootstrap, perform these steps:
- Distinctive: line 86
Check for language markers:
- Distinctive: line 123
After emitting files, tell the user what dependencies to install:
- Very specific: line 143
Follow Part C so CONTRIBUTING.md and AGENTS.md include the beyond-linting conventions.
- Distinctive: line 147
If the directory is a git repo:
- Very specific: line 150
Commit with message: chore: add code style config for JS/TS, Go, Python (list only detected languages)
- Distinctive: line 153
If not a git repo, warn: "Not a git repo.
- Distinctive: line 157
Run a quick check to confirm tools work:
- Distinctive: line 180
Use these verbs so callers can trust return types without reading the body.
- Distinctive: line 197
Must return the asked-for value — never null, undefined, Option/Maybe, or other absence.
- Very specific: line 215
JavaScript / TypeScript: prefer null for not-found.
- Distinctive: line 225
Always return a collection.
- Very specific: line 236
Prefer get / find / list. Avoid fetch / load / resolve unless the domain strongly needs that word and it is clearer than get/find/list.
- Very specific: line 240
Must exist → getX… → non-nullable.
- Very specific: line 247
Prefer dependency injection so units stay maintainable and testable.
- Distinctive: line 261
Keep pure domain logic and local values inside the returned function (or as pure helpers).
- Distinctive: line 353
Prefer one module per real domain boundary (own routes and/or data).
- Distinctive: line 399
Put in the module: when it belongs to that domain: that domain’s routes, queries, and response/request schemas.
- Distinctive: line 401
Put in shared locations: when multiple modules or the whole app need it:
- Very specific: line 411
Cross-module imports are allowed: when one domain genuinely depends on another module’s public API (prefer the module barrel).
- Distinctive: line 415
Nesting: Start shallow (role files at the module root).
- Distinctive: line 431
Keep handlers thin; put SQL / persistence in the module repository factories.
- Distinctive: line 432
Add a services layer only when the domain needs orchestration beyond thin routes → repository.
- Very specific: line 433
When a module grows, nest with subfolders.
- Very specific: line 436
Put tests under top-level test/, not inside src/modules/.
- Very specific: line 441
Create top-level src/routes/, src/repositories/, src/services/ that slice *across* all domains.
- Distinctive: line 442
Create modules for sprint tickets, feature flags, or temporary experiments — only for durable architecture parts.
- Very specific: line 443
Create a repository-only src/modules/… just to share a small helper — use src/lib/ instead.
- Distinctive: line 445
Put process env reads or raw DB client setup inside every module — inject via factories / composition root.
- Very specific: line 447
Prefer plural folder names for new modules (orders) when a singular domain noun fits (order).
- Distinctive: line 453
When using this skill to adopt or scaffold code-style guidance:
- Very specific: line 456
Ensure CONTRIBUTING.md exists (create it if missing).
- Very specific: line 457
Add all convention sections to CONTRIBUTING.md — retrieval naming, factory DI, and module structure (paste/adapt …
- Distinctive: line 458
Create or update AGENTS.md so agents are pointed at those CONTRIBUTING sections (paste/adapt templates/agents-mention.md).
- Distinctive: line 460
Do not leave the conventions only in a skill file or chat — they must live in-repo where humans and agents both find them.
“Common” is measured: kept by at least 6 in 10 of the 16 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Code Style
Two jobs in one skill:
- Formatter / linter bootstrap — detect languages and emit deterministic config files (ESLint, gofmt/golangci-lint, Ruff).
- Beyond-linting conventions (JS/TS) — retrieval naming (
get/find/list), factory DI (Make…), and backend module/folder structure.
When scaffolding a repo, do both: emit tool configs and put the conventions in CONTRIBUTING.md with a pointer from AGENTS.md.
Part A — Formatter and linter bootstrap
Bootstrap deterministic code style configuration. Detects languages in the repo and emits config files that standard tools consume to auto-fix code.
Supported Languages
| Language | Detection | Tools |
| JS/TS | tsconfig.json, package.json, .js, .ts, .jsx, .tsx | ESLint + @stylistic/eslint-plugin |
| Go | go.mod, .go | gofmt + golangci-lint |
| Python | pyproject.toml, requirements.txt, .py | Ruff |
What Gets Emitted
JS/TS
eslint.config.js— ESLint flat config with @stylistic ruleseslint-local-plugin.js— Custom rules (destructure-param-newline, padding).editorconfig— Tab width 8, charset utf-8.vscode/settings.json— Format-on-save, ESLint integration.vscode/extensions.json— Recommends ESLint extension
Go
.golangci.yml— Default linter set (errcheck, gosimple, govet, ineffassign, staticcheck, unused).editorconfig— Tab width 8 (display hint; gofmt uses tabs).vscode/settings.json— Format-on-save, golangci-lint integration.vscode/extensions.json— Recommends Go extension
Python
ruff.toml— Ruff formatter + linter config.editorconfig— 4-space indent (PEP8), charset utf-8.vscode/settings.json— Format-on-save, Ruff integration.vscode/extensions.json— Recommends Ruff extension
Style Rules
| Rule | JS/TS | Go | Python |
| Indentation | Tabs (8-space display) | Tabs (8-space display) | 4 spaces |
| Line width | 999 | gofmt default | 999 |
| Braces | Allman | gofmt default | N/A |
| Quotes | Double | N/A | Double |
| Semicolons | Always | N/A | N/A |
| Trailing commas | All | N/A | N/A |
Behavior
- Detect languages — Scan repo for language markers
- Emit config files — Copy templates for each detected language
- Overwrite existing — Replace any existing config (deterministic, no merge)
- Emit shared files —
.editorconfigand.vscode/settings - Scaffold conventions — Ensure
CONTRIBUTING.mdandAGENTS.mdcarry retrieval naming, factory DI, and module structure (see Part C) - Git commit — If in a git repo, auto-commit with
chore: add code style config for <languages> - Non-git warning — If not a git repo, warn and skip commit
Instructions (formatter / linter)
When invoked for bootstrap, perform these steps:
Step 1: Detect Languages
Check for language markers:
JS/TS: tsconfig.json OR package.json OR any .js/.ts/.jsx/.tsx file
Go: go.mod OR any .go file
Python: pyproject.toml OR requirements.txt OR any .py fileReport which languages were detected.
Step 2: Emit Config Files
For each detected language, read the corresponding templates from this skill's templates/ directory and write them to the repo root (or appropriate location).
JS/TS templates:
templates/js/eslint.config.js→eslint.config.jstemplates/js/eslint-local-plugin.js→eslint-local-plugin.jstemplates/js/editorconfig→.editorconfigtemplates/js/vscode-settings.json→.vscode/settings.jsontemplates/js/vscode-extensions.json→.vscode/extensions.json
Go templates:
templates/go/golangci.yml→.golangci.ymltemplates/go/editorconfig→.editorconfigtemplates/go/vscode-settings.json→.vscode/settings.jsontemplates/go/vscode-extensions.json→.vscode/extensions.json
Python templates:
templates/python/ruff.toml→ruff.tomltemplates/python/editorconfig→.editorconfigtemplates/python/vscode-settings.json→.vscode/settings.jsontemplates/python/vscode-extensions.json→.vscode/extensions.json
Multi-language repos: Merge .editorconfig sections and .vscode/ settings intelligently.
Step 3: Document Dependencies
After emitting files, tell the user what dependencies to install:
JS/TS:
npm install -D eslint @stylistic/eslint-plugin @babel/eslint-parser @babel/coreGo:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latestPython:
pip install ruff
# or: uv add --dev ruffStep 4: Scaffold conventions docs
Follow Part C so CONTRIBUTING.md and AGENTS.md include the beyond-linting conventions. Do this even when only formatter configs were requested, if those docs are missing the sections.
Step 5: Git Commit (if applicable)
If the directory is a git repo:
- Stage all changed/new config files (and CONTRIBUTING/AGENTS updates from Step 4)
- Commit with message:
chore: add code style config for JS/TS, Go, Python(list only detected languages) - Do NOT push
If not a git repo, warn: "Not a git repo. Skipping commit. Files have been written but are not version-controlled."
Step 6: Verify
Run a quick check to confirm tools work:
JS/TS: npx eslint --max-warnings 0 . (expect it to run, may report fixable issues)
Go: golangci-lint run (expect it to run)
Python: ruff check . (expect it to run)
Report success or any issues.
Part B — Code-style conventions (beyond linting)
Contract and structure rules that linters do not enforce: retrieval naming (get / find / list), factory DI (Make…), and backend module/folder structure. Primarily for JS/TS.
When to use these conventions
- Naming or reviewing functions that load one value or a collection
- Designing units that touch I/O, clocks, env, DB, or other side effects
- Laying out
src/modules/…for a new backend (TypeScript modular monolith or similar) - Adopting this guidance in a repo (see Part C)
Retrieval naming (get / find / list)
Use these verbs so callers can trust return types without reading the body.
Failures: throwing on hard errors (and on get when missing) is the accepted JS compromise here. Do not introduce Result/Either types for these contracts unless the repo already uses them.
Quick comparison
| Verb | Missing target | Return shape | Hard errors (DB down, bad input, auth, …) |
| get | Fail (throw / error) | Always the value — never null / undefined / Option | May throw |
| find | Soft-fail | Absent value (null, Option, etc.) | May throw |
| list | Empty collection | Always a bag/array — never null / Option | May throw |
Rule of thumb: “I have a User” → get. “I might have a User” → find. “Zero or more Users” → list.
get — definitely there
- Contract: the thing exists. Callers may assume a real value.
- Must return the asked-for value — never null, undefined, Option/Maybe, or other absence.
- If missing → throw.
function getUserById(id: string): User {
const user = db.users.get(id);
if (!user) throw new NotFoundError(`User ${id}`);
return user;
}
// Wrong — name promises a value but type allows absence
function getUserById(id: string): User | null { ... }find — maybe there
- Same lookup as
get, but missing is success with absence. - Soft-fail only for “not found.” Still throw on real failures.
- JavaScript / TypeScript: prefer
nullfor not-found; avoidundefined.
function findUserByEmail(email: string): User | null {
return db.users.findByEmail(email) ?? null;
}list — a bag of matches
- Always return a collection. No matches → empty bag (success).
- Never return null / Option for “nothing matched.”
function listUsersByRole(role: Role): User[] {
return db.users.filter({ role }); // [] if none
}Other retrieval verbs
Prefer get / find / list. Avoid fetch / load / resolve unless the domain strongly needs that word and it is clearer than get/find/list.
Retrieval checklist
- Must exist →
getX…→ non-nullable; throw if absent. - Optional →
findX…→ nullable / Option; JS/TS usenull. - Many →
listX…→ collection; empty OK; never null. - Hard failures stay hard for all three (throw).
Dependency injection (Make… factories)
Prefer dependency injection so units stay maintainable and testable. In JS/TS, use the factory pattern: a Make… function takes outside dependencies, does one-time setup, and returns the real function.
Purity goal (FP framing): not “no effects,” but effects only through injected capabilities. Make… is the impure shell (wire deps, run I/O); keep pure transforms as separate helpers when that clarifies the boundary.
Failures: throw on hard errors. That is intentional without a Result/Either library — do not push Result types for DI or retrieval.
What belongs in deps?
Pass into Make… only what comes from outside the pure unit. That is usually:
- Environment / config — values supplied at the composition root (env map, secrets, URLs, feature flags). Pass them in as normal deps; do not wrap env lookup in
MakeFindEnv/MakeGetEnv, and do not fall back to ambientprocess.envinside factories. - Side effects — capabilities that reach out (query/DB, HTTP, filesystem, email, queues).
- Non-determinism / time — clocks, “today”, random IDs. Inject them so tests can pin behavior.
Keep pure domain logic and local values inside the returned function (or as pure helpers). Do not inject plain local data that has no external or setup cost.
Factory shape and examples
Naming: prefix with Make + verb/domain only (MakeListParents, MakeIsExpired, MakeDb). Align the verb with get/find/list when the returned function is a retrieval. Do not use mk… for new code.
List + nested setup — deps in, setup nested factories, return the list function:
export function MakeDb(deps: { dbUrl: string }) {
return openDatabase(deps.dbUrl);
}
export function MakeListParents(deps: { dbUrl: string }) {
const db = MakeDb(deps); // setup / nested factory
return (email: string): Promise<Parent[]> =>
db.parents.where({ email }).toArray(); // [] if none
}Injected clock:
export function MakeIsExpired(deps: { now: () => Date }) {
return (expiresAt: Date) => expiresAt.getTime() < deps.now().getTime();
}
// Wrong — wall clock hidden inside
export function MakeIsExpired() {
return (expiresAt: Date) => expiresAt.getTime() < Date.now();
}Composition root — pass env/config in as deps (no Make-env helper); wire { dbUrl } into factories:
export function MakeApp(env: NodeJS.ProcessEnv) {
const dbUrl = env.DATABASE_URL;
if (!dbUrl) throw new Error("DATABASE_URL is required");
const deps = { dbUrl };
const listParents = MakeListParents(deps);
const isExpired = MakeIsExpired({ now: () => new Date() });
// mount routes that call listParents / isExpired
return app;
}
export function MakeTestApp() {
return MakeApp({
DATABASE_URL: "postgresql://user:pass@test.invalid/app",
});
}Composition
- Nested factories share the same deps bag; each pulls what it needs and builds children.
- Composition roots (app entry, route modules, tests) construct the deps bag and call factories once; request handlers call the returned functions.
Anti-patterns
// Wrong — ambient process.env / I/O buried inside the unit
async function listParents(email: string) {
const db = getDatabase(process.env.DATABASE_URL!);
return db.parents.where({ email }).toArray();
}
// Wrong — wall clock hardcoded instead of injected
export function MakeListDueToday(deps: { queryDueOn: (d: Date) => Promise<Item[]> }) {
return () => deps.queryDueOn(new Date());
}
// Wrong — module-level mutable client as an implicit global
let db: Database;
export function listParents(email: string) {
return db.parents.where({ email }).toArray();
}Module / folder structure (backends)
Scope: new backends (TypeScript modular monolith or similar). Do not apply src/modules/… domain folders inside frontend apps/*/src unless a separate frontend convention says so.
Organize application code by durable system components (domains), not by technical layer at the top of src/.
A module is a main part of the system architecture — stable over time — not a sprint ticket, weekly “feature,” or feature-flag slice. Think of an online shop: modules like order and billing (the domains the system is built from), not folders named after this week’s campaign or ticket.
- Domain folders live under
src/modules/<name>/. - Folder names are kebab-case singular domain nouns (e.g.
order,billing). Prefer singular for new modules even if an older repo used plurals historically. - Each module owns the pieces for that domain (HTTP surface, persistence, API schemas). Cross-cutting wiring and shared utilities stay outside modules.
- Prefer one module per real domain boundary (own routes and/or data). Do not create a new module for a short-lived work item. When a domain grows large, nest with subfolders inside that module.
Top-level layout (relative to modules)
Typical src/ shape:
| Area | Role |
src/modules/ | System domains / components (order, billing, …) |
src/lib/ | Shared app utilities & cross-cutting middleware |
src/db/ | Database client, migrations, seed, DB types |
src/env.ts | Environment access at the composition boundary |
src/app.ts | Composition root — mount middleware & module routes |
src/index.ts | Process entry (listen, shutdown) |
Repo root may also hold test/, infra/, docs/, tooling configs — those are not domain modules.
Inside a module
Files are named <name>.<role>.ts, matching the folder name (at the module root). Roles:
| Role | File | Responsibility |
| Routes | <name>.routes.ts | OpenAPI/HTTP route factories (Make…Routes); thin handlers that call repository (or service) factories |
| Repository | <name>.repository.ts | Data-access factories (MakeList…, Make…Query, etc.); domain row types often live here |
| Schemas | <name>.schemas.ts | Zod / OpenAPI request & response schemas for that module’s API |
| Services (optional) | e.g. <name>.service.ts or under a subfolder | Domain/orchestration between routes and repositories — add when needed, not by default |
Not every module needs every role.
- Routes + repository + schemas — typical API domain (e.g.
order,billing). - Routes + schemas, no repository — pure/status endpoints (e.g.
health). - Small helpers shared by several modules (no full HTTP domain of their own) →
src/lib/, not a dedicatedsrc/modules/…folder.
How pieces connect
- Composition root (
src/app.ts) builds shared deps (e.g.dbUrlfrom env) and mounts module routes (MakeOrderRoutes(args), …). - Routes factory constructs repository (and, when present, service) factories once, registers OpenAPI routes, and returns a sub-app.
- Repository factory takes injected deps, sets up DB (via shared
MakeDb), returns the callable used by handlers or services.
Default call path: routes → repository. A services layer may be added when needed for orchestration or non-trivial domain logic; do not invent it for every module.
Factories follow this skill’s DI naming (Make…). Retrieval verbs on repositories follow get / find / list.
Shared vs module-local
Put in the module when it belongs to that domain: that domain’s routes, queries, and response/request schemas; types only that module (or a tightly coupled sibling) needs.
Put in shared locations when multiple modules or the whole app need it:
| Kind | Where |
| Auth, logging, OpenAPI helpers, DI types, shared Zod primitives | src/lib/ |
| Small shared domain helpers used by multiple modules (no own HTTP surface) | src/lib/ |
| Env binding | src/env.ts (src root) |
| DB connection / migrations / generated DB types | src/db/ |
| App-wide middleware that may call a module | still src/lib/, importing the module |
Cross-module imports are allowed when one domain genuinely depends on another module’s public API (prefer the module barrel). For a small helper several modules need, put it in src/lib/ rather than inventing a module with no routes.
Nesting & barrels
- Nesting: Start shallow (role files at the module root). When a domain grows, prefer nested subfolders inside that module rather than flat sibling files only or premature split into new top-level modules.
- Barrels: Module
index.tsbarrels are good — use them as the public façade (and for nested subfolders when useful). Outside code should prefer importing from the barrel rather than deep private paths when a barrel exists.
Tests relative to modules
Keep tests outside modules — top-level test/ (or equivalent), not co-located __tests__ beside module source:
- Broad API / schema / health tests at
test/*.test.ts - Shared fakes /
MakeTestAppintest/helpers.ts - Heavier DB work under
test/integration/
Module structure checklist
Do
- For new backends, use
src/modules/<singular-kebab>/with<name>.routes.ts/.repository.ts/.schemas.tsas needed (e.g.order,billing). - Keep handlers thin; put SQL / persistence in the module repository factories.
- Add a services layer only when the domain needs orchestration beyond thin routes → repository.
- When a module grows, nest with subfolders; expose a deliberate
index.tsbarrel. - Wire new routes from the composition root (
src/app.ts). - Share truly cross-cutting helpers and multi-module domain helpers via
src/lib/(orsrc/db//src/env.tswhen they belong there). - Put tests under top-level
test/, not insidesrc/modules/.
Don’t
- Apply this module layout to frontend apps by default (backend-only convention).
- Create top-level
src/routes/,src/repositories/,src/services/that slice across all domains. - Create modules for sprint tickets, feature flags, or temporary experiments — only for durable architecture parts.
- Create a repository-only
src/modules/…just to share a small helper — usesrc/lib/instead. - Dump code that belongs to a single domain into
src/lib/“for convenience.” - Put process env reads or raw DB client setup inside every module — inject via factories / composition root.
- Force a services layer on every module.
- Prefer plural folder names for new modules (
orders) when a singular domain noun fits (order).
Part C — Scaffolding into a repo
When using this skill to adopt or scaffold code-style guidance:
- Emit formatter/linter configs for detected languages (Part A), when bootstrap is in scope.
- Ensure
CONTRIBUTING.mdexists (create it if missing). - Add all convention sections to
CONTRIBUTING.md— retrieval naming, factory DI, and module structure (paste/adapt templates/contributing-section.md). - Create or update
AGENTS.mdso agents are pointed at those CONTRIBUTING sections (paste/adapt templates/agents-mention.md).
Do not leave the conventions only in a skill file or chat — they must live in-repo where humans and agents both find them.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

