Checks reference

opensip-cli ships 158 built-in checks across seven packs. Each check is a single source file that returns violations when the rule is broken. Below: every check by pack, grouped by primary tag, with the one-line description from defineCheck.

This page is auto-generated from the source by scripts/build-checks-index.mjs. Do not edit it by hand — edit the check's source file (the link in each row), then re-run the generator.


Universal (96 checks)

Language-agnostic; runs against every project.

Architecture (16)

| Slug | Description |

|---|---|

| docker-ignore-validation | Validate .dockerignore files exist alongside Dockerfiles with required patterns |

| docker-version-sync | Validate Docker Node/pnpm versions match package.json |

| empty-package-detection | Detects packages with empty or commented-out exports |

| env-var-validation | Detects environment variable access without proper validation |

| heavy-import-detection | Detects heavy/deprecated library imports and excessive named imports that bloat bundle size |

| interface-implementation-consistency | Verifies interfaces match their implementations |

| no-custom-event-emitter | Detects direct EventEmitter usage that should use infrastructure/events |

| no-duplicate-packages | Detects packages that serve the same purpose |

| no-kebab-option-indexing | Command handlers must not index parsed options by a kebab-case key — Commander camelCases long flags, so the kebab key is always undefined (silent no-op flag) |

| node-version-consistency | Validate Node.js version consistency across configs |

| project-readme-existence | Ensures every package has a README.md file |

| stale-build-artifacts | Detects compiled .js/.d.ts/.js.map files in source directories that should only exist in dist/ |

| tool-has-manifest | Every first-party tool package must declare a conformant opensipTools manifest (kind/id/apiVersion/commands) the host can read before import |

| tool-identity-single-source | Tool packages declare opensipTools.identity once; manifest id, primary command, aliases, and pluginLayout.domain must match the normalized runtime surface |

| vitest-config-extends-base | Per-package vitest configs must extend the shared .config/vitest.base (when one exists) |

| vitest-config-required-with-tests | Ensures packages with tests have a vitest.config at the package root |

Security (18)

| Slug | Description |

|---|---|

| api-key-rotation | Validate API key handling supports rotation |

| auth-middleware-coverage | Validate routes have authentication middleware |

| auth-route-guard | Verify (auth) group _layout files include authentication checks (useAuth/useSession hooks) |

| cors-configuration | Validate CORS configuration follows security best practices |

| csp-headers | Validate Content Security Policy headers configuration |

| dependency-vulnerability-audit | Dependency vulnerability scanning via package manager audit |

| docker-best-practices | Validate Dockerfiles follow security and efficiency best practices |

| env-secret-exposure | Detect secrets exposed through environment variables in logs or errors |

| hasura-production-config | Verify Hasura production docker-compose has required security settings |

| jwt-validation | Validate JWT handling follows security best practices |

| no-eval | Detect dangerous eval and dynamic code execution |

| no-hardcoded-secrets | Detect hardcoded secrets, API keys, and credentials in source code |

| package-supply-chain-policy | Validate npm/pnpm/Bun supply-chain guardrails |

| rate-limit-coverage | Validate routes have rate limiting configured |

| semgrep-scan | Run Semgrep static analysis to detect security vulnerabilities |

| sentry-pii-scrubbing | Detects missing PII scrubbing in Sentry — personal data may leak to third party |

| use-centralized-crypto | Enforce use of centralized crypto module instead of direct crypto operations |

| webhook-signature-verification | Detect webhook endpoints without signature verification |

Quality (28)

| Slug | Description |

|---|---|

| async-state-pattern | Ensure data-driven screens use AsyncState pattern |

| dead-code | Detect unused files, exports, types, and dependencies using Knip |

| dependency-version-consistency | Ensures consistent dependency versions across all packages |

| expo-vector-icons | Ensure consistent icon library usage with @expo/vector-icons |

| file-length-limit | (no description; see source) |

| fitness-ignore-hygiene | Validates that @fitness-ignore directives have valid check slugs and reason comments |

