Critiq team
- philosophy
Why we open-sourced the rules engine (and what stays in the catalog)
Critiq ships the rule engine, DSL, and 435+ OSS catalog rules in the open. Here is what you get locally, what Pro adds, and how to inspect rules yourself.
Why we open-sourced the rules engine (and what stays in the catalog) content
Static analysis tools often ask you to trust a black box: run a scan, read the findings, and hope the vendor will explain the logic later. We built Critiq differently. The rule engine, the Rule DSL contract, the testing harness, and a large public catalog all ship in the open so you can run checks locally, read the rules, and decide from the output, before you wire anything into CI or a hosted product.
That choice is deliberate. Deterministic code review only earns trust when the rules are inspectable. Open-sourcing the engine is not a marketing stunt; it is how we hold ourselves accountable to the same transparency we ask teams to expect from their own review process.
Open-core, not open-washing
We use an open-core model, not “open source” as a funnel with the real product hidden behind a login. The core runtime, critiq-core, is a deterministic, catalog-first rule engine. It includes the Rule DSL, semantic validation, source adapters, a repository scan runtime, and the CLI commands you run in your repo today. None of that requires a Critiq account, Critiq Cloud, or a paid license.
What stays outside the OSS boundary is narrower than you might expect from other vendors, but it is real. Critiq Pro ships a separate premium catalog and adapters that the public CLI does not register by default. Hosted workflows in Critiq Cloud orchestrate scans for connected repositories. Those surfaces build on the same contracts; they do not replace the need for local proof.
The line we draw is practical: if a team should be able to verify a finding without calling us, the rule logic and the engine that evaluates it belong in OSS. If the value is deeper analysis on premium facts, a maintained pack we fund ongoing research for, or hosted orchestration across an org, that work may live elsewhere, and we say so plainly.
What ships in OSS today
The public CLI surface is intentionally small. You install @critiq/cli and @critiq/rules, point it at a repository, and get structured output you can read in the terminal or pipe into CI.
npx @critiq/cli check .
critiq check --format json .
critiq check --format sarif .critiq check runs the OSS catalog against your tree (or a git diff when you pass --base and --head). Output formats include pretty, json, sarif, and html. Exit codes are catalog-driven, which matters when you gate merges on severity. A separate critiq audit secrets command runs a dedicated secret-pattern scan with its own exit code, and pretty output from critiq check also surfaces an advisory built-in secret summary.
The Rule DSL (v0alpha1) is the contract every catalog rule follows. Rules declare metadata (id, title, summary, rationale, tags), scope (languages and paths), a match expression over deterministic facts, and an emit block that shapes findings. Security rules in the OSS catalog declare metadata.references (CWE, OWASP, advisories) and metadata.detection.kind: pattern so you can see what kind of issue a rule targets. Transparency fields are excluded from ruleHash so finding fingerprints stay stable when help text changes, a small detail that matters when you diff scan results over time.
The @critiq/rules catalog currently exposes more than 435 rules spanning correctness, performance, quality, security, logging, config, framework packs (React, Next.js, Django, Spring, Rails, Axum, Laravel, and others), and shared polyglot facts across Go, Java, PHP, Python, Ruby, Rust, and TypeScript. The TypeScript and JavaScript path is the deepest; other languages share deterministic adapters for the facts those rules need. The catalog grows in the critiq-rules repository; releases publish to npm as @critiq/rules.
Rule authoring and inspection commands ship with the CLI, not as a separate “enterprise authoring suite”:
- critiq rules validate, schema and contract checks on .rule.yaml files
- critiq rules test, run RuleSpec fixtures against rules
- critiq rules normalize, canonical JSON view of a rule after validation
- critiq rules explain, parsed summary, references, and inferred template variables
You can also run Critiq in GitHub Actions without Cloud: critiq-action installs the CLI and catalog when needed, captures JSON output, posts optional inline review comments on PR diffs, and supports fail-on-severity merge gates. That action is OSS and documented on GitHub; no hosted account required.
What Pro adds (without the sales pitch)
Critiq Pro is a separate workspace with its own catalog and runtime packages. The public critiq check command does not register Pro adapters by default, so OSS and Pro stay distinct execution paths unless you explicitly opt into Pro tooling.
Today @critiq-pro/rules ships 131 premium catalog rules. That includes client-safety rules for Android and Electron, framework-focused wave-1 rules across Go, Java, JavaScript, Node.js, PHP, Python, Ruby, Rust, and TypeScript via premium source adapters, and 85 native Dockerfile rules (pro.docker.dok-*) with DeepSource DOK-* parity through a dedicated Dockerfile adapter. Docker analysis is configured with dockerfilePaths and trustedRegistries in .critiq/pro.yaml, paths and registries the OSS CLI does not evaluate out of the box.
Pro also wraps external engines where a maintained adapter beats reimplementing years of upstream work. @critiq-pro/aws-iac-nag is the wrapped engine shipping today; Critiq Cloud’s worker can run it alongside critiq check when orchestrating PR scans. Additional premium packs (Terraform depth, supply chain, cross-file dataflow) remain on the roadmap, we mention them as direction, not as shipped surface.
We are not going to pretend Pro is “just more OSS rules with a license key.” It is a funded catalog and adapter layer for teams that want deeper coverage on facts we do not ship in the public catalog. The honest comparison is simple: OSS gives you the engine, the DSL, the tooling, and 435+ rules you can read and run today; Pro adds premium packs you opt into when those rules match your stack.
Inspect rules locally
You do not need to spelunk minified bundles to understand a Critiq finding. Rules are YAML files. The catalog lives in critiq-rules; after install, node_modules/@critiq/rules points at the same rule files npm published. Custom rules belong under .critiq/rules/ in your repo and follow the same DSL.
A practical workflow when a finding looks wrong or overly broad:
- Re-run with JSON to capture rule id, severity, and location: critiq check --format json .
- Locate the rule file by id (for example ts.security.ssrf in the TypeScript security pack)
- Run critiq rules explain on that file to see validation status, normalized shape, and references
- If you author or fork the rule, validate and test before merging: critiq rules validate and critiq rules test
Because findings fingerprint on stable rule hashes, you can compare outputs across CLI versions and know whether a delta came from rule logic or from metadata tweaks.
Example: critiq rules explain
Take ts.security.ssrf, server-side request forgery, from the OSS catalog. The rule matches outbound calls where the target can be attacker-controlled or private-network reachable. Its metadata cites CWE-918 and OWASP SSRF guidance. Running explain on the rule file prints the parsed contract, semantic validation result, normalized JSON, declared references, and template variables used in message strings:
# From a checkout of critiq-rules, or the path under node_modules after install:
critiq rules explain libs/rules/catalog/rules/typescript/ts.security.ssrf.rule.yamlPretty output includes sections you can skim without reading the entire YAML:
Parsed Summary
Path: .../ts.security.ssrf.rule.yaml
Rule ID: ts.security.ssrf
Title: Server-side request forgery
Summary: Outbound requests should not use attacker-controlled targets or private hosts.
...
References
- cwe CWE-918 (Server-Side Request Forgery (SSRF))
- owasp (Server-Side Request Forgery) -> https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
Inferred Template Variables
emit.message.title
- ${captures.ssrfCall.text} (...)
emit.message.summary
- ${captures.ssrfCall.text} (...)That is the transparency bar: the same references your security team expects in a ticket appear in the rule file and in explain output. If remediation text changes, ruleHash does not, so historical SARIF or JSON artifacts remain comparable.
Community extensibility
Open-sourcing the engine is only half the story. The other half is letting teams extend Critiq without waiting on our release train. Local custom rules under .critiq/rules/ use the same DSL and the same validate / test / explain commands as the public catalog. RuleSpec fixtures (.spec.yaml) pair invalid and valid source snippets with expected findings, the same harness critiq-rules uses in CI.
We publish maintained examples in critiq-rules (simple node.where rules, path-scoped config rules, negated matches) and document the workflow on docs.critiq.dev. If you outgrow inline rules, you can package a catalog and point .critiq/config.yaml at it, the runtime is catalog-first by design.
Contributions back to @critiq/rules flow through the critiq-rules repository: new rules need references for security categories, detection kind set correctly, and specs that prove both positive and negative cases. That gatekeeping is public too, catalog-rules.spec.ts enforces reference coverage so security findings always cite CWE, OWASP, or an equivalent reference.
We welcome issues and pull requests on critiq-core, critiq-rules, and critiq-action. For Pro catalog changes, the critiq-pro repository stays private, but the OSS contracts (DSL schema, fact kinds, CLI behavior) evolve in the open so adapters do not become secret handshakes.
Where to go next
If you have not run Critiq locally yet, start with a check and one explain call on a rule that fires in your codebase. Read the normalized output and the references block. Decide whether the finding matches your threat model, that loop is the product.
npx @critiq/cli check .
critiq rules explain node_modules/@critiq/rules/rules/typescript/ts.security.ssrf.rule.yamlDocs live at https://docs.critiq.dev/, CLI reference, first-rule guide, and the generated OSS catalog browser. The critiq-core, critiq-rules, and critiq-action repositories on GitHub hold the source. We will keep publishing engineering notes here when the DSL, catalog, or boundaries between OSS and Pro change. Inspect first; integrate when the output earns it.
More from the blog

- philosophy
The trust gap in AI-assisted coding, and what inspectable feedback looks like
Developers use AI assistants daily but often distrust review feedback. Inspectable rules, evidence, and local checks close that gap.
Read article
- philosophy
What evidence over vibes means in code review
Review comments should be defensible: tied to a rule, a line, severity, and references, not just confident prose.
Read article
- guides
Your first critiq check: reading pretty output like a senior review
Install the OSS CLI, run your first scan, and learn to read severity, rule IDs, file paths, and fix suggestions in pretty and JSON output.
Read article