Best Practices
These principles apply whether you're writing a check yourself or reviewing one your coding agent generated. A well-structured check tells the agent exactly what to look for and how to fix it; a vague one produces noise.
Scope narrowly
Write one check per concern. A single check that tries to cover security, test coverage, and documentation will produce muddled results. Split it into three checks instead.
---
name: Input Validation
description: Verify new API endpoints validate their inputs
---
Look for new API endpoints that accept user input without validation
(missing type checks, no schema validation, no length limits).
If found, add appropriate input validation.
A "review everything" check will spread itself thin and miss things. A focused check does one job well.
Be specific about what to look for
The prompt must describe exactly what the agent should look for and what it should do about it. Vague instructions produce vague results.
Good:
Look for new API endpoints that don't validate their inputs. Add schema validation using zod where missing.
Bad:
Check that the code is secure.
Structure criteria as a concrete list:
Look for these issues in the changed code and fix them:
- New REST endpoints missing request body validation
- Database queries using string interpolation instead of parameterized queries
- Error responses that expose stack traces or internal paths
The more specific you are about what to look for, the more reliable the check.
What you don't need to write
When a check runs, the system automatically prepends a meta prompt that handles diff scoping for you. Specifically, it:
- Provides the full diff and a list of changed files
- Instructs the agent to only review changed lines
- Prevents the agent from touching pre-existing issues in unchanged code
- Restricts edits to changed files only
You don't need to include instructions like "review the changed files" or "only look at the diff" — that's already handled. Focus your check on what to look for and how to fix it, not on scoping or diff mechanics.
What checks can do
Checks are not limited to reading the diff. The agent running a check can:
- Read files in the repository beyond the diff, to understand surrounding context
- Run bash commands like
grep,find, or custom scripts - Use a browser to visit URLs, take screenshots, and verify rendered output
- Access the PR diff including file names, additions, and deletions
- Use the GitHub CLI (
gh) to read PR metadata, comments, or linked issues
This means a check can do things like verify a new page renders correctly in a browser, or cross-reference the diff against your database schema.
Checks vs. tests vs. linting
Linting handles formatting, style, and static patterns. Use ESLint, Prettier, Ruff, or equivalent. If a rule can be expressed as a pattern match on syntax, it belongs in a linter.
Tests verify correctness, behavior, and regressions. Use your test framework. If the question is "does this function return the right output for these inputs," write a test.
Checks handle judgment calls that require understanding context:
- "Is this database migration safe to run on a 500M-row table?"
- "Does this PR update the API docs to reflect the endpoint changes it makes?"
- "Are there security issues in this auth flow that a linter wouldn't catch?"
- "Does this error handling follow the patterns established elsewhere in the codebase?"
Checks fill the gap between mechanical linting and human review. They are most valuable for questions that require reading multiple files, understanding intent, or applying project-specific conventions that aren't codified in a linter rule.
Examples
Complete check files you can drop into
.continue/checks/ directly. These are generic starting points — checks generated by your coding agent will be more specific to your project.Security review
---
name: Security Review
description: Catch hardcoded secrets, injection vectors, and missing input validation
---
Look for these security issues in the changed code and fix them:
- Hardcoded API keys, tokens, passwords, or connection strings — move them to environment variables
- New API endpoints or request handlers without input validation — add appropriate validation
- SQL queries built with string concatenation or template literals — convert to parameterized queries
- Sensitive data (passwords, tokens, PII) written to logs or stdout — remove or redact the sensitive fields
- New cryptographic code using weak algorithms (MD5, SHA1 for security purposes, ECB mode) — replace with stronger alternatives
- Secrets added to files that are not in `.gitignore` — remove them and add the files to `.gitignore`
Test coverage
---
name: Test Coverage
description: Ensure new code has corresponding tests
---
Look for new code that's missing tests:
- A new source file was added without a corresponding test file (e.g., `utils.ts` added but no `utils.test.ts`) — create a test file with basic coverage for the exported functions
- New exported functions or public methods with no tests exercising them — add tests covering the main code paths
- An existing test file was deleted without the corresponding source file also being deleted — flag this for review
No changes needed if:
- All new source files have corresponding test files
- New functions/methods are already covered by tests
- Only test files, docs, or config files were changed
Documentation freshness
---
name: Documentation Freshness
description: Keep docs in sync when public APIs or configuration changes
---
Look for changes to public-facing APIs or configuration where the documentation wasn't updated:
- A public function, class, or type signature was added or changed — update the corresponding docs (README, docs/, or inline JSDoc/docstrings)
- Configuration options were added or renamed (config files, environment variables, CLI flags) — update the relevant documentation to reflect the new options
- API route paths or request/response shapes changed — update the API documentation
No changes needed if the PR doesn't touch public APIs or configuration, or if docs were already updated.
Conventional commits
---
name: Conventional Commits
description: Ensure the PR title follows conventional commit format
---
Check that the pull request title follows the Conventional Commits specification.
The title must match this format: `type(optional scope): description`
Valid types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`
If the PR title doesn't match the format, suggest a corrected title based on the content of the changes.
Dependency audit
---
name: Dependency Audit
description: Review new or updated dependencies for risk
---
If no dependency files (`package.json`, `requirements.txt`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `Gemfile`, or similar) were changed, no action is needed.
When dependencies were added or updated, look for these issues:
- A new dependency that appears unmaintained (no commits in the last 12 months) — flag for review and suggest well-maintained alternatives
- A dependency was bumped by more than one major version (e.g., v2.x to v4.x) without a note in the PR description — add a comment explaining the jump
- A known deprecated or security-flagged package was added — replace with the recommended alternative
- A dependency that duplicates functionality from an existing dependency — remove and use the existing one instead
- Dev dependencies in production dependency sections (e.g., a test framework in `dependencies` instead of `devDependencies`) — move to the correct section
Migration safety
---
name: Migration Safety
description: Catch destructive database migrations
---
If no migration files were added or changed, no action is needed.
When migrations are present, look for these issues:
- `DROP TABLE` or `DROP COLUMN` without a preceding migration that backs up or migrates the data — add a data migration step or split into separate migrations
- Column type narrowing (e.g., `TEXT` to `VARCHAR(50)`, `BIGINT` to `INT`) without a backfill step — add a backfill or guard against data truncation
- `NOT NULL` constraint added to an existing column without a `DEFAULT` value — add a default or a data backfill migration
- Renaming a column or table that is referenced by application code without updating that code in the same PR — update the references
- A destructive and a constructive change in the same migration file — split into separate migrations for safe rollback