| graph-ignore-hygiene | Validates that @graph-ignore directives have valid graph rule ids and reason comments |

| graphql-offset-pagination | Detect $offset variables in GraphQL queries that indicate offset-based pagination |

| image-optimization | Detect unoptimized image usage and recommend best practices |

| navigation-typing | Verify navigation params are properly typed for type-safe routing |

| no-ai-attribution | Detects AI-attribution metadata in comments |

| no-compatibility-layer-names | Detects compatibility-layer, legacy-wrapper, and backward-compat declarations |

| no-console-log | Disallow console.log in production code - use a structured logger |

| no-deprecated-tags | Detects @deprecated JSDoc tags in production code |

| no-non-null-assertions | Detects TypeScript non-null assertion operator (!) usage in production code — prefer proper null handling |

| no-process-artifacts | Detects process/planning artifacts (Phase X, Sprint X, version stamps) in comments |

| no-raw-regex-on-code | Detect regex checks that should use contentFilter: strip-strings |

| no-skipped-tests | Tests must never ship skipped, focused (.only), or placeholder |

| no-temporary-workarounds | Detects HACK/FIXME comments that describe themselves as temporary |

| no-todo-comments | TODO/FIXME/XXX/OPTIMIZE markers should not ship to production |

| no-unimplemented-markers | (no description; see source) |

| no-window-alert | Disallows window.alert(), window.confirm(), and window.prompt() — use proper UI components |

| performance-anti-patterns | Detects common performance anti-patterns (sequential await, spread in loops) |

| pino-serializer-coverage | Validates that complex objects logged have proper Pino serializers |

| sentry-release-set | Detects Sentry.init() without release — cannot track regressions across deploys |

| sentry-source-maps | Detects missing Sentry source map upload — stack traces will be unreadable |

| yagni-ignore-hygiene | Validates that @yagni-ignore directives have valid detector slugs and reason comments |

| zod-openapi-sync | Ensures Zod schemas use .satisfies z.ZodType<> pattern |

Resilience (26)

| Slug | Description |

|---|---|

| batch-operation-limits | Detect batch operations that may process unbounded data |

| cache-ttl-validation | Validate cache TTL values for appropriate caching behavior |

| catch-clause-safety | Detects unsafe catch clause patterns: as Error casts without instanceof, catch(e: any) |

| dangerous-config-defaults | Detect dangerous default configurations |

| error-code-registration | Validates that error codes used in code are registered in an error registry file |

| event-architecture | Validate event handling follows architectural patterns |

| event-handler-idempotency | Validate event handlers implement idempotency |

| exit-code-correctness | Detect error branches that mask failures with silent success exit |

| graceful-shutdown | Validate services implement graceful shutdown handling |

| no-custom-cache | Enforce use of a shared cache abstraction instead of custom Map-based caches |

| no-custom-rate-limiter | Enforce use of a shared rate limiter instead of custom rate limiting implementations |

| no-hardcoded-timeouts | Detect hardcoded timeout values that should be configurable |

| no-process-exit-in-finally | Detect process.exit() that bypasses finally cleanup |

| rate-limiting-coverage | Validate API endpoints have rate limiting |

| readline-cleanup | Detect readline usage without proper cleanup (close/finally) |

| recovery-patterns | Enforce use of shared recovery/retry utilities instead of hand-rolled retry loops |

| reentrancy-guard | Detect boolean reentrancy guards that need counter/mutex semantics |

| retry-config-validation | Validate retry configs: flag excessive maxRetries (>10) and aggressive baseDelay (<100ms) |

| sentry-dsn-configured | Detects Sentry.init() without a DSN — monitoring silently disabled |

| sentry-environment-set | Detects Sentry.init() without environment — errors from all environments mixed |

| sentry-error-boundary | Detects React + Sentry without ErrorBoundary — render crashes go unreported |

| sentry-sample-rate | Detects missing or 1.0 tracesSampleRate — tracing disabled or too expensive |

| timer-lifecycle | Detects setInterval() calls without corresponding clearInterval() cleanup — prevents timer leaks |

| transaction-boundary-validation | Validate transaction boundaries are properly managed |

| transaction-timeout | Validate transactions have timeout configurations |

| unbounded-memory | Detect unbounded collections and file reads that may cause OOM |

Documentation (4)

| Slug | Description |

|---|---|

| directive-audit | Audit suppression directives for periodic review |

| eslint-justifications | Ensures all ESLint suppressions have proper justifications |

| no-markdown-references | Detect markdown file references in code comments that may become stale |

| public-api-jsdoc | Requires JSDoc documentation on all public API exports in shared packages |

Testing (4)

| Slug | Description |

|---|---|

| no-stub-tests | Detects stub tests with empty bodies, TODO-only bodies, or trivial always-passing assertions |

| test-convention-consistency | Detects mixed .test and .spec naming conventions across the codebase |

| test-file-naming | Validates test file naming conventions follow .test.ts or .spec.ts patterns |

| test-file-pairing | Ensures every source file has a corresponding test file |


TypeScript (56 checks)

TypeScript/JavaScript projects; uses TS-AST analysis.

Architecture (15)

| Slug | Description |

|---|---|

| architecture-no-run-done-result | Run commands render via the single RunPresentation variant; the contracts surface must not re-introduce a per-tool *DoneResult run type |

| callback-invocation-safe | Class-field callbacks invoked from producer code paths (subscribers.forEach, for-of over listeners, etc.) must be wrapped in a safe<Name>(...) helper or try/catch. A throw from one subscriber must not crash the producer or skip subsequent subscribers. |

| circular-import-detection | Detects file-level circular import dependencies |

| command-handler-host-owned-output | A tool command handler must let the host own rendering and exit — no direct stdout/console/process.exit inside a non-raw-stream defineCommand handler |

| contracts-schema-consistency | Validates that contracts use Zod schemas consistently: types derived from schemas via z.infer |

| drizzle-orm-migration-guardrails | Detects dangerous patterns in Drizzle ORM migrations (raw SQL, DROP, TRUNCATE, type changes) |

| host-tool-runtime-import-boundary | External tool runtimes never import in the host: importToolRuntime stays in the admission/discovery boundary, host imports are bundled-only, and the external worker policy is confined to the worker plane (ADR-0054 M4-G capstone) |

| live-view-through-cli-live | Tool engine live views route through cli-live (no direct ink render imports) |

| missing-type-exports | Detects types imported via deep internal paths not declared in the package exports map or barrel |

| module-coupling-fan-out | Flags files with high outbound import fan-out (god-files) |

| no-bootstrap-tool-import | The CLI host must not statically import a tool runtime — bundled tools load via the dynamic plugin path (§1 install-source independence) |

| package-json-exports-field | (no description; see source) |

| phantom-dependency-detection | Detect phantom dependencies (used but not declared in package.json) |

| subprocess-correlation-required | CLI subprocess spawn/fork sites must forward the RunCorrelation bag (runId via env, other fields via env+spec) so child failures are attributable |

| tsconfig-extends-validation | Ensures all tsconfig.json files extend a shared base and the base file exists |

Security (4)

| Slug | Description |

|---|---|

| input-sanitization | Detect unsanitized user input usage |

| pii-exposure-in-logs | Detects potential PII exposure in log statements |

| sql-injection | Detect potential SQL injection vulnerabilities |

| unsafe-secret-comparison | Detect timing-unsafe equality comparisons on secret/token values |

Quality (31)

| Slug | Description |

|---|---|

| a11y-form-labels | Verify form inputs have associated labels for accessibility |

| a11y-semantic-html | Detect View components with press handlers missing accessibilityRole |

| api-contract-validation | Validate API handlers have proper validation, typed responses, and error handling |

| api-response-validation | Ensure API responses are validated with Zod schemas |

| array-validation | Detect array parameters without proper validation |

| async-waterfall-detection | Detect sequential await statements that could be parallelized |

| database-index-coverage | Validate database queries have appropriate indexes |

| database-schema-validation | Validate database schema definitions follow best practices |

| dispose-pattern-completeness | Validate IDisposable implementations clean up all resources |

| duplicate-utility-functions | Detect duplicate and similar utility functions |

| error-handling-quality | Detect silent error handling in try/catch and Result patterns |

| fastify-route-validation | Ensure all Fastify POST/PATCH/PUT routes validate request bodies with Zod schemas |

| fastify-schema-coverage | Validate that Fastify routes have proper request/response schema validation |

| in-memory-repository-detection | Detect repository classes using Map or in-memory storage instead of proper persistence |

| incomplete-regex-escaping | Detect incomplete regex character escaping that can lead to security vulnerabilities |

| lifecycle-cleanup-enforcement | Detect resources with lifecycle methods (destroy/close/shutdown) created without cleanup |

| logger-event-name-format | Validate logger evt fields have 3+ dot-separated segments |

| missing-input-validation | Detect API handlers accepting external input without validation (Zod, Joi, etc.) |

| no-any-types | Detect usage of any type - use unknown with type narrowing instead |

| no-hardcoded-correlation-id | Detect hardcoded correlation ID string literals |

| null-safety | Detect unsafe property and method access without null checks |

| numeric-validation | Detect numeric parameters without NaN/Infinity/range validation |

| result-pattern-consistency | Ensures consistent use of Result<T,E> for expected failures and throw for unexpected failures |

| silent-early-returns | Detect single-line early returns without logging |

| stream-buffer-size-limits | Detects Buffer.concat() and stream buffering without size limit guards |

| stubbed-implementation-detection | Detects incomplete/placeholder implementations |

| test-only-frontend-modules | Detects frontend code only imported by test files |

| throws-documentation | Detects functions with throw statements but no @throws JSDoc |

| toctou-race-condition | Detects read-then-update patterns without atomic guarantees |

| typescript-frontend | Validates TypeScript compilation for frontend apps |

| unused-config-options | Detects configuration properties defined but never accessed |

Resilience (5)

| Slug | Description |

|---|---|

| context-leakage | Detect potential request context leakage |

| context-mutation | Detect unsafe mutations of request/execution context |

| detached-promises | Detect promises that may not be awaited (potential silent failures) |

| no-raw-fetch | Detect direct fetch() calls that should use wrapped HTTP clients |

| no-unbounded-concurrency | Detect Promise.all with unbounded concurrency |

Testing (1)

| Slug | Description |

|---|---|

| mock-implementations-in-production | Detects mock, stub, or fake implementations in production code |


Python (2 checks)

Python projects.

Quality (2)

| Slug | Description |

|---|---|

| python-function-too-long | Python functions should stay under a line budget for readability and testability |

| python-no-bare-except | Bare except clauses catch system-exiting exceptions like KeyboardInterrupt |


Go (1 check)

Go projects.

Quality (1)

| Slug | Description |

|---|---|

| go-no-fmt-print | (no description; see source) |


Java (1 check)

Java projects.

Quality (1)

| Slug | Description |

|---|---|

| java-no-print-stack-trace | e.printStackTrace() bypasses the logging framework — use a logger instead |


C / C++ (1 check)

C/C++ projects.

Quality (1)

| Slug | Description |

|---|---|

| cpp-clang-tidy | Run clang-tidy and surface its diagnostics as opensip-cli violations |


Rust (1 check)

Rust projects.

Quality (1)

| Slug | Description |

|---|---|

| rust-no-dbg-macro | (no description; see source) |


How to use a check

Every check above is loaded automatically when its pack is in your project's node_modules/. To target one explicitly:

opensip fit --check <slug>           # run one check
opensip fit --tags security          # run all checks tagged security
opensip fit --recipe quick-smoke     # run a named lineup

Per-check parameter overrides go in your recipe under config: — see recipes and checks.

To write your own check, see plugin authoring.