Detect and match the conventions, patterns, and local idioms of an existing codebase before writing new code. Use this skill when adding an existing codebase, especially when you're unfamiliar with the project or haven't worked in this area of the code before. Triggers on any implementation task in an existing project, or when you notice your code doesn't look like surrounding code. Trigger when writing tests, config files, or documentation in an existing project, since conventions apply to those too.
When a senior engineer joins a new project, the first thing they do isn't write code — it's read code. They're not reading for understanding (that comes later). They're reading for patterns. How does this team name things? How do they structure files? Where do they put tests? How do they handle errors? What abstractions do they use?
This process is so automatic that most seniors can't articulate the conventions they've absorbed — they just "feel" when something looks wrong. This skill makes that pattern detection explicit and systematic.
The underlying principle is simple: consistency is more important than personal preference. A codebase where everything follows the same patterns — even imperfect ones — is easier to navigate, review, and maintain than a codebase where each file reflects a different author's style.
Before scanning files manually, check whether the team's conventions have been codified. Manually scanning 3-5 files works, but if the team has already documented their conventions as ADRs, principles, or architecture decisions, those are the authoritative source.
If gjalla is available, query these tools first:
get_context(scope="rules") — load active ADRs and principles. These are the
conventions the team chose to write down — naming standards, architecture patterns,
error handling strategies. They take precedence over patterns you observe in code
(code might be inconsistent; the rules represent intent).get_context(scope="architecture") — load the system's architecture. This tells you
how components are organized, which patterns are used (MVC, hexagonal, event-driven),
and how relationships between components are structured.get_file_context(file_path="...") — before editing a specific file, get its
architectural role so you understand how it fits into the larger structure.If gjalla is not available, proceed with the file-scanning approach below. Look for
CONTRIBUTING.md, .editorconfig, linter configs, or docs/style-guide.md.
Before writing new code, scan the codebase for patterns in each of these categories. You don't need to document all of them — just enough to write code that blends in.
is/has/should? Are callbacks prefixed with on/handle?OrderService,
UserRepository, PaymentHandler)?<table>_id convention?Feature folders: src/orders/controller.ts, src/orders/service.ts, src/orders/model.ts
Layer folders: src/controllers/orders.ts, src/services/orders.ts, src/models/orders.ts
foo.test.ts next to foo.ts) or in a
separate test directory?describe/it, test_<function>_<scenario>, or something else?You don't need to read the entire codebase. Follow this process:
Find a recent, well-reviewed file similar to what you're building. Look at recent PRs or recently modified files in the area you're working in. These represent the team's current conventions (which may differ from older code).
Read 3-5 files of the same type. If you're writing a new service, read 3 existing services. If you're writing a new API endpoint, read 3 existing endpoints. Look for the patterns they share.
Check for explicit style guides. Look for CONTRIBUTING.md, .editorconfig,
linter configs, or a docs/style-guide.md. These are the rules the team chose to write
down.
When in doubt, match the surrounding code. If the conventions aren't clear or are inconsistent across the codebase, match the conventions of the nearest code — the files in the same directory or the same feature area.
Sometimes the codebase conventions are genuinely bad. Maybe error handling is inconsistent, or the naming is confusing, or there's a pattern that creates bugs.
Default to matching existing conventions anyway. Consistency has value even when the convention isn't ideal. A codebase with one consistent (imperfect) pattern is easier to work with than a codebase with two patterns where "the new way is better."
Exception: when the convention is actively harmful. If following the convention would introduce a security vulnerability, data corruption risk, or performance problem, deviate from it — and document why. Add a TODO or a note in the PR explaining that this deviates from the existing pattern and why.
If you believe a convention should change project-wide, that's a separate effort. Don't try to reform the codebase one file at a time during feature work — that creates inconsistency, which is worse than a bad but consistent convention.
This skill doesn't produce a standalone document. Instead, it ensures that every file you create follows the patterns of the codebase it lives in. The output is code that looks like it was written by someone who's been on the team for months, not by an outsider.
If you discover that conventions are unclear or inconsistent, note this to the user — it
may be worth establishing explicit conventions (a CONTRIBUTING.md or linter rules) to
prevent the inconsistency from growing.
In the PR description, document which conventions you matched and any deviations:
## Conventions Attestation
**Rules checked**: [ADRs/principles from get_context(scope="rules") that applied]
**Conventions matched**: [specific patterns you followed — naming, architecture, error handling]
**Conventions deviated from**: [any deviations, with justification]
**Conventions discovered (not yet codified)**: [patterns you observed in code that aren't
in any formal rule — worth discussing with the team]
This attestation serves two purposes: it proves the agent respected the team's conventions, and it surfaces uncodified conventions that the team might want to formalize.