Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 {}.