refactor(cdp): extract attachTo, getWindowId, evaluateJson helpers Target.attachToTarget was decoded at 5 sites, Browser.getWindowForTarget at 5, and Runtime.evaluate unwrapped at another. Each is now one typed helper. Deletes the dead cdp/window-binding.ts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Mon, 27 Jul 2026 01:17:32 +0530
test(cdp): cover call/callOnTarget/callBrowser through a stub transport; collapse decode into one path session-call-test.ts previously only exercised decodeResult (Task 3's surface, and mostly duplicating commands-test.ts) — call, callOnTarget, callBrowser, and the session's internal req helper had zero coverage. Add a stub CdpTransport (no socket, no browser) and test: a valid payload decodes to typed data, a garbage payload becomes invalid_response without throwing, a transport-level error passes through with its original kind (not relabeled), call/callOnTarget/callBrowser route the session id correctly, and opts.timeoutMs reaches the transport only when provided. Also collapse the four near-identical transport-then-decode bodies (req, call, callOnTarget, callBrowser) into one: the three public methods now delegate to req, which is the sole place unknown ends for every CDP call the session makes, internal or public. Public signatures are unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Mon, 27 Jul 2026 01:07:05 +0530
refactor(cdp): make session.call generic over the command table call/callOnTarget/callBrowser now take a known method and return its decoded result type. The session is where unknown ends; transport keeps returning unknown. Removes the casts in session.ts and target-factory.ts, including the session's own internal Target.*/Browser.* calls, which now decode through the same path as the public call methods. Also completes two params-schema gaps in commands.ts surfaced by this migration: Target.createTarget was missing openerId and Runtime.evaluate was missing userGesture, both real CDP fields src/cdp/ already sends. tsc is red project-wide (6 errors, all in src/domains/) — the sanctioned state between Tasks 4 and 7. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Mon, 27 Jul 2026 00:48:45 +0530
feat(cdp): add typed command table with validated decoders One typebox schema per CDP command is the source of both the TS types and the runtime validator, so they cannot drift. Malformed responses become invalid_response errors instead of TypeErrors several frames later. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Mon, 27 Jul 2026 00:35:38 +0530
test: port remaining suites to node:test Mechanical port of the hand-rolled check() harness. Import-after-env ordering preserved so suites still read their sandbox dirs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Mon, 27 Jul 2026 00:27:08 +0530
fix(test): split P5/P6/P10 into one node:test per original check() label Task 1 review found three ported checks collapsed two original labels into one test(), losing the per-assertion granularity the brief's Step 7 requires. Splits P5, P6, and P10 back into two test() blocks each, using the original labels verbatim, with each block doing its own dynamic import after before() sets PI_CODING_AGENT_DIR. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Mon, 27 Jul 2026 00:19:46 +0530
chore(build): split tsconfig, typecheck tests, add node:test runner test/ was never type-checked and had no runner. Adds tsconfig.base.json shared by a src project and a test project, an npm test script scoped to non-manual suites, and a CI step. Ports the profile store suite as proof. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Mon, 27 Jul 2026 00:13:06 +0530
docs: add codebase refactor design Covers comment removal, CDP type-safety boundary, tool authoring contract, duplication/stale-code fixes, and commit sequencing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 26 Jul 2026 21:05:54 +0530
chore: release 0.10.3 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 26 Jul 2026 20:51:43 +0530
fix(profile): resolve replaced binaries and surface real launch failures Two failures made a profile launch report the wrong cause. Linux appends " (deleted)" to /proc/<pid>/exe once the running binary is unlinked, which is what a google-chrome package upgrade does while the browser stays open. detectRunningBrowser passed that literal string on as the executable path, so every launch tried to spawn "/opt/google/chrome/chrome (deleted)" and hit ENOENT. Executable paths are now validated against disk, with the marker stripped and argv[0] used as a fallback; a binary genuinely named "… (deleted)" still wins. spawn() reports a missing or non-executable binary asynchronously via an 'error' event rather than throwing, and that event was discarded — so openProfileWindow returned success, no window opened, and the caller blamed the browser 15s later with a sentinel timeout. The launch now awaits 'spawn'/'error', returns the real cause, and removes its handshake page on the failure path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 26 Jul 2026 20:51:43 +0530
chore: release 0.10.2 Also resyncs package-lock.json, which was left at 0.9.0 by the 0.10.0 and 0.10.1 bumps. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 26 Jul 2026 11:59:13 +0530
fix(client): guard page-info evaluation against a missing documentElement The page-info probe read document.documentElement.scrollWidth/scrollHeight directly, which throws when documentElement is absent. Fall back to zeroed dimensions so evaluation returns a usable PageInfo instead of failing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 26 Jul 2026 11:35:13 +0530
docs: replace real emails with example.com placeholders in README
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 26 Jul 2026 00:52:04 +0530
fix: kill leaked Chrome processes on profile seed failure When a profile is pinned and ProcessSingleton fails to delegate, the spawned Chrome process starts a full second browser instance. The sentinel never appeared, but the spawned process was never killed (detached + unref'd + reference discarded), accumulating zombie browsers that consume RAM. Three changes: - Store child process ref and expose kill() on ProfileWindowHandle. Call kill() when the sentinel doesn't appear within the timeout. - Only clear profileContextId when the browser UUID changes (Chrome mints a fresh UUID on every launch), avoiding unnecessary re-spawns. - Don't clear profileContextId in setProfilePin when the pin hasn't changed, preventing gratuitous re-spawns on session_start.
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 26 Jul 2026 00:33:44 +0530
chore: update 0.10.0 release date
amankumarsingh77 amankumarsingh7702@gmail.com
Sat, 25 Jul 2026 23:52:20 +0530
feat: pin the agent to a chosen browser profile (#16)
* feat: pin the agent to a chosen browser profile (#15)
Harness tabs were created with a bare Target.createTarget, which places
them in Chrome's defaultBrowserContextId — and that value follows window
focus. Which profile the agent acted as therefore depended on which
browser window the user last clicked, so the same task could run as a
work account on one run and a personal account on the next.
/browser-profile lists the connected browser's profiles as "Name (email)"
and pins one to ~/.pi/agent/browser-harness.json, so the choice outlives
the session. The same picker appears on first browser_setup when nothing
is pinned; with no interactive UI, or on cancel, setup continues with a
note and the previous behavior.
Chrome offers no direct route to another profile: Target.createTarget
rejects a foreign browserContextId, and openerId does not inherit the
opener's context. The window is opened through the browser's own command
line (--profile-directory, handed to the running browser by Chromium's
ProcessSingleton) and identified by a unique file:// sentinel page, since
a bare about:blank#token argument is discarded. Further tabs come from
window.open evaluated with userGesture: true — the only CDP-reachable way
to place a tab in a non-default browser context — correlated by a unique
token so concurrent isolated tabs stay distinct. A failed handshake is
reported, never silently redirected to another profile.
All four tab-creation sites now funnel through cdp/target-factory, so
open_urls and the isolated tabs behind web_search / read_page cannot run
with a different profile's cookies than the visible tabs.
Also fixed along the way: snap Chromium is discovered, Windows uses
%LOCALAPPDATA%, browsers launched with an explicit --user-data-dir are
found, the running browser is chosen by ranking candidates against the
connected user-data-dir rather than taking the first process found, and
an installed-but-closed browser no longer reads as running.
CI runs the profile suites and a real-browser end-to-end test on ubuntu,
macOS, and Windows — profile discovery is the one part of the harness
whose behavior genuinely differs per OS.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: single-flight harness window creation
Isolated tabs run concurrently (browser_read_page is registered
unserialized), so several could each find "no harness window" and create
one — two blank windows before this feature, two LAUNCHED profile windows
after it. ensureHarnessWindow now shares one in-flight creation per
client.
Sharing introduces a second hazard: freshlyCreated is a claim on the seed
tab, and if every waiter received it, they would all drive the same tab.
Only the caller that started the creation keeps the claim; the rest open
their own tab beside it.
Covered by test/manual/profile-concurrency-test.ts (five concurrent
isolated tabs, pinned and unpinned: distinct targets, one window, correct
profile), wired into CI on Linux only — the coordination is pure JS and
identical across platforms.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: tilde expansion differs by purpose on Windows
CI on windows-latest caught this: join("~", "x") yields "~\x" there, and
expandTilde only handled "~/".
The two uses are not the same, so they no longer share a helper. The
agent dir stays byte-compatible with pi's own expandTildePath ("~/" only,
every platform) — being more lenient would put the pin file somewhere pi
never looks. $CHROME_USER_DATA_DIR is ours to interpret, so it accepts
"~\" as well, which is what a Windows user would type.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Sat, 25 Jul 2026 00:23:05 +0530
docs: rewrite README for accuracy and readability The README taught the coordinate-first interaction model that the harness replaced with stable [eN] refs, and documented 22 of the 38 registered tools. Restructured so each section answers one question, and rewrote the content against the actual tool registry. - Teach the ref-first model: snapshot yields [eN] handles that re-resolve at action time, with coordinates as the fallback rather than the default. - Document the 16 missing tools: the forms path (fill/select_option/focus), console, wait_for, dispatch_key, drag_and_drop, upload_file, download, print_to_pdf, viewport_resize, close_tab, and setup. - Rebuild the comparison table as prose cells grouped by dimension. Drops the unverifiable "unknown" rows and the duplicated click/dispatch claims, and adds a provenance line so competitor claims stay correctable. - Remove stale guidance: /browser-reload-daemon as the fix for a Chrome restart (auto-reconnect landed in 0.6.0), and the unbenchmarked "10-50x faster" claim on http_get. - Add sections for concurrency and tab isolation, flags and environment variables (BU_CDP_WS, BU_CDP_PORTS, BH_SCRIPT_DIR), and a troubleshooting table keyed to the errors the harness actually emits. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Fri, 24 Jul 2026 22:47:33 +0530
docs: add 0.8.3 and 0.9.0 changelog entries The changelog stopped at 0.8.1 while npm was on 0.8.3 and main had already bumped to 0.9.0. Backfills the 0.8.3 stale-socket fix and documents the 0.9.0 cycle: web_search / read_page / deep-research, the forms domain and durable window binding, the Windows daemon fix (#7), Brave + channel support and stale DevToolsActivePort discovery (#4), and the removed footer status chip (#10). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Fri, 24 Jul 2026 22:15:26 +0530
feat: add forms domain and durable window binding (v0.9.0) (#14) - Add forms domain with a universal field setter that auto-detects element type and fires framework-compatible input events (React native-setter trick) - Add window-binding helper to capture and bind the real Chrome windowId as the session's durable window identity on every new-window code path - Wire supporting changes across CDP session/ownership, client, navigate, isolated-tab, prompt, and state - Add manual tests for forms and window binding - Bump version 0.8.3 -> 0.9.0 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Wed, 22 Jul 2026 00:59:58 +0530
feat: support Brave + Chrome channels, fix stale DevToolsActivePort discovery (#13) * feat: support Brave + Chrome channels, fix stale DevToolsActivePort discovery Broadens browser detection and hardens CDP endpoint discovery, based on the investigation and approach in #4 (Brave Beta on macOS with a leftover Chrome DevToolsActivePort file). Browser detection (src/setup.ts, src/cdp/discovery.ts): - checkChromeRunning() now recognizes Brave (macOS "brave browser", Linux brave/brave-browser, Windows brave.exe), alongside the existing Chrome/ Chromium/Edge detection. Also excludes gpu/updater sub-processes that can linger after a browser quits. - profileDirs() gains Brave (Stable/Beta/Nightly/Dev) and Chrome Beta/Dev/ Canary/Chromium profile paths across macOS, Linux, and Windows. Stale DevToolsActivePort handling (src/cdp/discovery.ts): Previously discovery trusted the first readable DevToolsActivePort file. A browser that has quit leaves its file behind, so if another browser later binds the same port (e.g. 9222), discovery returned a WS URL carrying the dead browser's UUID against the live browser's server, and the connection failed. discoverWsUrl() now: - collects all readable candidates instead of committing to the first; - when candidates share a port, keeps the most-recently-written file (mtime); - skips candidates whose port isn't live via a fast single-shot probe (no 30s waitForPort block on stale files); - asks each live browser for its canonical webSocketDebuggerUrl via /json/version, falling back to the file's WS path when that endpoint is disabled (some browsers only expose it via --remote-debugging-port); - falls back to probing well-known ports (9222, plus BU_CDP_PORTS) when no profile file is readable — covering sandboxed harnesses (EPERM/EACCES) and non-default install locations. Setup guidance updated to mention brave://inspect / edge://inspect and the --remote-debugging-port launch flag. Verified: typecheck clean; queryLiveWsUrl / mtime-dedup / fallback-port logic exercised against a mock /json/version server; checkChromeRunning() matches the single main process against live macOS ps output, excluding all helpers. Closes #4 Co-authored-by: Trevor Whitney <trevorjwhitney@gmail.com> * fix: harden discovery against malformed port files + stale-then-fallback Addresses two issues raised in review of the discovery rewrite: - Validate the port parsed from DevToolsActivePort before building a candidate. A truncated/corrupt file (non-numeric or out-of-range first line) yielded NaN, and net.connect throws ERR_SOCKET_BAD_PORT synchronously for NaN / <=0 / >=65536 — which escaped discoverWsUrl as an unhandled rejection instead of surfacing as a Result error. Such entries are now skipped. - Fall back to well-known ports (9222 / BU_CDP_PORTS) after all discovered candidates prove stale. Previously the fallback ran only when no port file was readable, so a leftover file for a quit browser caused a ~30s waitForPort block and failure without ever trying a live fallback port. Ports already covered by a candidate are skipped to avoid re-probing. --------- Co-authored-by: Trevor Whitney <trevorjwhitney@gmail.com>
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Mon, 13 Jul 2026 00:47:35 +0530
fix: make browser daemon setup work on Windows (#7) (#12) The Unix socket daemon introduced in v0.6.0 made several POSIX-only assumptions that break setup on Windows: - protocol.ts hardcoded a Unix socket path (/tmp/pi-browser-daemon.sock). Node IPC on Windows requires a named pipe (\\.\pipe\<name>); a /tmp path is not a valid net listen/connect target there. - spawn.ts spawned the bare tsx binary / `npx` and probed the non-Windows .bin/tsx shim. On Windows npm binaries are .cmd shims that must run via a shell, and spawning them directly fails with EINVAL / ENOENT. - isDaemonRunning() pre-checked the socket with fs.access(), which always fails for a named pipe and would report a live daemon as dead. - stale-socket unlink() would throw on a named pipe path. Changes: - DAEMON_SOCKET_PATH is now platform-aware: named pipe on win32, Unix socket elsewhere. - spawnDaemon() resolves tsx.cmd / npx.cmd on Windows, runs via shell with per-token quoting (paths with spaces) and windowsVerbatimArguments. - isDaemonRunning() skips the fs.access pre-check on Windows and probes the pipe directly. - stale-socket cleanup is a no-op on Windows (named pipes self-clean). - setup.ts daemon-failure message uses the actual DAEMON_SOCKET_PATH. Closes #7
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Sun, 12 Jul 2026 22:03:43 +0530
fix: remove browser footer status indicator (#10) (#11)
The footer status chip set during session_start could go stale: after a
successful /browser-setup, the setup command only called ctx.ui.notify()
and never updated ctx.ui.setStatus("browser", ...), so the footer kept
showing the red "Browser — run /browser-setup" nudge even though the
browser was connected.
Rather than syncing the status from the setup handler, remove the footer
status indicator entirely. Browser control is on-demand and the setup
command already reports its own outcome via notify(), so the persistent
footer chip added no value and only introduced a stale-state bug.
Closes #10
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Sun, 12 Jul 2026 22:03:37 +0530
feat: add deep-research skill, /deep-research command, fix web-search-researcher deep-research skill fans out to isolated web-search-researcher subagents (now using browser_web_search + browser_read_page instead of the non-existent web_search/web_fetch), coverage-driven loop with a hard ceiling, synthesizes a cited Markdown report. /deep-research command as explicit entry point. Docs updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Wed, 08 Jul 2026 21:41:47 +0530
feat: add expand/collapse (Ctrl+O) rendering to web_search and read_page
Both tools dumped full output into the TUI. Add a shared renderExpandableText
helper (src/domains/render.ts) mirroring browser_execute_js: a compact preview
by default, full body on expand via keyHint("app.tools.expand"). Tools stash a
{summary, body, fullOutputPath} render payload in details; the full text still
goes to the LLM via ToolOk.text. Also surfaces engine + result count in the
web_search summary line (closes the S4 observability gap).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Wed, 08 Jul 2026 21:31:37 +0530
feat: add browser_read_page reader-mode tool URL (or owned targetId) → clean main-article text with nav/ads/footer boilerplate stripped, via a dependency-free readability heuristic. DOM walk lives in an in-page capture expression; scoring/selection is a pure, fixture- tested function (link-density + boilerplate-ancestor filtering, body-text fallback for structure-less pages). Reuses the isolated-attach lifecycle; registered unserialized (safe concurrent read). 10 extractor unit scenarios. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Wed, 08 Jul 2026 21:24:32 +0530
feat: add browser_web_search tool (real-Chrome SERP scrape, no API key) Thin query→ranked-links primitive. Isolated-attach tab lifecycle mirroring browser_open_urls (never touches the user's current tab); pure Google SERP parser with semantic (a h3) extraction and redirect unwrapping; CAPTCHA and no-results surfaced as invalid_state + details.reason. Fixture-based parser tests (9 scenarios). Establishes the isolated-tab lifecycle and tsx+fixture test convention that browser_read_page and deep-research build on. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Wed, 08 Jul 2026 21:13:15 +0530
release: v0.8.3 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Wed, 08 Jul 2026 20:17:57 +0530
fix: stale socket detection prevents daemon spawn after crash isDaemonRunning() only checked file existence of the Unix socket. A dead daemon leaves a stale socket, causing ensureDaemon() to skip spawning and client.start() to fail with 'Chrome not connected'. Replace with a liveness probe: connect, register, verify ack, then disconnect. On failure, clean up the stale socket. Also makes bridge handleRequest async to poll for Chrome connection for up to 15s before rejecting.
amankumarsingh77 amankumarsingh7702@gmail.com
Mon, 06 Jul 2026 23:15:08 +0530
fix: make dispatch_key fire legacy keyCode handlers and tighten execute_js IIFE wrap (#9) - browser_dispatch_key now sets keyCode/which on the synthesized KeyboardEvent (both ref and selector paths) so handlers checking e.keyCode === 13 fire. - browser_execute_js IIFE auto-wrap triggers only when the source starts with a return statement, not on any substring "return " (which silently produced undefined for bare expressions). - browser_fill guidelines point at dispatch_key for tag-input submission and the snapshot+click recipe for custom dropdowns. Bump to 0.8.1. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Sun, 05 Jul 2026 13:15:22 +0530
release: v0.8.0
amankumarsingh77 amankumarsingh7702@gmail.com
Fri, 03 Jul 2026 09:36:56 +0530
refactor: extract event queue from transport into dedicated module
amankumarsingh77 amankumarsingh7702@gmail.com
Fri, 03 Jul 2026 09:36:47 +0530
feat: address elements by stable refs across re-renders (#8) Interaction tools could only target elements by raw viewport coordinates (browser_click) or model-guessed CSS selectors (browser_fill/focus/ select_option/upload). Neither survives a re-render: on React/SPA forms, every save or edit reflows the page, so captured @(x,y) coordinates go stale and guessed selectors miss — leaving the agent to fall back to hand-rolled execute_js DOM walks and unnoticed failed saves. Add a stable ref system, mirroring Playwright MCP / browser-use: - snapshot assigns each interactive element a ref (e1, e2, …), shown as [eN] in the outline, and publishes a per-tab ref → backendNodeId map - interaction tools accept an optional `ref` that re-resolves the element at call time (via DOM.resolveNode / getBoxModel), so it stays valid across re-renders; coordinates/selectors remain as fallbacks - mutating tools append a compact diff of changed / newly-appeared (*) / removed interactive elements, so silent failed saves surface immediately - stale refs return an actionable "re-snapshot" error instead of a miss Ref map is replaced per snapshot (bounded memory); fill keeps the native _valueTracker write path so React controlled inputs still update. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Mon, 29 Jun 2026 00:02:54 +0530
ci: use Node 24 for OIDC/npm 11 support
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 21 Jun 2026 00:55:38 +0530
ci: add trusted-publishing workflow for npm
amankumarsingh77 amankumarsingh7702@gmail.com
Sun, 21 Jun 2026 00:51:33 +0530
release: v0.6.0 — per-tab isolation, Unix socket daemon, on-demand init (#6) * feat: Unix socket daemon with auto-reconnect for persistent Chrome CDP Eliminates the 'Allow Remote Debugging' Chrome prompt that appeared on every pi session by multiplexing pi instances through a single persistent daemon process. Key additions: - Unix socket IPC (net.createServer + readline JSON framing) - CdpBridge with ID multiplexer + event router - DaemonTransport implementing CdpTransport interface - Auto-spawn with ensureDaemon() (lazy, checks socket) Fixes since initial implementation: - Bridge auto-reconnects to Chrome with exponential backoff (1s-60s). Previously the bridge tried once at startup and permanently failed if Chrome wasn't ready — causing 'Chrome not connected' on every browser tool call. - Daemon spawn uses project-local tsx binary instead of global --import flag, fixing silent spawn failure (ERR_MODULE_NOT_FOUND). - Stale ctx crash: persistState in onOwnershipChange wrapped in try/catch to prevent CDP event consumer crashes. 49 test assertions across 4 test files. Zero TypeScript errors. * feat: on-demand browser initialization Browser daemon no longer auto-starts on session_start. Instead: - session_start creates the client lazily but does NOT connect or spawn the daemon. Zero Chrome prompts for non-browser pi sessions. - Browser tool wrapper checks for daemon socket before each call. Socket missing → clear error: 'Run /browser-setup first'. Socket exists → proceeds silently (daemon already running). - /browser-setup is the explicit, one-time init point. It spawns the daemon and connects to Chrome only when the user opts in. - SKILL.md updated with Connection Setup instructions telling agents to direct users to /browser-setup when socket is missing. * fix: checkChromeRunning on macOS — match by substring not exact ps -A -o comm= returns full executable paths on modern macOS (e.g. /Applications/Google Chrome.app/Contents/MacOS/Google Chrome), not the basename. The old exact-match check (browserProcesses.includes(l)) never matched, causing false 'No browser instance running' errors. Changed to substring includes() with helper/renderer/crashpad filtering. * feat: browser_setup as agent-callable tool The agent can now self-recover from 'Browser harness not initialized' errors by calling browser_setup directly — no user mediation needed. - Extracted shared performSetup() from the slash command into setup.ts - Created src/domains/setup.ts with ensureAlive:false to bypass the socket guard (this tool IS the setup, can't require itself) - Registered browser_setup in the tool registry - Updated SKILL.md: agent calls browser_setup directly, not ask user - Removed stale test/manual/spawn-test.ts * release: v0.6.0 — per-tab isolation, Unix socket daemon, on-demand init
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Sun, 21 Jun 2026 00:46:44 +0530
docs: add per-tab isolation research, design, and implementation plan - Research: multi-agent safety analysis with precedent findings - Design: 4-slice per-tab isolation architecture (thoughts/shared/designs/) - Plan: 3-phase implementation plan (thoughts/shared/plans/) - Agent definitions (.pi/agents/) for codebase analysis workflow
amankumarsingh77 amankumarsingh7702@gmal.com
Fri, 08 May 2026 00:18:22 +0530
feat: add per-tab isolation for multi-agent safety Replace singleton dialog, pageInfoDirty, networkBuffer, and consoleBuffer with per-tab TabSession objects stored in a Map<string, TabSession>. - Add TabSession type (sessionId, targetId, dialog, pageInfoDirty, networkBuffer, consoleBuffer) and tabs/sessionIdToTargetId Maps - Add ev.sessionId filter guard in consumeEvents to prevent cross-tab event contamination - Rework switchTo to create/reuse TabSession without clearing buffers, updating sessionId on re-attach - Route all CDP events (dialog, network, console) through resolveTab to the correct TabSession - takeDialog/drainPageInfoInvalidations/drainNetworkBuffer/ drainConsoleBuffer read from current TabSession - Target.targetDestroyed prunes dead TabSession entries - attachFirstPage creates initial TabSession and prunes dead entries - Per-tab pageCaches Map in client.ts replaces pageCache singleton - listTabs reconciliation prunes dead pageCaches entries - console-buffer.ts clear() resets nextSeq to 1 (per-tab seq space) - Multi-agent warning in prompt.ts Parallel Execution section
amankumarsingh77 amankumarsingh7702@gmal.com
Fri, 08 May 2026 00:18:15 +0530
release: v0.5.0 — browser_console tool for JS error/console diagnostics
amankumarsingh77 amankumarsingh7702@gmal.com
Thu, 07 May 2026 12:54:12 +0530
docs: rewrite README for v0.4.0 — comparison table, snapshot-first patterns Adds a "Why pi-browser-harness?" comparison table (vs Playwright MCP, Stagehand, Puppeteer MCP) at the top, surfacing the differentiators a chooser actually cares about: real Chrome, coordinate clicks through iframes/shadow DOM, inline TUI rendering, AX tree with @(x,y) coords, parallel execution, scripts. Tool list reorganized into "Page inspection (use these by default)" / "Visual (last resort)" / Navigation / Interaction / Utility — adds browser_snapshot, browser_network_requests, browser_close_tab. Patterns rewritten snapshot-first; form filling and research no longer screenshot. New sections for parallel execution and tab ownership. Temporary scripts example fixed to use the actual daemon.session().call() binding. Three explicit anti-screenshot rules in "What NOT to do". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Wed, 06 May 2026 00:20:20 +0530
release: v0.4.0 — accessibility snapshot, network capture, snapshot-first prompts
Adds two new tools and pivots the agent's default workflow away from
screenshots toward structured page data.
browser_snapshot — CDP accessibility tree (roles, names, states, hierarchy)
with click coordinates @(x,y) attached to every interactive element via
DOM.getBoxModel (parallel, 1.5s aggregate budget). Pass directly to
browser_click — no screenshot round-trip. Optional includeScreenshot:true
for visual confirmation. format:"json" returns a slim structure with full
box per node.
browser_network_requests — replaces the deprecated browser_get_network_log
placeholder. Filters by urlPattern (substring or /regex/), method, status,
resource type, recency. Optional response-body capture under a 5s aggregate
budget with 50KB per-body cap. Buffer is page-scoped (cleared on tab switch),
500 records/tab, with a bufferOverflowed flag on drain.
CDP plumbing: in-process aggregator in src/cdp/network-buffer.ts wired into
the existing single-consumer event loop. Accessibility domain enabled
alongside Page/DOM/Runtime/Network on every attach.
Ctrl+O expand/collapse on three tools' renderResult — browser_snapshot,
browser_network_requests, browser_execute_js. Compact-by-default views with
keyHint("app.tools.expand") that respects user keybinding remaps.
Tool prompts pivoted snapshot-first: browser_screenshot is documented as
LAST RESORT for visual verification only; browser_snapshot is the default
for understanding pages; browser_execute_js is the default for surgical
reads. browser_click and browser_open_urls guidance follows.
SKILL.md collapsed from ~342 to ~53 lines — keeping only what isn't already
in tool prompts: the decision tree, connection rules, browser_run_script
daemon bindings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Wed, 06 May 2026 00:06:49 +0530
feat: tab ownership — isolate harness tabs from the user's browsing Track which page targets this harness session opened so the agent can never attach to, switch to, or close a tab the user opened themselves. New tabs are spawned in a dedicated Chrome window (newWindow:true on first open, openerId chaining after) so harness activity stays visually separate. - new OwnershipRegistry (src/cdp/ownership.ts) tracks owned targetIds and the harness window seed; mutations notify a single listener that persists to BrowserState (ownedTargetIds, harnessWindowTargetId) - attachFirstPage prefers an already-owned live target; otherwise opens a fresh harness-owned tab in its own window instead of grabbing whatever page the user is on - session subscribes Target.setDiscoverTargets and reaps targetDestroyed events so the registry stays in sync with reality - listTabs returns owned:boolean per tab and reconciles dead ids - browser_list_tabs defaults to scope:"owned"; pass scope:"all" to inspect the user's other tabs (read-only — they cannot be switched to or closed) - browser_switch_tab refuses non-owned tabs, with a clear remediation hint - browser_new_tab opens inside the harness window via openerId, falling back to a fresh window when the seed has been closed - new browser_close_tab tool — owned tabs only, supports unique hex prefix Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Tue, 05 May 2026 23:23:59 +0530
release: v0.3.2 — parallel tool execution, scroll fixes, TUI crash fix - Add async mutex for auto-serialization of mutation tools - Observation tools can run in parallel with mutations - Fix scroll deltaY sign convention (positive=down per W3C) - Add Page.bringToFront before scroll to prevent silent drops - Fix screenshot TUI crash on long file paths (truncateToWidth)
amankumarsingh77 amankumarsingh7702@gmal.com
Tue, 05 May 2026 22:37:26 +0530
fix: prevent TUI crash when screenshot path overflows terminal width (#2) The Image text-fallback render does not respect the rendered width, so a long file path can blow past the terminal width and crash the host TUI. Wrap the component to truncate each rendered line with truncateToWidth so it fits the available width. Co-authored-by: amankumarsingh77 <amankumarsingh7702@gmal.com>
Aman Kumar 145339995+amankumarsingh77@users.noreply.github.com
Tue, 05 May 2026 00:52:11 +0530
feat: parallel tool execution with automatic mutation serialization - Add lightweight async mutex (src/util/mutex.ts) for FIFO serialization - Add serialized?: boolean to BrowserToolDefinition - Wire mutex acquisition into registerBrowserTool execute wrapper - Expose mutationMutex() on BrowserClient - Mark all mutation tools (click, type, scroll, navigate, switch_tab, etc.) as serialized - Leave observation tools (screenshot, page_info, execute_js, http_get, etc.) unguarded - Update prompt and skill docs to reflect parallel-safe behavior - Fix scroll tool: add Page.bringToFront, explicit button:none/buttons:0/pointerType:mouse - Update .gitignore to ignore scripts/ and data/ folders
amankumarsingh77 amankumarsingh7702@gmal.com
Mon, 04 May 2026 22:44:55 +0530
Revert "chore: add pre-parallel-execution latency baseline" This reverts commit 361f4b31f7870f0a8bbd46793edc46c9967fdd69.
amankumarsingh77 amankumarsingh7702@gmal.com
Mon, 04 May 2026 21:18:34 +0530
chore: add pre-parallel-execution latency baseline
amankumarsingh77 amankumarsingh7702@gmal.com
Mon, 04 May 2026 21:17:21 +0530
docs: add speed-optimizations research; chore: improve browser detection in setup
amankumarsingh77 amankumarsingh7702@gmal.com
Mon, 04 May 2026 21:14:30 +0530
feat: render screenshots inline in TUI via Image component; add parallelization guidance to SKILL.md - browser_screenshot now has renderResult that creates an Image component for inline display in Kitty/iTerm2/Ghostty/WezTerm terminals - Falls back to dim text placeholder on terminals without image support - Updated system prompt table description to mention TUI inline rendering - Added Parallelization section to SKILL.md teaching the agent to batch independent operations (browser_open_urls, browser_http_get, etc.)
amankumarsingh77 amankumarsingh7702@gmal.com
Sun, 03 May 2026 00:43:43 +0530
fix: replace @ts-expect-error with @ts-ignore for dynamic sharp import
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 22:15:41 +0530
chore: update lock file for sharp optional dependency
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 22:01:18 +0530
release: v0.3.1 — audit fixes for list_tabs IDs, switch_tab prefix matching, download auto-mkdir, session recovery, docs updates Bug fixes: - list_tabs: show full 32-char targetIds (was truncated to 8 chars) - switch_tab: prefix matching fallback for hex prefixes >= 8 chars - download: auto-create directory with mkdir -p - ensureAlive: Runtime.evaluate probe to recover from crashed page targets Docs: - dispatch_key: clarify DOM-only event behavior - navigate: warn about Google anti-bot limitation - network_log: update deprecated promptSnippet - SKILL.md: document actual daemon API (evaluateJs, pageInfo, session.call) - SKILL.md: add troubleshooting for sharp/maxDim and Google navigation - sharp: add to optionalDependencies for screenshot maxDim auto-resize
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 21:59:30 +0530
chore: address final-review minors — surface event-consumer crashes, document IIFE-wrap heuristic, log shutdown failures, fix CHANGELOG file-size claim Five tweaks from the whole-implementation review: - session.ts: log unexpected event-consumer rejections instead of silent swallow - client.ts: comment the return-substring IIFE-wrap false-positive case - transport.ts: comment that ws.onclose post-open settle is no-op-by-design - index.ts: log client.stop() failures during shutdown - CHANGELOG.md: correct largest-file claim (transport.ts and client.ts are ~220 each, not "client.ts at ~180") Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:53:34 +0530
chore(release): v0.3.0 — internal rewrite
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:50:13 +0530
chore: final cleanup — drop unused keyCode export
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:48:19 +0530
refactor: delete legacy daemon, tools, protocol, renderers; collapse to single tsconfig
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:46:12 +0530
refactor: drop legacy daemon usage from index/setup; trim state; move 4 files to strict tsconfig Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:44:52 +0530
feat(domains): migrate execute_js and run_script with path allowlist + timeout + return validation
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:41:15 +0530
feat(domains): migrate http_get (timeout covers body) and get_network_log (deprecation note)
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:36:50 +0530
feat(domains): migrate drag_and_drop
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:35:30 +0530
feat(domains): migrate viewport_resize
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:34:39 +0530
feat(domains): migrate upload_file (safeJs), download (validated dir), print_to_pdf
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:32:07 +0530
feat(domains): migrate tab tools (list, current, switch, new)
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:28:15 +0530
feat(domains): migrate go_back, go_forward, reload
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:26:01 +0530
feat(domains): migrate navigate (NavOutcome) and open_urls Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:24:23 +0530
feat(domains): migrate screenshot, add typed sharp shim, restore click crosshair overlay
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:20:09 +0530
feat(domains): migrate handle_dialog
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:16:24 +0530
feat(domains): migrate page_info, wait, wait_for_load with typed timeout
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:14:52 +0530
feat(domains): migrate scroll with W3C deltaY semantics and dialog guard
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:12:36 +0530
feat(domains): migrate type, press_key, dispatch_key with safeJs and matched-count validation
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:08:50 +0530
feat(domains): migrate browser_click to defineBrowserTool — vertical slice Implements Task 9: adds src/domains/click.ts with the new architecture, updates registry.ts to register clickTool, removes the legacy browser_click block from tools.ts, and wires BrowserClient alongside BrowserDaemon in index.ts so both systems coexist during migration. Also fixes AnyBrowserToolDefinition variance: uses never-arg renderCall in the erased type and a boundary cast in registerBrowserTool so concrete tool definitions (with specific Static<S> args) are assignable to the registry array without widening.
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:05:09 +0530
feat: add defineBrowserTool helper, truncation, schemas/common, empty registry Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 16:00:58 +0530
fix(cdp): serialize event consumer; persist dialog until taken; validate page info shape
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:55:44 +0530
feat: add CDP session and BrowserClient factory
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:52:10 +0530
fix(cdp): validate inbound CDP messages with a runtime type guard
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:48:28 +0530
feat(cdp): add factory-based transport with Result and event AsyncIterable
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:46:05 +0530
fix(cdp): clear socket timer on probe success; surface non-ENOENT readFile errors
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:43:52 +0530
feat(cdp): port DevToolsActivePort discovery to Result
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:42:07 +0530
feat(cdp): add types and error model for new transport layer
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:40:27 +0530
build: enable strict tsconfig flags for new code, keep legacy lenient
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:39:06 +0530
docs(util): clarify safeJs trust boundary and unsupported value types
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:38:07 +0530
feat(util): add pure keycodes and safeJs template helper
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:36:13 +0530
fix(util): preserve AbortSignal.reason; validate namespace in temp paths
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:33:27 +0530
feat(util): add result, time, and paths primitives for v0.3 rewrite
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:31:01 +0530
feat: v0.2.1 — feature parity with browser-use/browser-harness Adds the missing tools called out in docs/browser-harness-comparison.md: upload_file, dispatch_key, download (configure dir), viewport_resize, drag_and_drop, print_to_pdf, get_network_log, plus the iframe-target helper. Updates promptGuidelines and the system prompt's tools table. Tracked in todo.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:29:23 +0530
docs: add v0.3.0 harness rewrite implementation plan 27 tasks: foundations → CDP transport/session/client → defineTool helper → vertical slice (click) → 13 domain migrations → wire-up + delete legacy → smoke + release. Each task has concrete code, exact file paths, and a typecheck checkpoint. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:17:27 +0530
docs: add v0.3.0 internal-rewrite design spec Per-domain module split, frozen tool names, normalized params, unified Result+details contract. Captures the full audit (predictability bugs, security gaps) and the structural fixes for each. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 15:05:19 +0530
perf: v0.2.0 — event-based waitForLoad, fast ensureAlive, JPEG screenshots, page info caching 5 performance optimizations (14-36% faster end-to-end, output quality unchanged): - fast ensureAlive(): WS state check instead of CDP roundtrip (96% faster per-call) - event-based waitForLoad(): CDP load events instead of 300ms polling (99.5% faster for loaded tabs) - JPEG screenshot support: 29-49% smaller files, faster CDP transfer - page info caching: 1s TTL eliminates redundant evaluateJS calls - parallel domain enables: Promise.all instead of sequential await in switchTab() Benchmark: 3622ms vs 4243ms baseline on 3-tab navigation + screenshot task.
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 11:40:20 +0530
ci: suppress npm pack notice output
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 00:42:32 +0530
fix: commit package-lock.json for CI reproducibility Removes package-lock.json from .gitignore so npm ci works in CI. Without the lock file, actions/setup-node cache resolution fails and npm ci has no dependency tree to install from.
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 00:40:51 +0530
docs: rewrite README — add hero image, condense tools, fix accuracy - Add hero image banner at top - Merge 4 tool tables into 1 compact reference table - Fix tool syntax to match actual parameter schemas - Add Core Patterns section (navigation, form fill, extraction, research) - Add Dialogs, SPAs, Keyboard modifiers subsections - Add What NOT to do section - Add Architecture diagram - Add Contributing link - Remove verbose/duplicate usage examples
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 00:38:39 +0530
chore: update hero image
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 00:30:00 +0530
fix: normalize repository.url for npm
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 00:09:37 +0530
chore: prepare v0.1.0 release - Add hero image for pi package gallery - Update CHANGELOG with release date - Update README with npm install instructions - Add assets/ to npm package files - Add CONTRIBUTING.md and GitHub templates - Add CI workflow for typecheck and pack validation
amankumarsingh77 amankumarsingh7702@gmal.com
Sat, 02 May 2026 00:08:22 +0530
Replace dynamic tool registration with browser_run_script Remove register_tool/remove_tool/list_dynamic_tools and the entire dynamic-tools.ts module. Replace with a single browser_run_script tool that executes temporary scripts from disk with daemon access. Scripts are now written to disk before execution, making them auditable and re-runnable. Same bindings (daemon, require, params, etc.) as before via the same AsyncFunction mechanism.
amankumarsingh77 amankumarsingh7702@gmal.com
Thu, 30 Apr 2026 17:52:26 +0530
fix: stop Chrome remote-debugging consent popup storm Previously a single consent-pending socket could spawn up to 5 stacked 'Allow remote debugging?' dialogs. Three causes: - onopen reset _reconnectAttempts, but Chrome accepts the WS upgrade before the user clicks Allow, so a held socket looked healthy. - ensureAlive's health probe used the full 15s CDP timeout; while the user was reading the dialog the probe would time out, trigger a stop()+start(), and a fresh popup would stack on top. - onclose auto-reconnected unconditionally even when consent had never been granted on that connection. Now a connection is only considered healthy once the first CDP roundtrip completes (attachFirstPage). ensureAlive does a 2s short probe before tearing down the socket. onclose bails out of auto- reconnect when consent was never observed, so a denied dialog surfaces a clean error instead of looping.
amankumarsingh77 amankumarsingh7702@gmal.com
Thu, 30 Apr 2026 13:09:27 +0530
Replace socket daemon with direct CDP WebSocket connection Drops the Unix socket subprocess in favor of talking CDP directly over WebSocket from the extension. Removes the protocol's send/health helpers, simplifies setup to just verifying Chrome's remote debugging port, and tightens types in dynamic-tools. Bumps Node engine to >=22 and adds the ws dependency.
amankumarsingh77 amankumarsingh7702@gmal.com
Wed, 29 Apr 2026 01:38:17 +0530
Fix repo/bug URLs to point to amankumarsingh77/pi-browser-harness
amankumarsingh77 amankumarsingh7702@gmal.com
Wed, 29 Apr 2026 00:41:40 +0530
Initial release: pi-browser-harness Browser control extension for pi — 20 browser_* tools for navigating, clicking, typing, screenshotting, and extracting data from real Chrome via CDP. Includes self-extending harness (register_tool/remove_tool), guided /browser-setup, session persistence, and custom TUI renderers.
amankumarsingh77 amankumarsingh7702@gmal.com
Wed, 29 Apr 2026 00:40:36 +0530