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

Configuration

jevgate init writes a commented jevgate.toml at the repository root. The command line wins over the file, except that upload patterns and budgets in the file are ceilings that flags can only narrow. Unknown keys are errors. Its first line points editors with TOML schema support (Even Better TOML, Taplo) to jevgate.schema.json, which completes keys, rule names and levels and flags mistakes as you type.

upload_allow = ["src/**", "tests/**"]   # only these paths may be uploaded
upload_deny = ["**/.env*", "**/*.pem", "**/*.key"]
include_tests = true
max_cost = 1.00                          # dollars a check may spend; a whole-repository check costs a few cents

[rules]                                  # a level per group or rule
maintainability = "review"               # judge the group's default rules, and fail on their reviews
tests = "review"
security = "mature"                      # opt-in group, enabled by naming it; fails only on levels measured mature
"maintainability/hardcoded-values" = "report"   # an opt-in rule runs only when named: judge but never fail; "off" skips it

[[scope]]                                # levels for the files these paths match
paths = ["scripts/**", "tools/**"]
fail_on = ["report"]                     # every rule: judge, never fail
rules = { security = "review" }          # except these
KeyDefaultMeaning
upload_allowevery pathGlobs of the paths that may be uploaded, including instruction files and context
upload_denynoneGlobs never uploaded, even when allowed
generatedbuilt-in namesGlobs of generated files, which are skipped
testsbuilt-in conventionsGlobs of additional test files
contextnoneFiles always sent as related evidence, like --context
rulesthe default groupA list selects rules. A table gives each group or rule a level: review (every new finding), mature, uncertain, report (judge, never fail) or off, and consider, the same as review; a level for a group judges the rules it runs by default (maintainability leaves out the opt-in hardcoded values, which runs only when named), and every rule of a group with none on by default, such as security
[[scope]]nonepaths (globs), with fail_on for every rule and rules for rules or groups, as above; off is not accepted (use upload_deny). The last scope that matches a file and addresses a rule wins; flags win over scopes
fail_on["mature"]The level for rules without their own, like --fail-on
include_testsfalseJudge tests, like --include-tests
modelthe key’s provider’sThe model, as the key’s provider names it: jev-1.13.0 for TypeSafe, typesafe/jev-1.13 for OpenRouter, typesafe-ai/jev for Vercel AI Gateway. A pinned version keeps results repeatable; a repository that sets it for one provider needs --model with another provider’s key
cache_ttl_secs3600Cache lifetime for an alias: a model name without an x.y.z version, such as jev-latest or jev-1.13. Pinned versions such as jev-1.13.0 never expire
max_requestsunlimitedCeiling on API attempts per invocation; --max-requests can only lower it. A whole-repository check asks about one request per file, and more with opt-in rules, so a ceiling sized for pull requests stops it: a check that will not fit says so before its first request. Prefer max_cost to bound spend
max_seconds60 with --staged and --pre-push, else unlimitedCeiling on the seconds a check asks for: no request starts, and no retry waits, past it, and what is left unasked leaves the run incomplete; --max-seconds can only lower it
max_costunlimitedCeiling on a check’s estimated spend in dollars: each request is priced from its size before it is sent, stderr says when 75% and 90% are spent, and what would pass it is left unasked, leaving the run incomplete; --max-cost can only lower it
on_incomplete"pass" with --staged and --pre-push, else "fail"What a run that cannot finish exits with, like --on-incomplete: "fail" exits 2; "pass" exits 0 and says on stderr that the change was not checked, and why (Git hooks)
concurrency6, or 3 with a gateway’s keyMost simultaneous requests; --concurrency can only lower it. JevGate sends at most 6 at once, so a higher value, which releases before 0.26 accepted up to 8, means 6, and --concurrency above 6 is lowered to 6 with a notice. Requests also start at least 50 ms apart, TypeSafe’s limit of 1,200 a minute for an account. With an OpenRouter or Vercel AI Gateway key the default is 3: the gateway’s account on TypeSafe is shared by its other customers
max_file_bytes262144Files larger than this are reported as needs-context, never truncated; generated and vendored files are skipped instead
max_context_bytes32768Ceiling on context bytes per request
[[question]]noneA custom question: id, question, background, guidance, unit, paths, threshold, level and next_step, and its failing and passing examples, which jevgate rules test asks. .jevgate/questions/<id>.toml holds one per file

Rules are named by ID (maintainability/shared-logic), key (shared_logic) or group (maintainability, tests, security, documentation, custom, default, all). A custom question is named custom/<id>. The same names work in --rule, --skip-rule and --fail-on TARGET=LEVEL, and the most specific entry wins.

What fails the check by default

The default level, mature, fails the check only on the rules and levels measured mature: their findings were right at least 80% of the time on projects JevGate was never tuned on, over at least 20 findings labeled from the code. Every finding is reported as a review, and the level read here is the one its measured questions composed. Today those are function-simplification split reviews (20 of 23 right) and, when the documentation rules run, agent-context findings composed as considers (22 of 24). Look-here findings are not yet measured. A finding in a preview language, such as Kotlin or Swift, never fails it: those languages’ rules and levels are measured apart, and none is mature yet. A custom question fails it at its own level, since its author chose that level and JevGate cannot measure a team’s question on other projects. Every other finding is reported and marked as still being measured, without failing the check. jevgate rules shows each rule’s levels that fail by default and how often they were right, and accuracy gives every rule and level’s labels and how they are made.

Any level you set replaces the default exactly as it says, for the rules and paths it addresses: fail_on = ["review"] (or --fail-on review) fails on every new finding; --fail-on security=review sets one group and leaves the others at mature; mature itself can be set, such as for one group after a stricter fail_on. A later release can mark more levels mature as labels accumulate, or fewer; set fail_on to keep a fixed policy. Undecided answers never fail the check under mature.

A jevgate.toml written by jevgate init before 0.26 sets maintainability = "review" and tests = "review": those lines keep every review of the two groups failing the check, and judge hardcoded values. Delete them for the default rules and gate. While they are there with the comments init wrote after them, every command that reads jevgate.toml says so on stderr; to keep the levels, delete the comments.

Keys and where requests go

jevgate.toml has no key for the provider or its address: the change under review can edit that file, so it must not be able to send your key elsewhere. The provider follows the key (Install lists the three kinds), and a key goes only to its own provider. JEVGATE_BASE_URL, read only from the environment, replaces the provider’s API root for a self-hosted proxy or a test server: https:// to any host, or http:// only to localhost, 127.0.0.1 or [::1]. Each check says on stderr when it is set, and jevgate auth status checks the key against <root>/v1/models there.

The configuration reference lists every key with its type, and the rule names and levels it accepts.