Skip to content

leminkozey/browser-picker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Browser Picker for Claude Code

Click an element on any webpage in Safari — its selector, HTML, computed styles, box model, and (where available) React component + source file land in Claude Code via a /picked slash command.

Mirrors the element-picker from the VS Code Preview Extension, but for everyday browsing instead of an embedded webview.

"/picked make this button rounder" → Claude sees the actual element you clicked, no need to describe it.

Pieces

Path What
extension/ Web extension (Safari Web Extension, also runs as MV3 in chromium browsers)
safari-app/ Xcode project (Safari Web Extension Container App) — built via rebuild.sh
server/ Local Bun HTTP server on 127.0.0.1:7654
launchd/ macOS plist to auto-start the server on login
commands/picked.md The /picked slash command for Claude Code

Install

1. Server

cd server
bun run server.ts

You should see browser-picker server: http://127.0.0.1:7654.

To auto-start on login (recommended):

# adjust the bun path inside the plist first if you didn't install via the official bun installer
cp launchd/de.leminkozey.browser-picker.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/de.leminkozey.browser-picker.plist

Logs: /tmp/browser-picker.log, /tmp/browser-picker.err.log.

2. Safari extension (macOS)

Two routes — pick one:

A) Signed .app (persistent, requires free Apple Developer account)

Builds a signed .app wrapper. Safari treats it as a regular signed extension — no warnings, persists across restarts.

# from the repo root; edits the pbxproj's DEVELOPMENT_TEAM the first time you run it
./safari-app/rebuild.sh

Then in Safari:

  1. Open /Applications/Browser Picker.app once (registers with Safari)
  2. Safari → Settings → Extensions → enable "Browser Picker for Claude Code"
  3. "Always Allow on Every Website…"
  4. Pin the toolbar icon

B) Unsigned "Temporary Extension" (resets on Safari quit)

No Xcode needed, but you re-add it after every Safari restart.

  1. Safari → Settings → Advanced → enable "Show features for web developers"
  2. Safari → Settings → Developer → enable "Allow unsigned extensions"
  3. Same tab → "Add Temporary Extension…" → ⌘⇧G → paste the absolute path to the extension/ folder in this repo → Enter
  4. Safari → Settings → Extensions → enable Browser Picker → "Always Allow on Every Website…"

3. Chromium browser (alternative)

Chrome/Arc/Edge/Brave: extensions page → Developer mode → Load unpacked → pick extension/. Same MV3 code.

4. Slash command for Claude Code

Copy or symlink the command into your Claude Code commands directory:

mkdir -p ~/.claude/commands
ln -s "$PWD/commands/picked.md" ~/.claude/commands/picked.md

Verify with /help inside Claude Code — /picked should appear.

Use

  1. Open the page you want to talk about
  2. Click the Browser Picker icon in the toolbar → popup → "Pick elements"
  3. Hover gives you a box-model overlay; click to confirm. Each pick gets a p1, p2… badge stuck on the element
  4. In Claude Code: /picked make this button rounder — picked elements prepend Claude's context

⌘⇧P is suggested as a keyboard shortcut, but Safari binds that to print — configure your own in Safari → Settings → Extensions → Browser Picker → Keyboard Shortcuts.

Magicwand — Screenshot + Annotation

Move your mouse near the status pill while picking and a pencil drop pops out sideways. Click it to capture the viewport, then annotate with:

  • Pencil (freehand) / Line / Rectangle / Circle / Text
  • 4 colors (red, blue, green, dark)
  • Undo / Clear-all

Hit "Zum Chat hinzufügen" to send the annotated PNG along with picked elements via /picked. Claude Code will see the image as a multimodal input.

Files land in /tmp/browser-picker/screenshots/ and are auto-cleaned after 24h.

Payload shape

GET /latest returns markdown (used by /picked). GET /latest.json returns the raw object:

{
  "selector": "main > section.hero > h1.title",
  "tag": "h1", "id": null, "classes": ["title"],
  "text": "Hello world",
  "html": "<h1 class=\"title\">…</h1>",
  "rect": { "x": 40, "y": 120, "width": 720, "height": 56 },
  "boxModel": { "margin": {}, "border": {}, "padding": {}, "content": {} },
  "styles": { "display": "block", "color": "rgb(…)", "fontSize": "48px", },
  "parent": { "tag": "section", "classes": ["hero"], "display": "flex" },
  "children": ["span.eyebrow", "span.headline"],
  "component": "HeroTitle",
  "file": "/src/components/Hero.tsx",
  "line": 18,
  "pageUrl": "https://example.com/landing",
  "pageTitle": "Example",
  "pickedAt": "2026-05-17T16:20:55.693Z"
}

Endpoints

Method Path Returns
POST /selected {ok: true, sessionIndex} — used by the extension
POST /screenshot {ok, sessionIndex, path} — body is raw image/png, headers X-Page-Url + X-Page-Title
POST /render Markdown summary for the slash command (body: tpl=...); screenshots rendered as ![](file://...) first
GET /latest Markdown of the most recent element pick (screenshots skipped)
GET /latest.json Raw JSON of the last pick (element or screenshot)
GET /session.json All picks in the current session
GET /history.json Last 100 element picks
GET /health {ok, sessionCount, historyCount}
POST /session/clear Wipes session (current pick batch, not history)

Notes

  • Server keeps state in RAM only. Restart = empty.
  • Component / file / line work in React dev-builds (via __reactFiber$._debugSource). Production builds return null. Vue is detected via __vueParentComponent.
  • Content script is registered declaratively (content_scripts in manifest, not programmatic injection). Required for Safari, harmless for chromium.
  • Old tabs that were open BEFORE the extension was loaded need a refresh (⌘R) before they can be picked from.
  • The picker is light liquid-glass styled — toolbar icon is a template image so Safari tints it correctly.

Changelog

See CHANGELOG.md for version history. Current: 0.2.0 — Magicwand (screenshot + annotation), backdrop-filter perf, dock-button hardening.

License

MIT — see LICENSE.

About

Click any element on any webpage in Safari → stream selector, HTML, styles, box-model, React component to Claude Code via /picked

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors