Docs · v0.2

Everything landmine does, in one page.

Scan once, tell the agent first, keep the hook as a backstop. Node ≥ 22.12. The npm package is landmines, with an s; it installs the landmine and landmines commands.

Quickstart

In your project's root:

npx landmines scan             # find the open issues filed against your exact versions
npx landmines install --rules  # known-bugs section in AGENTS.md + CLAUDE.md, plus the pre-edit hook

scan needs a GitHub token, because GitHub search and GraphQL require auth. It uses GITHUB_TOKEN, then GH_TOKEN, then gh auth token. A token with no scopes is enough for public repositories.

Start with the rules section. On landmine-bench it took Claude Sonnet 5.5 from 86% to 99%; the hook alone didn't significantly beat no help. --rules writes both. Claude Code doesn't read AGENTS.md, which is why CLAUDE.md gets its own copy.

Re-run scan after you change dependencies. The hook only reads the index.

Install options

npx landmines <command>                         # no install
npm i -D landmines                              # dev dependency (recommended for teams)
npm i -g landmines                              # global: `landmine` and `landmines` on PATH
brew install devanshranjan10/tap/landmines      # Homebrew (also: devanshranjan10/tap/landmine)

install writes the hook command that matches how you installed, so it keeps working for everyone:

Installed asCommand it writes
dev dependencynpx --no-install landmines hook
npx / pnpm dlx / bunxthe pinned npx -y landmines@<version> hook
globallandmine hook
source checkoutabsolute paths, with a warning

The same package is on GitHub Packages as @devanshranjan10/landmines; that needs a token with read:packages, so npm is the simpler route. landmine (no s) on npm is an unrelated package.

Teams and CI

npm i -D landmines
npx landmines scan && npx landmines install --rules
git add .landmine/index.json .landmine/cards AGENTS.md CLAUDE.md
  • Commit the index. .landmine/index.json (and .landmine/cards/) lets teammates and CI share one index. .landmine/.gitignore keeps the raw cache and the per-machine install registry out of git.
  • Pre-commit or CI backstop, for agents with no pre-edit hook: npx landmines check --staged --exit-code checks only the lines a commit adds and exits 1 on a blocking match.
  • Refresh the index on a schedule with npx landmines scan. If a package can't be fetched, its previous issues are kept, marked stale, and the scan exits 2.

Commands

Run each as npx landmines <command>, or landmine <command> after a global install.

CommandWhat it does
scanReads lockfiles, queries npm, PyPI and GitHub, and writes .landmine/index.json. Raw responses are cached for 24 h. Flags: --refresh, --offline (re-analyse the cache, no network), --max-issues 100, --prod, --json, -q.
installAdds the hook or plugin for Claude Code plus every agent whose config is in the project. Leaves your other hooks alone; running it again is harmless. --harness auto|all|<names>, --mode block|warn, --heads-up, --mcp [agents], --rules [files].
rulesPrints, or writes between <!-- landmine:start/end --> markers, a short known-bugs section any agent reads, ranked by the APIs your code uses. --write <files>, --skill (full list as an Agent Skill), --max 15, --rank usage|confidence.
cardsOptional. A model reads each indexed issue once and writes a trigger card. At most 50 new model calls per run unless --all. --provider anthropic|claude-cli|openai, --model, --from, --export.
check <files>Treats whole files as just written and reports matches, marked [blocks: …] or [heads-up only]. --exit-code [--strict], --json.
check --stagedChecks only the lines staged for commit.
mcpRuns the MCP server over stdio.
list [package]Shows indexed issues; by default only the ones the hook can act on. --all, --json.
shareOne postable line about this project's scan, plus a README badge. Counts and package names only.
uninstallRemoves landmine's hook entries, plugin files, rules sections and skill.
hookThe hook entry point: harness payload on stdin, response on stdout. You don't call it yourself.

Agents

One normaliser reads every agent's payload shape (tool names, argument keys, patch formats) and answers in that agent's own deny format. live means run end to end against the real agent; "from docs" means built from the agent's documentation (and source, where open) with each payload shape covered by a test.

AgentWhat install writesVerified
Claude CodePreToolUse hook, .claude/settings.jsonlive 2.1.304: blocked once, agent changed approach
Codex CLIPreToolUse on apply_patch, .codex/hooks.jsonlive 0.159.0; trust the hook with /hooks
OpenCodeplugin, .opencode/plugins/landmine.tsloaded live in 1.18.33; a blocked edit not yet run live
CursorpreToolUse, .cursor/hooks.jsonfrom docs
Gemini CLIBeforeTool, .gemini/settings.jsonfrom docs
GitHub Copilot.github/hooks/landmine.jsonfrom docs
Windsurf / Devinpre_write_code, .devin/hooks.jsonfrom docs
Antigravity.agents/hooks.jsonfrom docs
Factory Droid.factory/hooks.jsonfrom docs
Augment (Auggie).augment/settings.jsonfrom docs
Kiro.kiro/hooks/landmine.jsonfrom docs
Qwen Code.qwen/settings.jsonfrom docs
Crushcrush.jsonfrom docs
Goose.agents/plugins/landmine/from docs
OpenHands.openhands/hooks.jsonfrom docs
Trae.trae/hooks.jsonfrom docs
Kilo Codeplugin, .kilo/plugin/landmine.tstested against a stub host
Clineplugin, .cline/plugins/landmine.tstested against a stub host
Ampplugin, .amp/plugins/landmine.tstested against a stub host
Piextension, .pi/extensions/landmine.tstested against a stub host
Freebuff, Aider, Zed, Roo, Continue, Warp…no pre-edit hook: rules --write AGENTS.md, rules --skill, install --mcp, check --stagedrules, skill and MCP config tested

