{"slug": "show-hn-intent-lens-see-what-claude-code-is-about-to-do-before-it-does-it", "title": "Show HN: Intent-lens – see what Claude Code is about to do, before it does it", "summary": "A developer released intent-lens, a plugin for the claude-mods marketplace that displays a one-line, plain-language description of a pending Claude Code tool call above the prompt before the call executes. The plugin's default local engine translates tool arguments deterministically at no token or network cost, while an optional model engine uses at most 60 output tokens per call; destructive commands such as recursive deletes, force-pushes and `curl … | sh` are flagged in red and never sent to the model.", "body_md": "*See what Claude is about to do — before it does it.*\n\n<sub>Part of the [claude-mods](https://github.com/Dhananjay-JSR/claude-mods) marketplace.</sub>\n\n<sub>A real Claude Code session with intent-lens loaded.</sub>\n\nA **Claude Mod** that shows the intent of a tool call in one line above the prompt, while the call is still pending.\n\nClaude Code shows you a tool *row* after Claude has already decided to act. `intent-lens` translates the call into a human sentence first, in the place your eyes already are. It reads either the tool's own arguments (free, instant) or asks Claude to phrase it (a few tokens).\n\nIn auto mode, Claude Code moves faster than you can read, and the commands it writes are made for the shell, not for you. A `find | xargs | awk` pipeline tells you almost nothing at a glance, and once it runs, the call folds into a summary like *Ran 2 shell commands*.\n\nintent-lens puts the meaning where your eyes already are, just above the prompt, while the call is still in flight:\n\n- **Understand it at a glance.** One sentence for the call, and each stage of a pipeline in plain words.\n- **Catch the dangerous ones.** A recursive delete, a force-push or`curl … | sh` turns the line red and raises a warning, even when the band is hidden.\n- **Pay nothing for it.** By default it reads the tool's own arguments: no tokens, no network.\n\nRegister the catalog once, then install this mod:\n\n```\n/plugin marketplace add Dhananjay-JSR/claude-mods\n/plugin install intent-lens@claude-mods\n```\n\nFrom your shell:\n\n```\nclaude plugin marketplace add Dhananjay-JSR/claude-mods\nclaude plugin install intent-lens@claude-mods\n```\n\nInstalls are cached. To take a newer version later:\n\n```\nclaude plugin update intent-lens\nclaude --plugin-dir /path/to/claude-mods/plugins/intent-lens\n```\n\nTo load it without typing the flag, alias it in your shell:\n\n```\nalias claude-lens='claude --plugin-dir /path/to/claude-mods/plugins/intent-lens'\n```\n\nTo load it in every session, add the directory to `CLAUDE_CODE_PLUGIN_DIRS` (`:`-separated).\n\nCheck it loaded with `/plugin` (Tab to **Installed**) or just run `/intent`.\n\n| Marker | Engine | What it does | Cost | \n|---|---|---|---|\n| `▸` cyan | **local** | Deterministic translation of the tool's arguments | none | \n| `✦` magenta | **model** | Claude writes the line from the tool, its arguments, and the local draft | at most 60 output tokens per call, plus the prompt | \n| `⚠` red | **risk** | Always local: a destructive shell command is never sent to the model | none | \n\n`auto` (the default) draws the local line immediately, then upgrades it with Claude for the calls that read worst — edits, unknown tools, and MCP tools. The band never sits blank while the model thinks.\n\n```\n▸ Bash   Count the top five languages across your repos\n         6 steps · fetch → extract values → sort → count repeats → sort by number → top 5\n✦ Edit   Add a null guard to the token parser\n⚠ Bash   delete files recursively\n```\n\nThe command itself stays in Claude Code's tool row. The band answers what it *means*.\n\nSwitch engines with `/intent mode local`, `auto`, or `model`.\n\n| Command | What it does | \n|---|---|\n| `/intent` | Show the current state and usage | \n| `/intent on` /`off` /`toggle` | Show or hide the band line (persisted). Warnings still fire when off. | \n| `/intent mode local\\|auto\\|model` | Choose the engine (persisted) | \n| `/intent words plain\\|terse` | Plain vocabulary (default), or the shorter one (persisted) | \n| `/intent log` | The last 20 calls with `✓` /`✗` outcomes and their engine | \n| `/intent clear` | Forget the history | \n| `/intent-log` | Same as `/intent log` | \n\nThe local engine is a pure function of the tool name and arguments — no I/O, no latency.\n\n| Tool | What it says | \n|---|---|\n| `Bash` /`PowerShell` | Claude's own `description` , plus a decoded chain of its stages | \n| `Read` | `~/app/src/auth.ts:10-20` | \n| `Edit` | `~/app/src/auth.ts (12 lines → 24 lines)` | \n| `Write` | `~/app/notes.md (48 lines)` | \n| `Grep` | `\"useEffect\" in ~/app/src` | \n| `Glob` | `**/*.test.ts under ~/app` | \n| `WebFetch` /`WebSearch` | `example.com — extract the rate limit table` /`\"…\" on the web` | \n| `Task` /`Agent` | `explore subagent — find the auth middleware` | \n| `TaskCreate` ,`EnterPlanMode` ,`ToolSearch` | A short phrase each, e.g. `add a task: write the migration` | \n| `TodoWrite` | `update the task list (6 items)` | \n| `AskUserQuestion` | `ask you: Which database should this use?` | \n| `mcp__server__tool` | `server:tool` | \n| anything else | Its first two string arguments, so new tools still say something | \n\n`Bash` is the interesting one: Claude Code's Bash tool already requires Claude to describe each command, so that description **is** the stated intent — normally buried in the tool row.\n\nUnder a pipeline, a second dim line decodes it stage by stage: `6 steps · fetch → extract values → sort → count repeats → sort by number → top 5`. Only pipelines of three or more stages get that line, because a two-step chain reads fine as it is. The mapping is literal — `curl` → fetch, `jq 'select(…)'` → keep matching rows, `uniq -c` → count repeats, `head -5` → top 5 — and quote-aware, so a `|` inside a jq program is not a new stage. `/intent words terse` switches to the shorter vocabulary (`pick fields`, `rank`). It explains the mechanics; the full command stays in Claude Code's tool row.\n\nThe model engine sends the tool name, a bounded view of the arguments (900 characters), and the local draft to `haiku`. It asks for at most 12 words, hard-caps the answer at 110 characters, and waits at most 1.5 seconds. `auto` also reaches for the model when a shell command arrives without a description, since the local line would then have to fall back to the raw command. A failure, a refusal, or a slow reply silently keeps the local line: the intent must never break a call.\n\nShell commands are matched against patterns that can destroy work or reach outside the project: recursive `rm`, `git reset --hard`, `git clean -fd`, force-push, `DROP`/` TRUNCATE`, `mkfs`/` dd`, fork bombs, `curl … | sh`, `sudo`, `chmod -R 777`, package publishes.\n\nA match turns the marker red and raises a toast. It is computed locally and always shown — in `model` mode, and even when the band is hidden. It is a **reminder, not a sandbox**: it matches the text of the command.\n\n- **`local` mode** sends nothing anywhere and costs no tokens.\n- **`auto` mode** calls the model only for edits, unknown tools, MCP tools, and a shell command Claude didn't describe — a few hundred tokens per edit.\n- **`model` mode** calls it for every tool call, which adds up to 1.5 seconds of latency per call.\n- Model calls use your own Claude Code credentials and go through `$.model.complete` , exactly like any other request the session makes.\n- Headless runs (`claude -p` , Agent SDK) never raise`ui.render` , and the mod calls the model only after that event has fired, so such a run spends nothing.\n\n```\nplugins/intent-lens/\n├── .claude-plugin/plugin.json   the manifest\n├── hooks/hooks.json             {\"modules\": [\"./register.js\"]} — makes it a mod\n├── hooks/register.js            hooks, both engines, risk rules\n├── tests/intent.test.mjs        hooks run against a stubbed API\n├── assets/logo.svg              the mark\n├── assets/demo.svg              the band, illustrated (all three markers)\n└── assets/screenshot-*.png      a real session\n```\n\n`claude plugin test` runs `.test.ts` files inside a session; these tests are plain Node instead, so they need no session, network, or credentials. They load the hooks module from a temporary copy and fire every hook — including `session.start` — against a stubbed mods API. Each test gets a fresh copy of the module, so one test's mode, history, or UI flag can never leak into the next.\n\n```\nnode tests/intent.test.mjs\n# 62 pass, 0 fail\n```\n\nRun it from this folder. The repository's CI runs the same tests and `claude plugin validate --strict` on every push, then installs the plugin from the marketplace entry to prove that path works too.\n\n- The band shows the **call in flight** , not a history, and clears the moment the call returns. With parallel calls, the newest takes the line and an older one finishing does not erase it.\n- Calls made by subagents are skipped, so one line is always the main thread's.\n- Nothing is drawn in headless runs, where there is no UI.\n- The model line is a hint about what Claude *says* it is doing; the arguments are the ground truth.\n- The band is a shared surface: it sits above whatever other mods draw, and the user can collapse it with `Ctrl+X Ctrl+A` .\n\nMIT.", "url": "https://wpnews.pro/news/show-hn-intent-lens-see-what-claude-code-is-about-to-do-before-it-does-it", "canonical_source": "https://github.com/Dhananjay-JSR/claude-mods/tree/main/plugins/intent-lens", "published_at": "2026-11-02 18:33:28+00:00", "updated_at": "2026-11-02 18:52:07.469118+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-safety"], "entities": ["intent-lens", "Claude Code", "claude-mods", "Anthropic", "Dhananjay-JSR"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-intent-lens-see-what-claude-code-is-about-to-do-before-it-does-it", "markdown": "https://wpnews.pro/news/show-hn-intent-lens-see-what-claude-code-is-about-to-do-before-it-does-it.md", "text": "https://wpnews.pro/news/show-hn-intent-lens-see-what-claude-code-is-about-to-do-before-it-does-it.txt", "jsonld": "https://wpnews.pro/news/show-hn-intent-lens-see-what-claude-code-is-about-to-do-before-it-does-it.jsonld"}}