Command-line reference
Generated from --help (jevgate 0.35.0). jevgate man COMMAND prints the same text as a man page.
jevgate
Code review gate that asks TypeSafe Jev small, literal questions about your code
JevGate parses the repository locally and builds small evidence units: a function, a file outline, a pair of copies, a test, a documentation section. It asks TypeSafe Jev short, typed questions about each one, and code, not a chat model, composes the answers into findings. Each finding has a location, how often findings like it were right and a next step, and undecided answers are reported as uncertain instead of hidden.
Rule groups: maintainability (on by default, except hardcoded values), tests (with --include-tests), the opt-in security and documentation groups, and custom: a team's own conventions, written as questions. By default only rules and levels measured right at least 80% of the time on projects JevGate was never tuned on fail the check, never in a preview language, and custom questions at their own level.
Usage: jevgate <COMMAND>
Commands:
auth Save, inspect or remove your API key: TypeSafe, OpenRouter or Vercel AI Gateway
check Review code with TypeSafe Jev; exit 1 when the gate fails, 2 when the run is incomplete
baseline Accept the findings of the last complete check, so later checks fail only on new ones
rules List every rule with its default, the levels that fail the check by default, and its question
init Write a commented jevgate.toml, or set up a coding agent's hooks or a Git hook (offline)
completions Print a shell completion script (offline)
man Print a man page in roff (offline)
mcp Run a Model Context Protocol server on stdin and stdout, for coding agents
hook Answer one coding-agent hook event read on stdin; always exits 0
serve Serve the latest report as read-only JSON on localhost (run alongside `check --watch`)
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
Workflow:
jevgate init Write jevgate.toml: upload scope, rules and gate
jevgate auth login Save an API key: TypeSafe, OpenRouter or Vercel AI Gateway
jevgate check --dry-run --show-requests Print every request body; no key, no network
jevgate check Review and apply the gate
jevgate baseline Accept current findings; later checks fail only on new ones
jevgate baseline --merge Accept a partial check's findings, keeping the rest
jevgate baseline mark wrong PATH[:LINE] Dismiss a finding with a reason; `baseline stats` counts them
jevgate rules propose Propose custom questions from AGENTS.md and other instruction files
jevgate rules add NAME Add a measured custom question from the gallery
For agents, Git hooks and CI:
jevgate init --agent claude Hooks for Claude Code (also codex, cursor, gemini, opencode)
jevgate init --git-hook pre-push A Git hook that judges what each push sends
jevgate check --base origin/main Only what changed since a revision
jevgate check --base origin/main --format json The full report, raw probabilities included
jevgate check --base origin/main --format github Annotations and a job summary on GitHub
jevgate rules --format json Every rule and the question it asks
jevgate hook Answer a coding agent's hook event read on stdin
jevgate rules test Custom questions against their examples
Exit codes:
0 Gate passed, or no supported file changed since --base; also a run that could not
finish when --on-incomplete passes it, as it does by default with --staged and
--pre-push, saying so on stderr
1 Gate failed
2 Run incomplete (no key, provider rejection, a budget reached), invalid
configuration or invalid usage
128+N Interrupted by signal N
`jevgate hook` always exits 0: agents read 2 as a block, so its JSON reply says what happened
Files (at the repository root):
jevgate.toml Configuration; `jevgate init` writes a commented one
jevgate-baseline.json Accepted findings; commit it
.jevgate/questions/ Custom questions, one per file; commit them
.jevgate/cache/ Answers by state and question; safe to restore and save in CI
.jevgate/latest.json The last report, the same JSON as --format json
.jevgate/report.html HTML dashboard, with --report
Environment:
TYPESAFE_API_KEY A TypeSafe key; wins over --env-file, .env and the saved key
OPENROUTER_API_KEY An OpenRouter key, used when no key comes from those
AI_GATEWAY_API_KEY A Vercel AI Gateway key, used when neither comes first
JEVGATE_BASE_URL Send requests to this API root instead (https, or http to localhost),
for a self-hosted proxy; never read from jevgate.toml or .env
JEVGATE_CREDENTIAL_STORE Where `auth login` saves: auto, keyring or file
JEVGATE_CONFIG_DIR Absolute directory for file-stored credentials
CI When set, --report writes the dashboard without opening a browser
NO_COLOR, CLICOLOR_FORCE Turn agent output color off or on where --color is auto
`jevgate <command> --help` explains each command; -h prints a summary. `jevgate completions SHELL`
and `jevgate man [COMMAND]` print shell completions and man pages.
jevgate auth
Save, inspect or remove your API key: TypeSafe, OpenRouter or Vercel AI Gateway
A check uses the first key it finds: TYPESAFE_API_KEY in the environment; then the file named by `check --env-file` (TYPESAFE_API_KEY, OPENROUTER_API_KEY or AI_GATEWAY_API_KEY), else TYPESAFE_API_KEY in the repository's `.env`; then the key saved by `jevgate auth login`; then OPENROUTER_API_KEY or AI_GATEWAY_API_KEY in the environment, which other tools read too. The key goes only to its own provider. In CI, set one variable from a secret; nothing needs to be saved.
Usage: jevgate auth <COMMAND>
Commands:
login Validate an API key from TypeSafe, OpenRouter or Vercel AI Gateway and save it for every repository
status Show which credential a check would use; exit 0 when it works, 2 otherwise
logout Remove saved credentials; environment variables and repository .env files are left alone
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate auth login Asks the kind of key, then a hidden prompt
jevgate auth login --with-key < key.txt Read a TypeSafe key from stdin
jevgate auth login --with-key --provider openrouter < key.txt
jevgate auth status Show which key a check would use and verify it
jevgate auth status --offline --json Same, without contacting the provider
jevgate auth logout
jevgate check
Review code with TypeSafe Jev; exit 1 when the gate fails, 2 when the run is incomplete
Parses the selected files locally, sends small evidence units (a function, a file outline, a pair of copies, a test, a documentation section, a code comment) with short questions, and composes the answers into findings. Unchanged units are answered from `.jevgate/cache`, so a re-run only pays for what changed. Every run writes the full report to `.jevgate/latest.json`, whatever the output format.
Every finding is a `review`: a place worth a look, to fix when it is right or dismiss with a reason (`jevgate baseline mark`). A file whose answers stay undecided is `uncertain`; one that cannot be judged without more evidence is `needs-context`.
Settings resolve in this order: flags, then `jevgate.toml`, then defaults. Upload patterns and budgets in the file are ceilings that flags can only narrow.
Usage: jevgate check [OPTIONS] [PATHS]...
Arguments:
[PATHS]...
Files or directories to review [default: discovered application source]
Without paths, JevGate walks the repository (respecting .gitignore) and selects application source in Rust, Python, JavaScript, TypeScript, Go, C#, Ruby, PHP, Java and Bend 2 (and, in preview, C, C++, Kotlin, Swift, Bash, Dart, Scala, Elixir and Lua), the scripts of Astro, Vue and Svelte files, and server templates (ERB, EJS, JSP, Handlebars, Jinja and others) that hold inline scripts or code reading the request. Tests, generated code and vendored files are classified and skipped with a reason. `upload_allow`/`upload_deny` in jevgate.toml still bound what is sent.
Options:
-h, --help
Print help (see a summary with '-h')
Scope:
--base <REVISION>
Review only what changed against this Git revision (commit, branch or tag)
Compares with the fork point, as a pull request diff does, and includes committed, staged, unstaged and untracked changes. Only what the change touches is asked about and reported: functions, tests, comments and values on changed lines, copies where either copy changed, a file's outline when the change adds members to it, and documents naming a path it deleted or renamed. A new file is judged whole. Deleted files are listed in the report. The revision must exist locally: in CI, check out with full history (for example `fetch-depth: 0`). When no supported file changed, the run is complete and exits 0.
--staged
Review only what is staged: the change a commit records, for a pre-commit hook
Compares the index with HEAD, and never reads untracked files; in a hook, the index Git is committing, which for `commit -a` or `git commit PATHS` is a temporary one. The files the change touched are read as staged, so a file staged in part with `git add -p` is judged as it will be committed; other files read as evidence come from disk. A commit that concludes a merge is judged for how the person resolved it, not for the merged branch's changes. Only what the change touches is asked about and reported, as with --base. When the run cannot finish, the commit goes through and JevGate says so (--on-incomplete), within 60 seconds by default (--max-seconds).
--pre-push
Review what a push sends, for a pre-push hook: the refs Git passes it on stdin
Each pushed commit is compared with the last commit on its first-parent line that a remote already has: a branch pushed before with its last push, a new or rebased branch with where it leaves the remote's history. Files are read as committed, not as the working tree holds them. Under pre-commit or prek, the ref they pass (PRE_COMMIT_TO_REF) is read instead; run on a terminal, the current branch. A ref none of whose history is on a remote is not checked, and a line says so. When the run cannot finish, the push goes through and JevGate says so (--on-incomplete), within 60 seconds by default (--max-seconds).
--whole-files
With --base, --staged or --pre-push, judge each changed file whole, not only what the change touches
--include-tests
Also judge tests: test value, redundancy, and shared logic among tests
Without it, test files are judged only for file organization. Test files of the preview languages are not judged either way. Also set by `include_tests = true` in jevgate.toml.
--context <PATH>
Related file sent as evidence for shared logic, callers and test subjects (repeatable)
The file must be inside the repository and is sent only with the requests it informs. Also set by `context` in jevgate.toml.
--source-extension <EXT>
Also review this file extension as text (repeatable, without the dot)
--config <FILE>
Read this configuration instead of <repository root>/jevgate.toml
The repository root is still found from the working directory. Use it in CI to apply a reviewed policy that the change under review cannot edit. The custom question files of .jevgate/questions/ are then not read, since the change could edit them too; --questions reads a reviewed copy.
--questions <DIR>
Read custom question files from this directory instead of .jevgate/questions/
With --config, give a reviewed copy of the questions directory, such as the base revision's, so the change under review cannot edit a question to pass.
Rules and gate:
--rule <RULE>
Select a rule ID, name, key or group (repeatable) [default: the `default` group]
Groups: maintainability, tests, security, documentation, custom (the custom questions; one is `custom/<id>`), default (every rule on by default) and all. A group selects the rules it runs by default, or every rule of it when it runs none by default (security, documentation), so hardcoded values runs only when named or with `all`. Naming any rule replaces the configured selection, so add `--rule default` to keep the defaults. Test rules also need --include-tests. `jevgate rules` lists every rule.
--skip-rule <RULE>
Deselect a rule ID, name, key or group (repeatable); applied after --rule and jevgate.toml
--fail-on <[TARGET=]LEVEL>
What fails the gate: LEVEL for every rule, or TARGET=LEVEL (repeatable) [default: mature]
LEVEL is review (every new finding; `consider` is the same), mature, uncertain, or none (advisory; `report` is accepted as a synonym). `mature` fails only on the levels of a rule measured right at least 80% of the time on projects JevGate was never tuned on, as its questions composed them, never in a preview language, and on a custom question's own level (`jevgate rules` shows them); other findings are reported without failing. TARGET is a rule ID, key or group, for example `security=review`; the most specific target wins. Flags replace `fail_on` and `[rules]` levels from jevgate.toml for the rules they address. Baselined and dismissed findings, and a custom question's notes, never fail the gate. An incomplete run exits 2 regardless of the gate, unless --on-incomplete passes it.
--on-incomplete <WHEN>
When the run cannot finish: pass (exit 0) or fail (exit 2) [default: pass with --staged and --pre-push, else fail]
A run that could not judge everything, for want of a key, after an HTTP 402, with a provider that stopped answering or at a budget, fails with exit 2 by default, so CI never passes on partial evidence. With --staged and --pre-push it passes by default, so an outage never holds a commit or a push; stderr then says the change was not checked, and why. Also set by `on_incomplete` in jevgate.toml.
Possible values:
- pass: Exit 0, saying on stderr that the change was not checked, and why
- fail: Exit 2
Output:
--format <FORMAT>
Output format [default: agent; jsonl with --watch; json with --show-requests]
Possible values:
- agent: Ranked findings with locations and next steps, for people and coding agents
- json: The full report as one pretty-printed JSON document
- jsonl: One compact JSON report per line; one per evaluation while watching
- github: GitHub Actions annotations and a job summary, then the agent text
- sarif: A SARIF 2.1.0 log, for GitHub code scanning and other SARIF readers
- gitlab: A GitLab Code Quality report, for merge request widgets
--color <WHEN>
Color agent output: auto, always or never
`auto` colors a terminal unless NO_COLOR is set, and any output when CLICOLOR_FORCE is set; on Windows, only Windows Terminal and terminals that set TERM count. Other formats are never colored.
Possible values:
- auto: On a terminal, unless NO_COLOR is set; CLICOLOR_FORCE turns it on elsewhere
- always
- never
[default: auto]
--verbose
Show every finding and per-file detail in agent output
--report
Also write .jevgate/report.html and open it in a browser (not opened when CI is set)
--dry-run
List the selected files, rules and planned requests without credentials, network or writes
Planned first-pass requests and questions the cache already answers are counted apart and cost nothing: a request sends only the questions the cache lacks. Follow-ups depend on the answers and are not known.
--show-requests
With --dry-run, include every initial request body (the exact source and questions)
Follow-up requests depend on answers and are not known in advance.
Model, budgets and cache:
--model <MODEL>
Model, as the key's provider names it; pin a version for repeatable results [default: the key's provider's model]
The default follows the key: jev-1.13.0 with a TypeSafe key, typesafe/jev-1.13 with an OpenRouter key, typesafe-ai/jev with a Vercel AI Gateway key. Also set by `model` in jevgate.toml. Answers are cached per model, so changing it re-asks every unit.
--max-requests <N>
Stop after this many API attempts in this invocation, watch updates included
Reaching the budget leaves the run incomplete (exit 2) rather than passing on partial evidence. `max_requests` in jevgate.toml is a ceiling this flag can only lower.
--max-seconds <SECONDS>
Stop asking after this many seconds; what is left unasked leaves the run incomplete [default: 60 with --staged and --pre-push]
No request starts, and no retry or pause runs, past it, and an attempt under way gets only the time left. The answers received are kept in the cache, so a rerun asks only for the rest. `max_seconds` in jevgate.toml is a ceiling this flag can only lower.
--max-cost <DOLLARS>
Stop asking before the estimated spend passes this many dollars; what is left unasked leaves the run incomplete
Each request is priced from its size before it is sent, at the model's price, and stderr says when 75% and 90% of the budget are spent. Answers from the cache cost nothing. `max_cost` in jevgate.toml is a ceiling this flag can only lower.
--concurrency <N>
Maximum simultaneous requests, at most 6; a higher value is lowered to 6 [default: 6, or 3 with a gateway's key]
The default follows the key: 6 with a TypeSafe key, 3 with an OpenRouter or Vercel AI Gateway key. Also set by `concurrency` in jevgate.toml, which this flag can only lower.
--max-file-bytes <BYTES>
Per-file read limit; a larger file is reported as needs-context, never truncated
[default: 262144]
--max-context-bytes <BYTES>
Total bytes of --context files per request; context is never truncated
[default: 32768]
--cache-ttl-secs <SECONDS>
Cache lifetime for an alias, a model name without an x.y.z version such as jev-latest [default: 3600]
Answers from a pinned model version, such as jev-1.13.0, never expire. Also set by `cache_ttl_secs` in jevgate.toml.
--refresh
Ignore the answers cached before this invocation and ask again
--cache-only
Use cached answers only and never contact the provider; unanswered units leave the run incomplete
--env-file <FILE>
Credential file holding TYPESAFE_API_KEY, OPENROUTER_API_KEY or AI_GATEWAY_API_KEY [default: <repository root>/.env]
TYPESAFE_API_KEY in the environment takes precedence; the file comes before the saved key and a gateway's variable in the environment. The repository's .env is read only for TYPESAFE_API_KEY: a gateway's key there is usually the application's own.
Watch:
--watch
Keep running and re-check the selected files after each save
Writes .jevgate/latest.json after every evaluation and prints one JSON report per line. Pair with `jevgate serve` or --report.
--debounce-ms <MS>
Wait this long after the last save before evaluating
[default: 500]
--poll-ms <MS>
How often to look for saves
[default: 250]
Examples:
jevgate check Discovered application source, default rules
jevgate check src/billing --verbose One directory, with notes and per-file detail
jevgate check --base origin/main --format json Only what changed, machine-readable
jevgate check --base origin/main --whole-files Every unit of each changed file
jevgate check --staged What a commit records, for a pre-commit hook
jevgate check --pre-push What a push sends, for a pre-push hook
jevgate check --rule default --rule security Add the opt-in security group
jevgate check --rule documentation Agent instruction files, project docs and code comments
jevgate check --rule comments Only code comments: repeated code, filler, narrated edits
jevgate check --include-tests Also judge test value and redundancy
jevgate check --fail-on none Advisory: never exits 1; exits 2 when incomplete
jevgate check --fail-on review Fail on every finding, not only on mature rules
jevgate check --fail-on mature --fail-on security=review
jevgate check --dry-run --show-requests Exactly what would be uploaded, offline
jevgate check --cache-only Replay cached answers; never contact the provider
jevgate check --max-seconds 30 --max-cost 0.10 Stop asking after 30 s or 10 cents; incomplete then
jevgate check --on-incomplete pass Exit 0 when the run cannot finish, saying so on stderr
Reading the JSON report (--format json or .jevgate/latest.json):
complete false when any selected file was not judged; the exit code is then 2,
or 0 when --on-incomplete passes it
scope whole-files, or changed-lines when --base judged what changed
staged true when --staged judged the index; pushed_revision: the
commit --pre-push judged, from base_revision
gate passed, reasons, new_findings, baselined_findings
fail_on the gate levels; fail_on_mature says what `mature` stands for
files[].status clear, review, uncertain, needs-context, not-applicable,
skipped or error
files[].findings rule, strength (review), measured_as (the level its
measured questions composed; none for a look-here
finding), line, message, action, locations,
concern_probability, fingerprint, baselined; precision:
right of labeled findings of its rule and level on
projects never used for tuning; preview: the preview
language whose labels those are; and gate: fails,
measuring (its rule and level are still being
measured, or its language is in preview) or advisory
(below the level in force)
files[].dimensions per rule: status, unit counts and the units left undecided
files[].judgments every raw answer, first pass and follow-ups
api_requests, paid_input_tokens, paid_output_tokens this run's usage
paid_models input tokens by the model that answered them
estimated_usd this run's cost; null when a response reported no usage
(unmetered_requests) or the model has no known price
jevgate baseline
Accept the findings of the last complete check, so later checks fail only on new ones
Writes `jevgate-baseline.json` at the repository root from `.jevgate/latest.json`. Commit the file. Findings are matched by a fingerprint of rule, path, unit and evidence, so unrelated edits keep them accepted. Offline: no source is read or sent.
A single finding can instead be accepted in the code, with a comment `jevgate: allow(RULE) reason` on its line or directly above it.
Each accepted finding can record why it was accepted: `intended` (right about the code, which is meant to be this way), `later` (right, to fix later) or `wrong` (the finding is mistaken). `baseline stats` turns these reasons into each rule's rate of wrong findings.
Usage: jevgate baseline [OPTIONS]
jevgate baseline <COMMAND>
Commands:
mark Dismiss findings with a reason, or record why accepted ones were accepted
list List accepted findings with their reason, rule, location, unit, fingerprint and note
stats Count accepted findings by rule and reason, with each rule's rate of wrong findings
help Print this message or the help of the given subcommand(s)
Options:
--merge
Keep earlier accepted findings for files the last check did not cover
Without it, the file is replaced, so after a `--base` or path-limited check the findings accepted for every other file are dropped. With it, entries for files the check covered, or that were deleted, are replaced by what the check found, and the rest are kept. A `--base` check that judged only what its change touched covers only the deleted files: the other entries of the files it checked stay.
--reason <REASON>
Record this reason on findings accepted now without one
Findings already accepted keep the reason they have.
Possible values:
- intended: The finding is right; the code is meant to be this way
- later: The finding is right; it will be fixed later
- wrong: The finding is mistaken
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate baseline Accept every finding of the last check
jevgate baseline --merge --reason later Accept a partial check's findings as known debt
jevgate baseline mark wrong src/api/search.ts:41 A mistaken finding
jevgate baseline mark intended scripts --rule maintainability/hardcoded-values
jevgate baseline mark later --note "#192" src/api/search.ts:41
jevgate baseline list --reason later --format md A checklist for a cleanup issue
jevgate baseline stats Wrong findings per rule
jevgate rules
List every rule with its default, the levels that fail the check by default, and its question
A rule is named by its ID (`maintainability/shared-logic`), its key (`shared_logic`) or its group (`maintainability`, `tests`, `security`, `documentation`, `custom`, plus `default` and `all`) anywhere a rule is accepted: `--rule`, `--skip-rule`, `--fail-on TARGET=LEVEL` and `[rules]`. A custom question is named `custom/<id>`.
Each rule shows how often the reviews and considers its measured questions composed were right on projects JevGate was never tuned on, from findings labeled from the code; a look-here question's findings are not yet measured. The levels right at least 80% of the time over at least 20 labels are mature: by default only they fail the check (`--fail-on mature`), never in a preview language, with each custom question at its own level in every language, and the other findings are reported without failing it.
`rules test` asks custom questions about their examples, `rules propose` proposes custom questions from the project's agent instruction files, `rules accept` adds a proposal to them, and `rules add` copies measured custom questions from the gallery.
Usage: jevgate rules [OPTIONS]
jevgate rules <COMMAND>
Commands:
test Ask custom questions about their examples; exit 1 when one gets an example wrong, 2 when incomplete
propose Propose custom questions from the lines of AGENTS.md and the other agent instruction files
accept Accept proposed questions: check each one and move it to .jevgate/questions/
add Add measured questions from JevGate's question gallery to .jevgate/questions/
help Print this message or the help of the given subcommand(s)
Options:
--format <FORMAT>
`table` for people; `json` adds scope, evidence unit, version, labels per level and decision policy
[default: table]
[possible values: table, json]
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate rules Every rule and custom question
jevgate rules --format json With scope, evidence unit, version and policy
jevgate rules test Ask custom questions about their examples
jevgate rules test --rule custom/no-body-logs One question's examples
jevgate rules propose Propose questions from agent instruction files
jevgate rules accept no-body-logs Move a proposal into .jevgate/questions/
jevgate rules add swallowed-errors Add a measured question from the gallery
jevgate rules test
Ask custom questions about their examples; exit 1 when one gets an example wrong, 2 when incomplete
A question's `failing` examples are code that breaks its rule: the answer about each must reach the question's threshold, so a check would find it. Its `passing` examples are code that keeps the rule: the answer must stay below the threshold. Each example is asked as a check asks the same units, and answers are cached like a check's: a rerun is free, and a new model or a reworded question asks again, so a question that stops separating its examples fails here before it misleads a check.
Usage: jevgate rules test [OPTIONS]
Options:
--rule <RULE>
A custom question, `custom/<id>`, or the group `custom` (repeatable) [default: every question with examples]
--format <FORMAT>
`table` for people; `json` for scripts, with every unit's probability
[default: table]
[possible values: table, json]
--dry-run
Count the requests the examples need and those the cache answers, without credentials, network or writes
Every example is still read and its units found, so an example that cannot be asked exits 2 here too.
--model <MODEL>
Model, as the key's provider names it [default: `model` in jevgate.toml, else the key's provider's model]
Answers are cached per model, so another model asks every example again: try the examples on a model before pinning it.
--refresh
Ignore cached answers for this invocation and ask again
--cache-only
Use cached answers only and never contact the provider; an example without one leaves the run incomplete
--max-requests <N>
Stop after this many API attempts; reaching it leaves the run incomplete
--env-file <FILE>
Credential file holding TYPESAFE_API_KEY, OPENROUTER_API_KEY or AI_GATEWAY_API_KEY [default: <repository root>/.env]
Read as `check` reads it: TYPESAFE_API_KEY in the environment takes precedence, and the repository's .env is read only for TYPESAFE_API_KEY.
--config <FILE>
Read this configuration instead of <repository root>/jevgate.toml
As for `check`, the question files of .jevgate/questions/ are then not read; --questions reads a reviewed copy.
--questions <DIR>
Read custom question files from this directory instead of .jevgate/questions/
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate rules test --dry-run Requests and new tokens, offline; every example checked
jevgate rules test Exit 1 when a question gets an example wrong
jevgate rules test --model jev-latest Try the examples on another model before pinning it
jevgate rules test --format json Every unit's probability, for scripts
jevgate rules propose
Propose custom questions from the lines of AGENTS.md and the other agent instruction files
Splits each instruction file into lines and list items and asks TypeSafe Jev of each whether it states a rule for how the code is written that one piece of it shows, and which piece: a function, test, comment, documentation section, file or change; then, of each rule, whether a reviewer checks it or a formatter, linter or script already does. Each rule a reviewer checks becomes a custom question that quotes the line and cites its file and line, written to `.jevgate/proposals/` (which Git ignores) as a note. Read one, edit it, then accept it with `jevgate rules accept ID`; nothing reaches the configuration otherwise. Answers are cached, so a rerun pays only for changed lines, and it never overwrites a proposal or proposes a line that is already a question.
Usage: jevgate rules propose [OPTIONS] [PATHS]...
Arguments:
[PATHS]...
Instruction files or directories to read [default: every instruction file an agent loads]
A directory selects the agent instruction files under it. A file is read whatever its name, such as CONTRIBUTING.md. Translations under a locale directory (`docs/i18n/ja/CLAUDE.md`) are read only when named.
Options:
--format <FORMAT>
Output format [default: table; json with --show-requests]
Possible values:
- table: Write the proposals to .jevgate/proposals/ and list them
- toml: Print the proposals as [[question]] tables to paste into jevgate.toml, instead of writing them
- json: Write the proposals to .jevgate/proposals/, and print every line with its answers and proposal
--dry-run
List the files, lines and planned requests without credentials, network or writes
Requests the cache already answers are counted apart and cost nothing. What checks each rule is asked only after the answers, so it is not counted.
--show-requests
With --dry-run, include every request body (the exact lines and questions)
--cache-only
Use cached answers only and never contact the provider; a line without one leaves the run incomplete
--max-requests <N>
Stop after this many API attempts; reaching it leaves the run incomplete
--env-file <FILE>
Credential file holding TYPESAFE_API_KEY, OPENROUTER_API_KEY or AI_GATEWAY_API_KEY [default: <repository root>/.env]
Read as `check` reads it: TYPESAFE_API_KEY in the environment takes precedence, and the repository's .env is read only for TYPESAFE_API_KEY.
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate rules propose --dry-run Files, lines and price; no key, no network
jevgate rules propose Write proposals to .jevgate/proposals/
jevgate rules propose AGENTS.md docs/STYLE.md Only these files
jevgate rules propose --format toml Print [[question]] tables for jevgate.toml
jevgate rules propose --format json Every line with Jev's answers
jevgate rules accept never-log-request-bodies Accept one after editing it
jevgate rules accept
Accept proposed questions: check each one and move it to .jevgate/questions/
Each ID names `.jevgate/proposals/ID.toml`, which must be a valid question file whose id no other question uses. Commit the moved file. A proposal is a note, which never fails the gate, until its `level` says otherwise.
Usage: jevgate rules accept <ID>...
Arguments:
<ID>...
Proposals to accept: their file names in .jevgate/proposals/, without .toml
Options:
-h, --help
Print help (see a summary with '-h')
jevgate rules add
Add measured questions from JevGate's question gallery to .jevgate/questions/
Each NAME is a custom question JevGate measured on real projects: the docs' question gallery page gives how often each was right. It is written to `.jevgate/questions/NAME.toml`, a file the project owns: adapt its guidance and paths to the code, and commit it. Like any custom question, it fails the gate at its own level.
Usage: jevgate rules add [OPTIONS] <NAME>...
Arguments:
<NAME>...
Gallery questions to add
Possible values:
- todo-without-owner: a TODO or FIXME that names neither an owner nor an issue.
- swallowed-errors: an error caught, or returned by a call, and then dropped.
- resource-leak: a file, connection, stream or lock not released on every path.
- thin-handlers: a request handler that does business work instead of delegating it.
- n-plus-one: a query or network call once per item of a loop, where one call would do.
Options:
--force
Replace question files of the same names, edits included
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate rules add swallowed-errors resource-leak Two questions, as .jevgate/questions/*.toml
jevgate check --rule custom --dry-run What they would ask, offline
jevgate check --fail-on custom=report Ask them without failing the gate while you try them
jevgate rules add --force n-plus-one Restore the gallery's wording of one
jevgate init
Write a commented jevgate.toml, or set up a coding agent's hooks or a Git hook (offline)
Without --agent or --git-hook: limits uploads to the detected source and test directories and to agent instruction files, denies credential files, and lists every rule group with its gate level. Review the file before the first paid check.
With --agent: writes the agent's hooks, which run `jevgate hook` when a turn starts, after each edit and when the turn ends, and a short text telling the agent how JevGate's findings work (a block between `<!-- jevgate:begin -->` and `<!-- jevgate:end -->` in AGENTS.md or GEMINI.md, or a rules file of its own). It merges into the files already there and changes nothing else, so running it again changes nothing, and --remove takes out only what it wrote. Every file is read before the first is written: a settings file that is not plain JSON (comments included) stops it with nothing written. It then runs the `jevgate` on your PATH, which the agent will run, and warns when that one cannot answer the hooks.
With --git-hook: writes `.git/hooks/pre-push` (`jevgate check --pre-push`) or `.git/hooks/pre-commit` (`jevgate check --staged`), never over a hook JevGate did not write. When JevGate cannot finish or is not installed, the hook lets the push or commit through and says so.
Usage: jevgate init [OPTIONS]
Options:
--force
Replace an existing jevgate.toml
--agent <AGENT>
Set up a coding agent instead of writing jevgate.toml (repeatable, or comma-separated)
Writes the agent's hooks, which run `jevgate hook`, and a short text telling the agent how JevGate's findings work, merged into the files already there. Your own settings (every repository) unless --project.
Possible values:
- claude: Claude Code: hooks in settings.json, instructions in rules/jevgate.md
- codex: Codex: hooks.json, and a block in AGENTS.md
- cursor: Cursor: hooks.json, and rules/jevgate.mdc in a repository
- gemini: Gemini CLI: hooks in settings.json, and a block in GEMINI.md
- opencode: OpenCode 1.x: a plugin running jevgate hook, and a block in AGENTS.md
--git-hook <HOOK>
Write a Git hook that runs JevGate before each push or commit, instead of jevgate.toml
`pre-push` runs `jevgate check --pre-push`, which judges what each push sends; `pre-commit` runs `jevgate check --staged`, which judges what each commit records. A push is the cheaper moment: it runs once for the commits it sends. The hook goes where Git reads hooks (`.git/hooks`), never over one JevGate did not write; when a hook manager keeps the repository's hooks (husky, lefthook, pre-commit), it says what to add there instead.
Possible values:
- pre-push: Before each push, judge what it sends: `jevgate check --pre-push`
- pre-commit: Before each commit, judge what is staged: `jevgate check --staged`
--project
With --agent: write the repository's agent files, for everyone who works in it
They go at the top of the Git work tree: `.claude/`, `.codex/`, `.gemini/`, `.cursor/`, `.opencode/`, AGENTS.md and GEMINI.md.
--remove
With --agent or --git-hook: take out the hooks and text JevGate wrote, and nothing else
--dry-run
With --agent or --git-hook: print what would change, and write nothing
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate init jevgate.toml for this repository
jevgate init --agent claude Claude Code's hooks, for every repository you open
jevgate init --agent codex,gemini --project This repository's Codex and Gemini CLI hooks
jevgate init --agent cursor --dry-run What would change, without writing
jevgate init --agent claude --remove Take out what JevGate wrote
jevgate init --git-hook pre-push A Git hook: judge what each push sends
jevgate init --git-hook pre-commit A Git hook: judge what each commit records
jevgate init --git-hook pre-push --remove Take the Git hook out again
Files, for your user and with --project:
claude ~/.claude/settings.json, rules/jevgate.md .claude/settings.json, .claude/rules/jevgate.md
codex ~/.codex/hooks.json, AGENTS.md .codex/hooks.json, AGENTS.md
cursor ~/.cursor/hooks.json .cursor/hooks.json, .cursor/rules/jevgate.mdc
gemini ~/.gemini/settings.json, GEMINI.md .gemini/settings.json, GEMINI.md
opencode ~/.config/opencode/plugins/jevgate.js, AGENTS.md .opencode/plugins/jevgate.js, AGENTS.md
CLAUDE_CONFIG_DIR, CODEX_HOME and XDG_CONFIG_HOME move the user files as they move the agents'.
jevgate completions
Print a shell completion script (offline)
Usage: jevgate completions <SHELL>
Arguments:
<SHELL>
bash, zsh, fish, elvish or powershell
[possible values: bash, elvish, fish, powershell, zsh]
Options:
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate completions bash > ~/.local/share/bash-completion/completions/jevgate
jevgate completions zsh > "${fpath[1]}/_jevgate"
jevgate completions fish > ~/.config/fish/completions/jevgate.fish
jevgate completions powershell >> $PROFILE
jevgate man
Print a man page in roff (offline)
Without a command, the page for `jevgate`; with one, the page for that command, such as `jevgate-check`.
Usage: jevgate man [COMMAND]
Arguments:
[COMMAND]
A command: auth, check, baseline, rules, init, serve, mcp, hook or completions
Options:
-h, --help
Print help (see a summary with '-h')
Examples:
jevgate man > ~/.local/share/man/man1/jevgate.1
jevgate man check > ~/.local/share/man/man1/jevgate-check.1
jevgate man check | man -l - Read a page without installing it (man-db)
jevgate serve
Serve the latest report as read-only JSON on localhost (run alongside `check --watch`)
Answers GET requests from local tools, never from a browser page: `/snapshot` (the full report), `/evidence` (findings and context per file), `/context-requests` (evidence a file still needs) and `/changes?since=GENERATION` (what changed since a report generation).
Usage: jevgate serve [OPTIONS]
Options:
--port <PORT>
Local port to listen on
[default: 47831]
-h, --help
Print help (see a summary with '-h')
jevgate mcp
Run a Model Context Protocol server on stdin and stdout, for coding agents
Offers three tools: `jevgate_check` runs a check in the repository and returns its findings, `jevgate_findings` reads the last report, and `jevgate_rules` lists the rules. Register it with an agent as the command `jevgate mcp`, started in the repository.
Usage: jevgate mcp
Options:
-h, --help
Print help (see a summary with '-h')
Examples:
claude mcp add jevgate -- jevgate mcp Claude Code, in the repository
{"mcpServers": {"jevgate": {"command": "jevgate", "args": ["mcp"]}}}
Clients configured with JSON, such as Cursor
jevgate hook
Answer one coding-agent hook event read on stdin; always exits 0
Configured as a hook of Claude Code, Codex, Gemini CLI, Cursor, OpenCode, Copilot CLI or VS Code, it reads the event as JSON on stdin and prints one JSON reply. VS Code names its edit tools its own way, which is not verified yet: there only the end of a turn is sure to be checked. When a turn starts, it records a snapshot of the working tree under `.jevgate/turns/`; after each edit, it checks what the turn changed in the edited files and passes the findings to the agent, never blocking; when the turn ends, it checks everything the turn changed and blocks the agent while findings fail the gate, at most 3 times a turn. Checks judge a turn as `check --base` judges a change, with the repository's jevgate.toml and key.
It always exits 0, since agents read exit 2 as a block: an outage, an HTTP 402, a missing key or a directory outside Git never blocks the agent, and the reply says so to the person and to the agent.
Usage: jevgate hook [OPTIONS]
Options:
--agent <AGENT>
The agent that runs the hook [default: detected from the event]
Possible values:
- claude: Claude Code, and Devin CLI, which loads its hooks
- codex: OpenAI Codex
- gemini: Gemini CLI
- cursor: Cursor, configured in its own hooks.json
- opencode: OpenCode, through JevGate's plugin
- copilot: GitHub Copilot CLI and VS Code, running Claude Code's hooks
--timeout <SECONDS>
Seconds before the hook gives up and lets the agent go on [default: 10 at a session or turn start, 30 after an edit, 50 at the end of a turn]
Keep it below the agent's own hook timeout: an agent that stops the hook first discards its reply, so the person is not told why.
-h, --help
Print help (see a summary with '-h')
Examples (`jevgate init --agent` writes each agent's hooks):
jevgate hook Claude Code, Codex, Gemini CLI, Copilot CLI: detected from the event
jevgate hook --agent cursor Cursor's own hooks.json
jevgate hook --agent opencode OpenCode, through JevGate's plugin
jevgate hook --timeout 20 Give up after 20 seconds, whatever the event
Claude Code and Codex run `jevgate hook || echo '{"systemMessage": …}'` and Gemini CLI
`jevgate hook; exit 0`, so a missing or older jevgate says so instead of blocking the agent.
Events: a session or turn start records the working tree (SessionStart, UserPromptSubmit,
BeforeAgent, beforeSubmitPrompt); an edit is checked (PostToolUse, AfterTool, postToolUse);
the end of a turn is checked and can be blocked (Stop, AfterAgent, stop). Others get {}.