install --mcp <agents> registers the MCP server in the project config of 16 agents: Claude Code, Cursor, Gemini CLI, Qwen, Copilot, Droid, Kiro, Trae, Antigravity, Freebuff, Roo, Warp, Pi, OpenCode, Kilo and Crush. Codex, Windsurf and Cline keep MCP servers in user-level config; for Codex run codex mcp add landmine -- npx -y landmines mcp.

Hook behaviour

  • Blocks once, then steps aside. The default --mode block denies an edit once per issue per agent session, and only for corroborated matches: the edit uses an issue's symbol and the file also uses something else the issue names (an option, a sibling API, the database driver). The retry goes through.
  • Weaker matches are dropped by default: on held-out real code about 93% of them didn't apply. --heads-up passes them as non-blocking context; --mode warn never blocks.
  • Fast and offline. About 0.11 s per call including Node startup, with a 149 KB index. It never touches the network.
  • Never says "allow", so your own permission prompts still apply.
  • Fails open. Any error, a missing index or an unknown payload means no output, and the edit goes through.

MCP server

The hook stays quiet unless a match is strong. The MCP server is for when the agent is already looking: a confusing error, or behaviour it can't explain. Three read-only tools:

  • landmine_check: a file in the project, or a snippet.
  • landmine_search: error text or an API name.
  • landmine_list: the indexed issues.
npx landmines install --mcp claude,cursor    # comma-separated; plain --mcp means Claude Code

In a live Claude Code session, asked whether inconsistent RootModel equality was a known bug in the pinned pydantic, Claude called landmine_search and answered with pydantic#10544, reported against 2.9.2.

Trigger cards

Optional. A model reads each issue thread once and writes a card: the APIs, the extra conditions that make the bug fire, tokens that show the workaround is already applied, and the workaround. Each card is self-checked against the issue's own repro. The hook, rules and MCP server use cards when present; the hook never calls a model.

npx landmines cards --provider claude-cli      # uses an existing Claude Code login
npx landmines cards --provider openai          # any OpenAI-compatible endpoint (OPENAI_BASE_URL)
npx landmines cards --provider anthropic       # needs @anthropic-ai/sdk installed

Cards are cached per issue, version and model. Each run prints its plan first and caps new model calls at 50 unless you pass --all.

Lockfiles and languages

  • npm: package-lock.json v1–v3, npm-shrinkwrap.json
  • pnpm: pnpm-lock.yaml 5.4, 6 and 9
  • yarn: classic and berry
  • bun: bun.lock (text; binary bun.lockb is not supported)
  • Python: uv.lock, poetry.lock, Pipfile.lock, pinned requirements*.txt

Only direct dependencies are checked. Source files: JS/TS (.js .jsx .ts .tsx .mjs .cjs .mts .cts) and Python (.py .pyi), read with a tolerant lexer so half-written code works. In .vue, .svelte and .astro files, template expressions can be missed.

Exit codes

CodeMeaning
0Success.
1check --exit-code found a match that would block an edit. With --strict, a heads-up match counts too.
2An error or a partial result: bad input, a scan that couldn't fetch every package, or cards that failed.

The hook always exits 0 (it fails open), except in the exit2 format, where a block is exit code 2 with the reason on stderr.

Security

  • Untrusted text reaches your agent. Issue titles, quotes and card summaries come from strangers on GitHub. landmine puts all of it inside one delimited untrusted block, neutralises forged delimiters, strips HTML, caps length, flags quotes that pipe a download into a shell or link unfamiliar hosts, and tells the agent never to follow instructions inside them. Don't let an agent run a quoted workaround without reading it.
  • Network. scan sends your direct dependency names and versions to registry.npmjs.org, pypi.org and api.github.com. cards sends each indexed issue's public thread to the model provider you choose. Nothing else leaves your machine.
  • Credentials. The GitHub token is sent only to api.github.com and never written to the index, cache or logs.
  • Files. Only .landmine/, the agent config files install names, and the marker-delimited rules sections. install refuses to rewrite a settings file it can't parse without losing comments.

Report vulnerabilities privately through the repository's security advisory form.

Uninstall

npx landmines uninstall

Removes landmine's hook entries, plugin files, rules sections and skill, deletes config files and directories it leaves empty, and skips config it never touched. Delete .landmine/ to remove the index.