# Semgrep Desk > One Semgrep rule at a time: audited, false-positive triaged, extended with the bypass variants it > misses, and turned into a variant hunt. A free in-browser reader parses the rule YAML and walks the > pattern operator tree before any model call. Live at https://semgrep-desk.skillsafe.ai/ ## What it is for A detection engineer has written a Semgrep rule and wants to know whether it is fit to merge. The work object is one rule file — a `rules:` list, or a single rule mapping — plus, optionally, the code sample the rule is meant to fire on. Four lanes run over that same rule. ## The four lanes The app is one system prompt with a `task` router. Every request carries a `task` field. | task | What it produces | Derived from | | --- | --- | --- | | `audit` | Does the rule express its intent: an operator inventory, findings, an ordered edit plan, and the corrected rule file. | `@trailofbits/semgrep-rule-creator` | | `fp-triage` | Which matches are noise: a per-line verdict on the annotated sample, and the narrowest exclusions, applied to a complete rule file. | `@trailofbits/fp-check` | | `variants` | The shapes of the same bug the rule walks past: a bypass-vector table with honest caught-now / caught-after columns, and the extended rule. | `@trailofbits/semgrep-rule-variant-creator` | | `hunt` | Where else the bug class lives: search targets with real queries, and a Markdown hunting plan for a human to execute. | `@trailofbits/variant-analysis` | Each lane's result carries a button that hands its output — and, where that lane produced a loadable rule file, the rule itself — to the next lane. ## What the browser does for free, before any credit is spent This is not a keyword scan. `semlint.js` contains: - A YAML block parser for the subset Semgrep rule files use: block mappings and sequences, flow collections (`languages: [python]`), single- and double-quoted scalars, and all five block-scalar headers, with line numbers retained. - The pattern operator tree walked with polarity tracked, so `patterns`, `pattern-either`, `pattern-inside`, the `pattern-not*` family and the `metavariable-*` family nest correctly. - Metavariable binding sets computed per rule, separating names bound by positive patterns from names bound only inside negations. Semgrep does not export the latter, so a `metavariable-regex`, a `focus-metavariable`, a `fix` or a `message` depending on one is a silent no-op — and that is reported as such. - Structural checks that need the tree rather than a regex: a `patterns` conjunction made only of negations (matches nothing), a block whose only positive member is a `pattern-inside`, an autofix interpolating an unbound metavariable, a `mode: taint` missing sources or sinks, taint keys present without `mode: taint`, an unknown rule-level key (a typo detector). - Regexes validated as **PCRE, not JavaScript**: `(?i)` inline flags, `\A` / `\z`, atomic groups and `(?P…)` are all legal in Semgrep and are not reported as errors. - A mechanical breadth score per rule: concrete tokens weighed against statement-level ellipses, inline ellipses and disjunction branches, because `f($X, ...)` is idiomatic while a bare `...` line is what turns a rule into a shape matcher. - Semgrep's own test annotations read from the sample — `ruleid`, `ok`, `todoruleid`, `todook`, `deepruleid`, `deepok` — with an annotation naming an id no rule declares reported as an assertion that never runs. - Credential-shaped literals masked in the browser before anything is sent. Everything it finds is passed to the model as facts, and the reply is checked against them afterwards: a flag that goes unanswered, is answered twice, or is invented is named in the UI. ## The contract Input: `task`, `rule`, `sample`, `intent`, `target`, `tolerance`, `context`, `prescan_facts`, and `upstream` when a lane was handed the previous lane's output. Output: one JSON object with `lane`, `title`, `headline`, `verdict` (`ship` | `tighten` | `rewrite`), `confidence`, `summary`, `findings[]`, `steps[]`, `detail_table`, `artifact`, `coverage_check[]`, `assumptions[]`, `open_questions[]`. Full worked examples in eight languages: https://semgrep-desk.skillsafe.ai/api.html ## What it does not do It never executes a rule, never runs Semgrep, and never touches a repository. It reads text. Match counts are always stated as "would match", never as measured. ## Sources A derived work built on and crediting four published agent skills from the `@trailofbits/skills` repository: `@trailofbits/semgrep-rule-creator`, `@trailofbits/fp-check`, `@trailofbits/semgrep-rule-variant-creator` and `@trailofbits/variant-analysis`. Semgrep is a trademark of Semgrep, Inc.; this is an independent derived work and is not affiliated with Semgrep, Inc. or with those skills' authors. ## Pricing Running a lane costs credits (model `gpt-terra`, publisher markup 10%). The prescan, both bundled examples, every export and the replay of a saved run for every lane are free and need no account.