lockpicks 0.7.1 → 0.8.0-go.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # lockpicks
2
2
 
3
- Read your Lockpick results from the terminal, and give coding agents the same access over MCP: sites, scans, findings, repair briefs and recheck comparisons. If you allow it, the CLI and agents can also run a free quick check, add a site, start a Pulse scan, check a DNS finding again and prepare a Deep scan that you approve in Lockpick. Master Key scans only start in the Lockpick web app, and the CLI never cancels or deletes anything.
3
+ Read your Lockpick results from the terminal, and give coding agents the same access over MCP: sites, scans, findings, repair briefs and recheck comparisons. If you allow it, the CLI and agents can also run a free quick check, add a site, start a Pulse scan, check a DNS finding again and prepare a Deep scan that you approve in Lockpick. They can also keep a site's auto-checks on a schedule, share a Pulse result at a public link and save a scan as a PDF. Master Key scans only start in the Lockpick web app, and the CLI never cancels a scan or deletes a site or result.
4
4
 
5
5
  ## Sign in
6
6
 
@@ -22,51 +22,74 @@ Use HTTPS for a remote Lockpick host; a host without a scheme (`lockpick.app`) m
22
22
 
23
23
  ## Commands
24
24
 
25
- | Command | What it shows |
26
- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
27
- | `lockpick whoami` | The user, workspace and key this terminal uses |
28
- | `lockpick doctor` | Checks Node.js, the selected host, connection, key, workspace and agent API without starting a scan |
29
- | `lockpick projects` | Projects with their latest Pulse and box |
30
- | `lockpick status [project]` | One project's report, or an overview of all of them |
31
- | `lockpick runs` | Pulse assessments and boxs, newest first |
32
- | `lockpick run <runId>` | One run: status, open findings, coverage and limits |
33
- | `lockpick watch <runId>` | Follows a run until it finishes |
34
- | `lockpick check <url>` | A free quick check of a website's homepage and public DNS; needs no site (key allowed to start Pulses) |
35
- | `lockpick sites` | Sites with their latest Pulse and box |
36
- | `lockpick sites add <url>` | Adds a site you own or may test (key allowed to add sites); adding does not scan it |
37
- | `lockpick sites switch <site> --yes` | Removes the site holding this month's free Pulse so another site can use it (key allowed to add sites and start Pulses); `--check <id>` also starts a Pulse on that quick check's site |
38
- | `lockpick pulse <project>` | Starts a Pulse (a recheck of the latest one when possible) and waits for the result |
39
- | `lockpick recheck <site>` | A full recheck: a new Pulse that uses one Pulse scan from the allowance, then waits for it |
40
- | `lockpick recheck <runId> --dns <id>` | Free: reads the public DNS records behind one DNS finding again; never contacts the site and never changes the grade |
41
- | `lockpick deps <site>` | Sends this folder's package names and exact versions (never code) to a site and lists the advisories that affect them (key allowed to add sites); `--dry-run` shows what would be sent, `--forget` removes the list |
42
- | `lockpick verify <site>` | Verifies you own a site once: the site's value and where to publish it (`--method dns`, `file` or `meta`); `--wait` looks for it for about five minutes |
43
- | `lockpick deep verify <site>` | The same proof, under `deep` |
44
- | `lockpick deep check <site> <id>` | Looks once for the published proof; each check uses one of its attempts |
45
- | `lockpick deep prepare <site> <id>` | Prepares a Deep scan with a verified proof and opens its approval page; nothing starts until you approve |
46
- | `lockpick deep start <operationId>` | Starts the Deep scan you approved (one Deep scan from the allowance) and waits for it |
47
- | `lockpick findings <runId>` | Findings that need attention (`--all` for informational ones) |
48
- | `lockpick finding <runId> <findingId>` | One finding with its evidence |
49
- | `lockpick brief <runId>` | One brief that fixes everything needing attention (`--finding <id>` for one finding, `--agent <name>` to tailor it, `--out brief.md` to save it) |
50
- | `lockpick fix <runId> --agent <name>` | Saves the fix-all brief to `lockpick-fixes.md` and prints the command that starts your agent on it |
51
- | `lockpick compare <runId>` | What a Pulse recheck changed against its baseline |
52
- | `lockpick open <id>` | Opens a run or project in the browser |
53
- | `lockpick skills` | Adds the Lockpick skills to your coding agent (`npx skills add`) |
54
- | `lockpick docs [words]` | Searches the Lockpick docs from the terminal, or lists the CLI guides (`--open` opens the best match) |
55
- | `lockpick ci init <site>` | Writes `.github/workflows/lockpick.yml`: a Pulse on each published release and on demand that fails on `--fail-on` findings (default `high`); `--dry-run` prints it, `--action` uses the Lockpick GitHub Action |
25
+ | Command | What it shows |
26
+ | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
27
+ | `lockpick whoami` | The user, workspace and key this terminal uses |
28
+ | `lockpick doctor` | Checks Node.js, the selected host, connection, key, workspace and agent API without starting a scan |
29
+ | `lockpick projects` | Projects with their latest Pulse and box |
30
+ | `lockpick status [project]` | One project's report, or an overview of all of them |
31
+ | `lockpick runs` | Pulse assessments and boxs, newest first |
32
+ | `lockpick run <runId>` | One run: status, open findings, coverage and limits |
33
+ | `lockpick watch <runId>` | Follows a run until it finishes |
34
+ | `lockpick check <url>` | A free quick check of a website's homepage and public DNS; needs no site (key allowed to start Pulses) |
35
+ | `lockpick sites` | Sites with their latest Pulse and box |
36
+ | `lockpick sites add <url>` | Adds a site you own or may test (key allowed to add sites); adding does not scan it |
37
+ | `lockpick sites switch <site> --yes` | Removes the site holding this month's free Pulse so another site can use it (key allowed to add sites and start Pulses); `--check <id>` also starts a Pulse on that quick check's site |
38
+ | `lockpick sites history <site>` | A site's security history: each scan depth's score trend, broken where the engine changed (scores either side of a new baseline are not comparable), open findings over time, fixes, regressions and the median time to fix |
39
+ | `lockpick pulse <project>` | Starts a Pulse (a recheck of the latest one when possible) and waits for the result |
40
+ | `lockpick recheck <site>` | A full recheck: a new Pulse that uses one Pulse scan from the allowance, then waits for it |
41
+ | `lockpick recheck <runId> --dns <id>` | Free: reads the public DNS records behind one DNS finding again; never contacts the site and never changes the grade |
42
+ | `lockpick recheck <runId> --finding <id>` | Check this fix, free: after you deploy a fix, reads again only what one finding of a Deep scan was seen on and says fixed, still open or could not check (and why); 5 per finding and 50 per workspace each day |
43
+ | `lockpick deps <site>` | Sends this folder's package names and exact versions (never code) to a site and lists the advisories that affect them (key allowed to add sites); `--dry-run` shows what would be sent, `--forget` removes the list |
44
+ | `lockpick github status <site>` | The site's linked GitHub repository and branch, its lockfiles (each with its last read status and packages), pull request comments, and whether your GitHub list is fresh |
45
+ | `lockpick github repos` | The GitHub repositories you can link (`--search`, `--limit`) |
46
+ | `lockpick github link <site> --repo owner/name` | Links the site to a repository (`--ref`, `--lockfile`, `--lockfiles auto`); when GitHub needs you, prints and opens a Lockpick approval page and waits for your decision (`--no-open`, `--no-wait`) |
47
+ | `lockpick github unlink <site>` | Unlinks the site from its repository |
48
+ | `lockpick github pr-comments <site> on\|off` | Turns the Deep pull request security comment on or off |
49
+ | `lockpick schedule status <site>` | The site's Pulse and Deep auto-checks (cadence, UTC hour, next run, last outcome) and the cadences its plan allows |
50
+ | `lockpick schedule set <site> --every daily\|weekly\|monthly` | Sets or changes the Pulse auto-check at once (`--at <0-23>` UTC hour, `--any-time`); with `--deep`, prints and opens a Lockpick approval page and waits for your decision (`--no-open`, `--no-wait`) |
51
+ | `lockpick schedule pause <site>` | Pauses the Pulse auto-check (`--deep` for the Deep one) |
52
+ | `lockpick schedule resume <site>` | Resumes a paused or removed auto-check with its cadence; `--deep` goes through the approval page |
53
+ | `lockpick share list <site>` | The site's Pulse results that have a live public link |
54
+ | `lockpick share create <runId>` | Publishes a completed Pulse result at a public link and prints it once; `--replace` makes a new link and the old one stops working |
55
+ | `lockpick share revoke <runId>` | Stops sharing a Pulse result; its link stops working |
56
+ | `lockpick export <runId> --out report.pdf` | Saves a finished scan as a PDF, in plain words or `--technical`; never replaces an existing file unless `--force` |
57
+ | `lockpick verify <site>` | Verifies you own a site once: the site's value and where to publish it (`--method dns`, `file` or `meta`); `--wait` looks for it for about five minutes |
58
+ | `lockpick deep verify <site>` | The same proof, under `deep` |
59
+ | `lockpick deep check <site> <id>` | Looks once for the published proof; each check uses one of its attempts |
60
+ | `lockpick deep prepare <site> <id>` | Prepares a Deep scan with a verified proof and opens its approval page; nothing starts until you approve |
61
+ | `lockpick deep start <operationId>` | Starts the Deep scan you approved (one Deep scan from the allowance) and waits for it |
62
+ | `lockpick findings <runId>` | Findings that need attention (`--all` for informational ones) |
63
+ | `lockpick finding <runId> <findingId>` | One finding with its evidence |
64
+ | `lockpick brief <runId>` | One brief that fixes everything needing attention (`--finding <id>` for one finding, `--agent <name>` to tailor it, `--out brief.md` to save it) |
65
+ | `lockpick fix <runId> --agent <name>` | Saves the fix-all brief to `lockpick-fixes.md` and prints the command that starts your agent on it |
66
+ | `lockpick compare <runId>` | What a Pulse recheck changed against its baseline |
67
+ | `lockpick open <id>` | Opens a run or project in the browser |
68
+ | `lockpick skills` | Adds the Lockpick skills to your coding agent (`npx skills add`) |
69
+ | `lockpick docs [words]` | Searches the Lockpick docs from the terminal, or lists the CLI guides (`--open` opens the best match) |
70
+ | `lockpick ci init <site>` | Writes `.github/workflows/lockpick.yml`: a Pulse on each published release and on demand that fails on `--fail-on` findings (default `high`); `--dry-run` prints it, `--action` uses the Lockpick GitHub Action |
56
71
 
