Appearance
Convention Packs
Caliper ships with curated convention packs for TypeScript, Python, and Go. When you run caliper init and select a framework, these checks are activated automatically — no configuration required.
Each check runs deterministically on every commit or PR. They catch the patterns that slip through in review: forgotten debug logging, mutable defaults, hardcoded secrets, and more.
TypeScript
Security
| Check | Detects | Fix |
|---|---|---|
| No execSync with template strings | execSync called with a template literal, risking shell injection | Use execFileSync with array args to prevent shell injection |
| No eval() calls | Usage of eval() | Avoid eval — use safer alternatives like JSON.parse or Function constructor |
| No hardcoded API keys or secrets | Strings assigned to variables named api_key, secret, password, token, etc. | Use environment variables for secrets, never hardcode them |
Type Safety
| Check | Detects | Fix |
|---|---|---|
| No explicit 'any' type annotations | : any, as any, or <any> in TypeScript files | Use a specific type, unknown, or a generic instead of any |
| No @ts-ignore without explanation | @ts-ignore comments that lack a reason | Use @ts-expect-error with a reason comment, or fix the type error |
| No non-null assertions on lookups | Non-null assertion (!) on .get() or bracket access results | Provide a fallback value instead of using ! on map/object lookups |
Code Quality
| Check | Detects | Fix |
|---|---|---|
| Functions under 50 lines | Functions exceeding 50 lines (AST-based) | Extract named helpers to keep functions focused and under 50 lines |
| Functions have at most 4 parameters | Functions with more than 4 parameters (AST-based) | Use an options object instead of many positional parameters |
| Cyclomatic complexity under 15 | Functions with cyclomatic complexity above 15 (AST-based) | Reduce branching by extracting conditions into named functions or using early returns |
| No console.log in production code | console.log() calls in src/ files | Use a proper logger or remove debug logging before committing |
| Files under 500 lines | Source files exceeding 500 lines | Split large files into focused modules with single responsibilities |
Architecture
| Check | Detects | Fix |
|---|---|---|
| No process.env reads at module level | Top-level const/let/var assignments from process.env | Read environment variables inside functions, not at module scope |
Python
Security
| Check | Detects | Fix |
|---|---|---|
| No hardcoded API keys or secrets | Strings assigned to variables named api_key, secret, password, token, etc. | Use environment variables for secrets, never hardcode them |
| No eval() or exec() calls | Usage of eval() or exec() | Avoid eval/exec — use safer alternatives like ast.literal_eval |
| No f-string or .format() in SQL queries | f-strings or .format() in execute() calls with SQL keywords | Use parameterized queries to prevent SQL injection |
Error Handling
| Check | Detects | Fix |
|---|---|---|
| No bare except clauses | except: without a specific exception type | Catch a specific exception type instead of using bare except |
Type Safety
| Check | Detects | Fix |
|---|---|---|
| No type: ignore without explanation | # type: ignore without a specific error code | Use type: ignore[specific-error] with a reason, or fix the type error |
Code Quality
| Check | Detects | Fix |
|---|---|---|
| No wildcard imports | from module import * statements | Import specific names instead of using wildcard imports |
| No mutable default arguments | [] or {} used as default parameter values | Use None as default and create the mutable object inside the function |
| No print() in production code | print() calls in src/ files | Use the logging module instead of print statements |
| Files under 500 lines | Source files exceeding 500 lines | Split large files into focused modules |
Testing
| Check | Detects | Fix |
|---|---|---|
| Source files have corresponding test files | Source files in src/ without a matching _test.py companion | Create a test file for each source module |
Go
Security
| Check | Detects | Fix |
|---|---|---|
| No hardcoded API keys or secrets | Strings assigned to variables named apiKey, secret, password, token, etc. | Use environment variables for secrets, never hardcode them |
| No string concatenation in SQL queries | String concatenation or fmt.Sprintf in Query/Exec calls with SQL keywords | Use parameterized queries to prevent SQL injection |
Error Handling
| Check | Detects | Fix |
|---|---|---|
| No ignored error returns | Function calls whose error return value is discarded | Always check error return values — don't ignore them |
| No panic() in library code | Usage of panic() | Return errors instead of panicking — panic is for unrecoverable situations only |
Architecture
| Check | Detects | Fix |
|---|---|---|
| Avoid init() functions | func init() declarations | Use explicit initialization instead of init() to make dependencies clear |
| No mutable global variables | Package-level var declarations (excluding sync primitives) | Avoid mutable globals — pass dependencies explicitly or use sync primitives |
Code Quality
| Check | Detects | Fix |
|---|---|---|
| Files under 500 lines | Source files exceeding 500 lines | Split large files into focused packages |
Testing
| Check | Detects | Fix |
|---|---|---|
| Source files have corresponding test files | Source files without a matching _test.go companion | Create a test file for each source package |
Extending with Custom Checks
The packs above are just the starting point. Run caliper refresh to scan your project's CLAUDE.md files and automatically compile additional checks tailored to your team's conventions. Custom checks are added to .caliper/checks.js alongside the pack checks.