Match Codebase Conventions
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.
Step 0: Load Team Conventions from System State
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.
Convention Detection Checklist
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.
Naming
- Variables and functions: camelCase, snake_case, or something else? Are booleans
prefixed with
is/has/should? Are callbacks prefixed with on/handle?
- Files and directories: kebab-case, PascalCase, snake_case? Do filenames match the
exported class/function name?
- Classes and types: PascalCase? Suffixed with the pattern (e.g.,
OrderService,
UserRepository, PaymentHandler)?
- Constants: UPPER_SNAKE_CASE? Where are they defined — in the file, in a constants
file, in environment variables?
- Database columns and tables: singular or plural table names? snake_case columns?
Do foreign keys follow
<table>_id convention?
- API endpoints: RESTful nouns or action verbs? Plural or singular resources? How are
nested resources structured?
Architecture Patterns
- Code organization: feature folders vs. layer folders? Where do new files go?
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
- Dependency injection: constructor injection, parameter injection, service locator,
or direct imports?
- Data access: ORM, query builder, raw SQL, or repository pattern? Are database calls
in the service layer or a separate data layer?
- API structure: controller → service → repository? Or something flatter/different?
- Configuration: environment variables, config files, feature flags? Where do they live?
Error Handling
- Strategy: throw exceptions, return Result/Either types, return error codes, or
callback-style errors?
- Custom error classes: does the project define domain-specific error types, or does
it use generic errors?
- Error responses: what shape do API error responses have? Is there a standard error
formatter?
- Logging: what gets logged on errors? What level? What context fields?
Testing
- Framework: Jest, pytest, Go testing, JUnit? What assertion style?
- File location: co-located with source (
foo.test.ts next to foo.ts) or in a
separate test directory?
- Naming:
describe/it, test_<function>_<scenario>, or something else?
- Fixtures and factories: how is test data created? Is there a factory pattern, fixture
files, or inline test data?
- Mocking: what gets mocked? How? Are there shared mock helpers?
- Coverage: is there a coverage threshold? Which kinds of tests exist (unit, integration,
e2e)?
Code Style
- Formatting: is there a formatter config (Prettier, Black, gofmt)? Follow it exactly.
- Linting: is there a linter config (ESLint, pylint, golangci-lint)? What rules are
enabled?
- Comments: does the project use JSDoc/docstrings/godoc? How detailed? Are inline
comments common or rare?
- Imports: absolute or relative paths? Grouped by type? Specific ordering?
Patterns You Might Not Think to Check
- How are feature flags used? Is there a standard pattern for checking flags?
- How are database migrations structured? What tool is used? Naming convention?
- How are background jobs defined? Is there a job framework? How are retries handled?
- How are events/messages published? Event names, payload shapes, serialization format?
- How are permissions checked? Middleware, decorators, inline checks?
- How are external API calls made? Shared HTTP client, per-service wrappers, retry logic?
How to Scan Efficiently
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.
When Conventions Conflict With Best Practices
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.
Output
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.
Attestation: Conventions Followed
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.
1---2name: match-codebase-conventions3description: 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.4---56# Match Codebase Conventions78When a senior engineer joins a new project, the first thing they do isn't write code — it's9*read* code. They're not reading for understanding (that comes later). They're reading for10*patterns*. How does this team name things? How do they structure files? Where do they put11tests? How do they handle errors? What abstractions do they use?1213This process is so automatic that most seniors can't articulate the conventions they've14absorbed — they just "feel" when something looks wrong. This skill makes that pattern15detection explicit and systematic.1617The underlying principle is simple: **consistency is more important than personal preference.**18A codebase where everything follows the same patterns — even imperfect ones — is easier to19navigate, review, and maintain than a codebase where each file reflects a different author's20style.2122---2324## Step 0: Load Team Conventions from System State2526Before scanning files manually, check whether the team's conventions have been codified.27Manually scanning 3-5 files works, but if the team has already documented their conventions28as ADRs, principles, or architecture decisions, those are the authoritative source.2930**If gjalla is available**, query these tools first:3132- `get_context(scope="rules")` — load active ADRs and principles. These are the33 conventions the team chose to write down — naming standards, architecture patterns,34 error handling strategies. They take precedence over patterns you observe in code35 (code might be inconsistent; the rules represent intent).36- `get_context(scope="architecture")` — load the system's architecture. This tells you37 how components are organized, which patterns are used (MVC, hexagonal, event-driven),38 and how relationships between components are structured.39- `get_file_context(file_path="...")` — before editing a specific file, get its40 architectural role so you understand how it fits into the larger structure.4142**If gjalla is not available**, proceed with the file-scanning approach below. Look for43`CONTRIBUTING.md`, `.editorconfig`, linter configs, or `docs/style-guide.md`.4445---4647## Convention Detection Checklist4849Before writing new code, scan the codebase for patterns in each of these categories. You50don't need to document all of them — just enough to write code that blends in.5152### Naming5354- **Variables and functions**: camelCase, snake_case, or something else? Are booleans55 prefixed with `is`/`has`/`should`? Are callbacks prefixed with `on`/`handle`?56- **Files and directories**: kebab-case, PascalCase, snake_case? Do filenames match the57 exported class/function name?58- **Classes and types**: PascalCase? Suffixed with the pattern (e.g., `OrderService`,59 `UserRepository`, `PaymentHandler`)?60- **Constants**: UPPER_SNAKE_CASE? Where are they defined — in the file, in a constants61 file, in environment variables?62- **Database columns and tables**: singular or plural table names? snake_case columns?63 Do foreign keys follow `<table>_id` convention?64- **API endpoints**: RESTful nouns or action verbs? Plural or singular resources? How are65 nested resources structured?6667### Architecture Patterns6869- **Code organization**: feature folders vs. layer folders? Where do new files go?70 ```71 Feature folders: src/orders/controller.ts, src/orders/service.ts, src/orders/model.ts72 Layer folders: src/controllers/orders.ts, src/services/orders.ts, src/models/orders.ts73 ```74- **Dependency injection**: constructor injection, parameter injection, service locator,75 or direct imports?76- **Data access**: ORM, query builder, raw SQL, or repository pattern? Are database calls77 in the service layer or a separate data layer?78- **API structure**: controller → service → repository? Or something flatter/different?79- **Configuration**: environment variables, config files, feature flags? Where do they live?8081### Error Handling8283- **Strategy**: throw exceptions, return Result/Either types, return error codes, or84 callback-style errors?85- **Custom error classes**: does the project define domain-specific error types, or does86 it use generic errors?87- **Error responses**: what shape do API error responses have? Is there a standard error88 formatter?89- **Logging**: what gets logged on errors? What level? What context fields?9091### Testing9293- **Framework**: Jest, pytest, Go testing, JUnit? What assertion style?94- **File location**: co-located with source (`foo.test.ts` next to `foo.ts`) or in a95 separate test directory?96- **Naming**: `describe/it`, `test_<function>_<scenario>`, or something else?97- **Fixtures and factories**: how is test data created? Is there a factory pattern, fixture98 files, or inline test data?99- **Mocking**: what gets mocked? How? Are there shared mock helpers?100- **Coverage**: is there a coverage threshold? Which kinds of tests exist (unit, integration,101 e2e)?102103### Code Style104105- **Formatting**: is there a formatter config (Prettier, Black, gofmt)? Follow it exactly.106- **Linting**: is there a linter config (ESLint, pylint, golangci-lint)? What rules are107 enabled?108- **Comments**: does the project use JSDoc/docstrings/godoc? How detailed? Are inline109 comments common or rare?110- **Imports**: absolute or relative paths? Grouped by type? Specific ordering?111112### Patterns You Might Not Think to Check113114- **How are feature flags used?** Is there a standard pattern for checking flags?115- **How are database migrations structured?** What tool is used? Naming convention?116- **How are background jobs defined?** Is there a job framework? How are retries handled?117- **How are events/messages published?** Event names, payload shapes, serialization format?118- **How are permissions checked?** Middleware, decorators, inline checks?119- **How are external API calls made?** Shared HTTP client, per-service wrappers, retry logic?120121---122123## How to Scan Efficiently124125You don't need to read the entire codebase. Follow this process:1261271. **Find a recent, well-reviewed file similar to what you're building.** Look at recent128 PRs or recently modified files in the area you're working in. These represent the team's129 current conventions (which may differ from older code).1301312. **Read 3-5 files of the same type.** If you're writing a new service, read 3 existing132 services. If you're writing a new API endpoint, read 3 existing endpoints. Look for the133 patterns they share.1341353. **Check for explicit style guides.** Look for `CONTRIBUTING.md`, `.editorconfig`,136 linter configs, or a `docs/style-guide.md`. These are the rules the team chose to write137 down.1381394. **When in doubt, match the surrounding code.** If the conventions aren't clear or are140 inconsistent across the codebase, match the conventions of the *nearest* code — the files141 in the same directory or the same feature area.142143---144145## When Conventions Conflict With Best Practices146147Sometimes the codebase conventions are genuinely bad. Maybe error handling is inconsistent,148or the naming is confusing, or there's a pattern that creates bugs.149150**Default to matching existing conventions anyway.** Consistency has value even when the151convention isn't ideal. A codebase with one consistent (imperfect) pattern is easier to152work with than a codebase with two patterns where "the new way is better."153154**Exception: when the convention is actively harmful.** If following the convention would155introduce a security vulnerability, data corruption risk, or performance problem, deviate156from it — and document why. Add a TODO or a note in the PR explaining that this deviates157from the existing pattern and why.158159If you believe a convention should change project-wide, that's a separate effort. Don't160try to reform the codebase one file at a time during feature work — that creates161inconsistency, which is worse than a bad but consistent convention.162163---164165## Output166167This skill doesn't produce a standalone document. Instead, it ensures that every file you168create follows the patterns of the codebase it lives in. The output is code that looks like169it was written by someone who's been on the team for months, not by an outsider.170171If you discover that conventions are unclear or inconsistent, note this to the user — it172may be worth establishing explicit conventions (a `CONTRIBUTING.md` or linter rules) to173prevent the inconsistency from growing.174175### Attestation: Conventions Followed176177In the PR description, document which conventions you matched and any deviations:178179```180## Conventions Attestation181182**Rules checked**: [ADRs/principles from get_context(scope="rules") that applied]183**Conventions matched**: [specific patterns you followed — naming, architecture, error handling]184**Conventions deviated from**: [any deviations, with justification]185**Conventions discovered (not yet codified)**: [patterns you observed in code that aren't186in any formal rule — worth discussing with the team]187```188189This attestation serves two purposes: it proves the agent respected the team's conventions,190and it surfaces uncodified conventions that the team might want to formalize.