57
72
  Every command takes `--host` and `--json`. With `--json`, errors are printed to stderr as `{ "error": "…", "code": "…" }`, plus `nextStep`, `retryAfterSeconds`, `webUrl` and `requestId` for the agent commands.
58
73
 
59
- Exit codes: `0` success; `1` network, not found or other error; `2` authentication; `3` a watched result failed, was cancelled or did not finish before the wait limit; `4` permission (key scope or project role) or allowance; `5` invalid input; `6` rate limit; `7` provider capacity or service failure; `8` open findings reached `--fail-on`. JSON results go to stdout, with errors and human progress on stderr. Text errors end with a `Help:` link to the docs page on your Lockpick host that explains them (`docsUrl` in JSON errors). `--json` never adds terminal colors; `NO_COLOR` turns them off and `FORCE_COLOR=1` turns them on for a CI log. While a scan runs, a terminal shows one live progress line; a pipe or CI (`CI` set) gets one line per change.
74
+ Exit codes: `0` success; `1` network, not found or other error; `2` authentication; `3` a watched result failed, was cancelled or did not finish before the wait limit; `4` permission (key scope or project role) or allowance; `5` invalid input; `6` rate limit; `7` provider capacity or service failure; `8` open findings reached `--fail-on`. JSON results go to stdout, with errors and human progress on stderr. Text errors end with a `Help:` link to the docs page that explains them on the matching docs site (custom and local hosts keep their own docs) (`docsUrl` in JSON errors). `--json` never adds terminal colors; `NO_COLOR` turns them off and `FORCE_COLOR=1` turns them on for a CI log. While a scan runs, a terminal shows one live progress line; a pipe or CI (`CI` set) gets one line per change.
75
+
76
+ `lockpick github` commands take the site as the first argument or as `--site <site>`, so an agent can link a repository for you. A link answers at once when the repository is already in your fresh GitHub list for the workspace; otherwise it prints a single-use Lockpick approval page, opens it in a terminal (never with `--json` or `--no-open`) and waits at the server's interval until you approve or the page expires. It exits `5` when GitHub did not list that repository for your account (install the Lockpick GitHub App on its owner, or check the name), `4` when declined, `7` when GitHub failed and `1` when the page expired. With `--json` the result is the final request; `--no-wait` prints the page and request id and returns.
77
+
78
+ A new link checks every lockfile in the repository (at most 20, the most-used language's first) and finds them again on each read, so a lockfile added later is picked up. Repeat `--lockfile <path>` to check exactly those lockfiles instead; that list is kept as chosen, and a later `lockpick github link` without a lockfile flag keeps it for the same repository. `--lockfiles auto` goes back to every lockfile found, and cannot be combined with `--lockfile`.
79
+
80
+ `lockpick schedule` manages a site's auto-checks, the Pulse and Deep scans Lockpick runs on a schedule within the plan's cadences. Reads need only the default key; a Pulse change needs a key allowed to start Pulses (`lockpick login --pulse`), and a Deep change or pause a key allowed to prepare Deep scans (`--deep`). A Pulse auto-check changes at once. A Deep one never changes from the terminal alone: `set --deep` and `resume --deep` print a single-use Lockpick approval page, open it in a terminal (never with `--json` or `--no-open`) and wait at the server's interval until you approve or the page expires. It exits `4` when declined, `5` when the change could not be made when you approved (the reason is printed) and `1` when the page expired; `--no-wait` prints the page and request id and returns. Pausing never needs approval. `set` keeps what you leave out on an existing auto-check, so `--at 6` alone only moves the hour.
81
+
82
+ `lockpick share create <runId>` publishes a completed Pulse result at a public link (a key allowed to start Pulses). Lockpick shows the link only to the call that makes it: run it again and it says the result is already shared, with no link; `--replace` makes a new link and the old one stops working, and `lockpick share revoke` stops sharing. `lockpick export <runId> --out <file>` writes the scan's PDF to exactly that file, creating it so that an existing file is never replaced unless you pass `--force`.
60
83
 
61
84
  `--fail-on critical|high|medium|low` on `pulse`, `recheck`, `watch`, `deep start` and `findings` exits `8` when open findings are that severe or worse, for CI. `lockpick ci init <site>` writes a GitHub Actions workflow that runs `npx -y lockpicks@<this version> pulse <site> --fail-on high` with the key from the `LOCKPICK_KEY` repository secret; it runs on published releases and by hand only, because each run uses a Pulse.
62
85
 
63
86
  Text from scanned sites and saved briefs can carry terminal escape sequences. The CLI neutralizes every control character in API responses before printing them (an escape shows as `␛`), and keeps only its own colours on the way out, so a scanned page cannot clear your screen, write your clipboard or hide a link. Ids are checked before they go into a URL, and the key is never printed, even when a server error repeats it.
64
87
 
65
- `watch`, `pulse`, full `recheck` and `deep start` wait for at most 600 seconds by default. Use `--timeout <seconds>` (up to 3600) and `--interval <seconds>` (2–30), or `--no-wait` for a started scan id immediately. If a wait ends while the scan is running, the CLI prints its id and exits `3`; resume with `lockpick watch <scanId>`. Waiting never sends the start request again. A quick check waits up to 90 seconds and a DNS recheck up to 60 seconds by default.
88
+ `watch`, `pulse`, full `recheck` and `deep start` wait for at most 600 seconds by default. Use `--timeout <seconds>` (up to 3600) and `--interval <seconds>` (2–30), or `--no-wait` for a started scan id immediately. If a wait ends while the scan is running, the CLI prints its id and exits `3`; resume with `lockpick watch <scanId>`. Waiting never sends the start request again. A quick check waits up to 90 seconds, a DNS recheck up to 60 seconds and Check this fix up to 300 seconds by default; a verdict of Check this fix exits `0` whatever it says.
66
89
 
67
- `pulse` and a full `recheck` started in a project folder with a lockfile ask once whether to send its package names and versions, and remember the answer for that folder (in the CLI's config folder, never in the project). `--lockfile` sends them for one run and `--no-lockfile` skips them; a script with no remembered answer never sends. Lockpick reads `package-lock.json`, `npm-shrinkwrap.json`, `pnpm-lock.yaml`, `yarn.lock`, `requirements.txt` (pinned lines only) and `poetry.lock` in the folder itself, not its subfolders.
90
+ `pulse` and a full `recheck` started in a project folder with a lockfile ask once whether to send its package names and versions, and remember the answer for that folder (in the CLI's config folder, never in the project). `--lockfile` sends them for one run and `--no-lockfile` skips them; a script with no remembered answer never sends. Lockpick reads `package-lock.json`, `npm-shrinkwrap.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lock`, `requirements.txt` (pinned lines only), `poetry.lock`, `uv.lock`, `Pipfile.lock`, `pdm.lock`, `composer.lock`, `go.mod` (`require` versions after `replace`; `go.sum` is not read), `Gemfile.lock`, `gems.locked`, `pom.xml` (versions written in the file or in one of its own properties; no parent POM, BOM or range), `gradle.lockfile`, `buildscript-gradle.lockfile`, `Cargo.lock`, `packages.lock.json`, `pubspec.lock`, `mix.lock` and `Package.resolved` in the folder itself, not its subfolders. Bun's binary `bun.lockb` and a Gradle build without dependency locking (`build.gradle` or `build.gradle.kts`) can't be checked; the CLI says how to make them checkable (commit the `bun.lock` that `bun install --save-text-lockfile` writes, or the `gradle.lockfile` that `./gradlew dependencies --write-locks` writes) and skips them when that file is already there. Nothing is resolved, installed or run.
68
91
 
69
- Each Pulse, and each full recheck, uses one of your account's Pulse scans, the same as starting it in the web app. A quick check and the DNS check again are free; quick checks are limited per account each hour and day.
92
+ Each Pulse, and each full recheck, uses one of your account's Pulse scans, the same as starting it in the web app. A quick check, the DNS check again and Check this fix are free; quick checks are limited per account each hour and day, and Check this fix to 5 per finding and 50 per workspace each day. Neither recheck changes the original grade.
70
93
 
71
94
  ## Coding agents (MCP)
72
95
 
@@ -77,7 +100,7 @@ lockpick mcp config claude --hosted --host https://<your-lockpick>
77
100
 
78
101
  prints a setup preview for your agent and leaves its existing configuration alone. The default uses the installed CLI over stdio and its saved key; `--hosted` uses the remote `/mcp` endpoint and the client's OAuth sign-in. For Claude Code, run the printed command, then check `claude mcp list`; remove it with `claude mcp remove lockpick`. For Cursor, VS Code and Codex, review the preview, then add `--apply` to merge it into the standard config file (or pass `--file <path>`). Setup refuses an existing Lockpick entry and refuses commented JSON that it cannot merge safely. It preserves unrelated servers, makes a private backup, and prints a guarded `lockpick mcp rollback <backup>` command. Rollback refuses to overwrite changes made after setup. For manual setup, merge the printed `lockpick` entry into the existing `mcpServers` or `servers` object, or add the Codex block. Do not put `LOCKPICK_KEY` into project files.
79
102
 
80
- Run `lockpick doctor --scope pulse` when you expect Pulse access (`sites` and `deep` also work). It prints PASS, WARN or FAIL with a next step; `--json` returns the same checks for scripts. It reads server state and does not start a scan or expand key permissions. The server (`lockpick mcp`, stdio) offers the same canonical `lockpick_*` tools as the hosted Lockpick connector: reads (`lockpick_whoami`, `lockpick_get_allowance`, `lockpick_list_sites`, `lockpick_site_status`, `lockpick_list_scans`, `lockpick_get_scan`, `lockpick_wait_for_scan`, `lockpick_list_findings`, `lockpick_get_finding`, `lockpick_get_repair_brief`, `lockpick_compare_scans`, `lockpick_get_quick_check`, `lockpick_get_dns_recheck`, and `lockpick_search_docs` and `lockpick_read_doc` for Lockpick's public docs) and writes that work only when the key has the permission (`lockpick_quick_check`, `lockpick_start_pulse` and `lockpick_recheck_dns` need Pulse; `lockpick_add_site` needs sites; `lockpick_start_deep_verification`, `lockpick_check_deep_verification`, `lockpick_prepare_deep` and `lockpick_start_deep` need Deep, and a Deep scan starts only after you approve it in Lockpick). Results come as markdown or JSON with the `{ data, error }` envelope as structured content, lists page with a cursor, and long repair briefs come in parts that each keep the Boundaries section. The `lockpick://scans/{scanId}/report` and `lockpick://scans/{scanId}/repair-brief` resources and the `fix-lockpick-findings`, `lockpick-check-my-site` and `lockpick-go-deeper` prompts are included.
103
+ Run `lockpick doctor --scope pulse` when you expect Pulse access (`sites` and `deep` also work). It prints PASS, WARN or FAIL with a next step; `--json` returns the same checks for scripts. It reads server state and does not start a scan or expand key permissions. The server (`lockpick mcp`, stdio) offers the same canonical `lockpick_*` tools as the hosted Lockpick connector: reads (`lockpick_whoami`, `lockpick_get_allowance`, `lockpick_list_sites`, `lockpick_site_status`, `lockpick_list_scans`, `lockpick_get_scan`, `lockpick_wait_for_scan`, `lockpick_list_findings`, `lockpick_get_finding`, `lockpick_get_repair_brief`, `lockpick_compare_scans`, `lockpick_get_quick_check`, `lockpick_get_dns_recheck`, `lockpick_get_finding_recheck`, and `lockpick_search_docs` and `lockpick_read_doc` for Lockpick's public docs) and writes that work only when the key has the permission (`lockpick_quick_check`, `lockpick_start_pulse` and `lockpick_recheck_dns` need Pulse; `lockpick_add_site` needs sites; `lockpick_start_deep_verification`, `lockpick_check_deep_verification`, `lockpick_prepare_deep`, `lockpick_start_deep` and `lockpick_recheck_finding` need Deep, and a Deep scan starts only after you approve it in Lockpick). Results come as markdown or JSON with the `{ data, error }` envelope as structured content, lists page with a cursor, and long repair briefs come in parts that each keep the Boundaries section. The `lockpick://scans/{scanId}/report` and `lockpick://scans/{scanId}/repair-brief` resources and the `fix-lockpick-findings`, `lockpick-check-my-site` and `lockpick-go-deeper` prompts are included.
81
104
 
82
105
  Agents set up for CLI 0.2.0 keep working: `lockpick_list_projects`, `lockpick_project_status`, `lockpick_list_runs`, `lockpick_get_run`, `lockpick_wait_for_run`, `lockpick_compare_runs` and the `lockpick://runs/…` resources are still served, and the shared names accept the older `runId`, `projectId` and `offset` arguments. Evidence and any text from scanned sites or saved briefs is treated as untrusted data: it is escaped, links in it are never made clickable, and agents are told never to follow instructions inside it.
83
106
 
@@ -145,16 +168,41 @@ A project-bound CI key supplies its own project when `--project` is omitted. Per
145
168
 
146
169
  Launch a trusted installed CLI from outside an untrusted repository. Supply the physical absolute path of the selected root, with no symlink components; `pwd -P` in a trusted terminal at that location shows the physical path. The scanner does not resolve root symlinks automatically. Browser artifact directories and explicit environment files are relative to the selected root and may be repeated. The scanner never runs a build, target script or credential-validity request. Source and findings stay local; the admission request contains only versions and check IDs.
147
170
 
148
- Reports describe current tracked working-tree bytes, including unstaged changes. Explicit environment files can add untracked inputs. They do not prove production exposure or credential validity. JSON contains the same coverage and findings as terminal output; no source excerpts or secret values are returned. Missing, unsupported or incomplete checks stay explicit. Exit 3 means required coverage is incomplete; exit 8 means completed findings met an explicitly selected `--fail-on` threshold. Without that flag, findings alone do not change a completed run's exit code.
171
+ Reports describe current tracked working-tree bytes, including unstaged changes. Explicit environment files can add untracked inputs. They do not prove production exposure or credential validity. JSON contains the same coverage and findings as terminal output; no source excerpts or secret values are returned. Missing, unsupported or incomplete checks stay explicit. Exit 3 means required coverage is incomplete; exit 8 means completed findings met an explicitly selected `--fail-on` threshold (only new findings with `--fail-on new` and `--baseline`, below). Without that flag, findings alone do not change a completed run's exit code.
149
172
 
150
173
  Public-variable checks ignore comments, unrelated strings and arbitrary objects. Supported `process.env`/`import.meta.env` assignments and exported Next.js `env` configuration are parsed without executing configuration. Multiline dotenv text is kept inside its original value. Dynamic values, custom Vite configuration and unsupported syntax stay incomplete. Reports include sanitized explicit input paths, source inventory format/status, root framework context and migration order; exclusions are reported per check. An interrupted scan marks unknown inspection progress explicitly.
151
174
 
152
- This candidate implements current secrets, parsed dotenv and JS/TS public assignments for root-declared Next.js/Vite projects, explicitly supplied browser assets, and embedded source in `.map` files selected with `--source-maps`. Map findings identify the map container at line 1 and the exact embedded source line/UTF-16 column and index. Source names are sanitized; absolute paths and URLs receive an index label. Maps without embedded content are not applicable; malformed maps, unsupported external sections and missing map inputs are explicit incomplete results. Inline data maps remain unsupported. Add `supabase-client` or `actions-injection` to `--checks` for the implemented AST-based source checks. Supabase resolves exact imports and immutable literals or explicitly supplied env declarations; unresolved origin/browser context becomes a review item. The workflow rule covers direct attacker-controlled event interpolation in supported Bash/sh blocks and records unsupported parser/shell/flow context. Neither rule executes source. Docker ARG/ENV scanning is implemented via `docker-values`, with literal credentials separated from sensitive-name review items. Supply repeatable `--dockerfile` paths and matching `--build-context` paths (in the same order, `.` for the root) to add explicit-context `docker-files` checks. Applicable ignore rules and COPY stage locations are inspected without building an image; unsupported syntax and unresolved contexts stay incomplete. Context candidates cover sensitive filenames and credentials already detected by selected source checks. Untracked candidate contents stay unread unless supplied with `--env-file`; name-only cases are review items with unresolved context. Add `supabase-migrations` to inspect tracked `supabase/migrations/*.sql` in filename order, or repeat `--migration-file` to supply an explicit ordered set. Missing RLS and clearly permissive policies are source-level review items, with table/policy/role context; no SQL executes and no database exposure is claimed. Partial history, dynamic SQL and unsupported statements remain explicit. The embedded PostgreSQL parser is bounded and requires no download. Use `--history` to inspect at most 200 commits reachable from the pinned HEAD. Loose and packed SHA-1/SHA-256 objects are read locally without invoking Git or fetching anything. Historical credentials retain commit/path evidence and rotation guidance. Shallow history, missing/oversized objects, unsupported metadata and limits remain incomplete. Other branch tips, reflogs and unreachable objects are outside this scope. Platform/native packaging and staging verification are still in progress; public API admission remains disabled for the candidate. The candidate reader supports local APFS on macOS and ext-family/tmpfs on Linux, with x64/ARM64 native readers. Windows local scans and network/FUSE/overlay filesystems remain explicitly unsupported. Tracked-file inventory supports Git index v2/v3/v4; validated linked worktrees use their own index/HEAD and bounded common Git metadata. Split/sparse indexes and unsafe metadata pointers remain unsupported. Root and source symlinks are refused. This section is not an announcement that the scanner is live.
175
+ This candidate implements current secrets, parsed dotenv and JS/TS public assignments for root-declared Next.js/Vite projects, explicitly supplied browser assets, and embedded source in `.map` files selected with `--source-maps`. Map findings identify the map container at line 1 and the exact embedded source line/UTF-16 column and index. Source names are sanitized; absolute paths and URLs receive an index label. Maps without embedded content are not applicable; malformed maps, unsupported external sections and missing map inputs are explicit incomplete results. Inline data maps remain unsupported. Add `supabase-client` or `actions-injection` to `--checks` for the implemented AST-based source checks. Supabase resolves exact imports and immutable literals or explicitly supplied env declarations; unresolved origin/browser context becomes a review item. The workflow rule covers direct attacker-controlled event interpolation in supported Bash/sh blocks and records unsupported parser/shell/flow context. Neither rule executes source. Docker ARG/ENV scanning is implemented via `docker-values`, with literal credentials separated from sensitive-name review items. Supply repeatable `--dockerfile` paths and matching `--build-context` paths (in the same order, `.` for the root) to add explicit-context `docker-files` checks. Applicable ignore rules and COPY stage locations are inspected without building an image; unsupported syntax and unresolved contexts stay incomplete. Context candidates cover sensitive filenames and credentials already detected by selected source checks. Untracked candidate contents stay unread unless supplied with `--env-file`; name-only cases are review items with unresolved context. Add `supabase-migrations` to inspect tracked `supabase/migrations/*.sql` in filename order, or repeat `--migration-file` to supply an explicit ordered set. Missing RLS and clearly permissive policies are source-level review items, with table/policy/role context; no SQL executes and no database exposure is claimed. Partial history, dynamic SQL and unsupported statements remain explicit. The embedded PostgreSQL parser is bounded and requires no download. Use `--history` to inspect at most 200 commits reachable from the pinned HEAD. Loose and packed SHA-1/SHA-256 objects are read locally without invoking Git or fetching anything. Historical credentials retain commit/path evidence and rotation guidance. Shallow history, missing/oversized objects, unsupported metadata and limits remain incomplete. Other branch tips, reflogs and unreachable objects are outside this scope. Platform/native packaging and staging verification are still in progress; public API admission remains disabled for the candidate. The candidate reader supports local APFS on macOS and ext-family/tmpfs on Linux, with x64/ARM64 native readers. Windows local scans and network/FUSE/overlay filesystems remain explicitly unsupported in this build; the Go build (`lockpicks@next`) also scans NTFS on a fixed Windows drive, and takes an absolute `--env-file` inside the repository, which the npm launcher's Node finds from any directory. Tracked-file inventory supports Git index v2/v3/v4; validated linked worktrees use their own index/HEAD and bounded common Git metadata. Split/sparse indexes and unsafe metadata pointers remain unsupported. Root and source symlinks are refused. This section is not an announcement that the scanner is live.
176
+
177
+ `--php-version` adds the `php-version` check, which is not in the default set and is admitted only while the server's `LOCKPICK_PHP_VERSION_EVIDENCE` switch is on. It reads the PHP version a repository states in its tracked files (`composer.json`, `composer.lock`, Dockerfiles, compose files, `.php-version`, `.tool-versions`, mise, Platform.sh/Upsun, App Engine, DDEV, Lando, GitHub Actions and GitLab CI), skipping `vendor/` and other dependency trees. Files are read as data through the same bounded reader; PHP, Composer and the repository's scripts never run. The report gains a `php` field (every version found with its file, line and role, the php2shell verdict and its basis), and the text output prints the version the repository builds with and the verdict. An exact runtime or toolchain pin below the fixed release on its branch adds one high-severity `php2shell` finding (CVE-2026-109618, CVE-2026-109619). Branches, constraints, CI and build stages never convict or clear. A repository says what the site is built with, not what the host runs.
178
+
179
+ `actions-policy`, `compose-policy` and `hosting-config` review deployment configuration. They are in no default set: request them with `--checks`, or repeat `--config-file <family>:<path>` to add a family and name a file it would not discover, such as `--config-file compose-policy:deploy/stack.yml`. The server admits them only while its `LOCKPICK_LOCAL_IAC` switch is on, which it is in development and staging and not in production until it is enabled there; a refused family is reported `admission-disabled` and none of its files are read. Their ten review items each describe a source declaration, not deployed state:
180
+
181
+ - `actions-policy` (root `.github/workflows/*.yml` or `*.yaml`): a job whose effective `permissions` is `write-all` (medium); a remote action or reusable workflow not pinned to a full commit SHA (low); a `pull_request_target` workflow whose `actions/checkout` takes the pull request head (high).
182
+ - `compose-policy` (`compose.yaml`, `docker-compose.yml` and their `.override` variants, at any depth): a service with `privileged: true` (high); a bind mount of the Docker socket (high); `network_mode: host` (medium); port 5432, 3306, 6379 or 27017 published on every host interface (medium).
183
+ - `hosting-config`: root `public: true` in `vercel.json` (medium); `[http_service].force_https = false` in `fly.toml` (low); a Supabase function with `verify_jwt = false` in `supabase/config.toml` (low). Netlify, Railway and Render files are recorded as inventory; `vercel.ts` and `.railway/railway.ts` are recognized as executable configuration and never read or run.
184
+
185
+ Each file is parsed on its own as data, with bounded YAML, TOML and JSON parsers. Duplicate keys, YAML aliases, merge keys, custom tags and values the scanner does not resolve (Compose interpolation, `include`, `extends`, override merging) leave the family incomplete, never passing. The report's `configurations` lists every selected file and its outcome. Nothing is built, run or contacted.
153
186
 
154
187
  Local MCP scanning is explicitly enabled with `lockpick mcp --local-root /absolute/repository`; repeat the flag for additional permitted roots. For generated client configuration, use `lockpick mcp config <client> --local-root /absolute/repository` (and `--apply` to install it). This cannot be combined with `--hosted`. The default MCP configuration does not expose `lockpick_scan_local`.
155
188
 
156
189
  The local tool takes a project ID, an absolute repository path within a configured root, check IDs and the same explicit relative inputs as the CLI. It uses the same admission/worker coordinator, rechecks authorization on every call, permits one local scan at a time and forwards cancellation to the worker. Results are not uploaded to Lockpick, but the calling MCP agent or model can see the redacted findings and paths. Do not enable local MCP if that disclosure is inappropriate for the repository.
157
190
 
191
+ ### Baselines: fail CI only on new findings
192
+
193
+ Save a run's `--json` output and pass it to a later run with `--baseline`. The comparison happens in the CLI process; the baseline is never uploaded and adds no API call beyond the normal admission.
194
+
195
+ ```sh
196
+ lockpick deep local "$(pwd -P)" --project <project-id> --json > .lockpick-local-baseline.json
197
+ lockpick deep local "$(pwd -P)" --project <project-id> --baseline .lockpick-local-baseline.json --fail-on high --fail-on new
198
+ ```
199
+
200
+ Findings are matched by their stable, non-credential-derived `id`. The terminal labels each finding `new` or `unchanged` and lists baseline findings that are gone. A gone finding is `fixed` only when every check that found it completed (or was not applicable) in this run; when one of those checks is partial, unsupported, errored or not selected, it is listed as `notRechecked` and never as fixed. JSON output adds a `baseline` object beside `report`: `new` and `unchanged` (current finding IDs), `fixed` and `notRechecked` (`id`, `ruleId`, `severity`, `checks`) and `baselineCompletion`. A run that used `--baseline` is itself a valid baseline.
201
+
202
+ `--fail-on` on `deep local` takes one severity and, with `--baseline`, `new` (`--fail-on high --fail-on new` or `--fail-on high,new`): exit 8 then needs a new finding at that severity or worse, so inherited findings do not fail CI. `--fail-on new` alone counts any new finding of low severity or worse. Accepted dismissals never count, and incomplete coverage still exits 3 first. When the baseline run was itself incomplete, a finding it could not see is reported as new.
203
+
204
+ The baseline is read like a dismissal policy: a regular file of at most 20 MiB, with no final symlink, hard link or FIFO. A baseline written by a different report schema, ruleset version or ruleset digest is rejected with the versions it names, rather than compared; record a new baseline after upgrading the CLI. The local MCP tool returns the JSON report to the agent and does not take a baseline; compare two results by their finding IDs there.
205
+
158
206
  ### Project dismissal policies (0.7.0)
159
207
 
160
208
  Pull a policy using a project manager account with the sites scope: