Version history for Claudezilla
The Multi-Harness Release — Oh My Pi, Hermes, and Pi support, eager tool catalog, PR #22 evaluate race fix
--all-tools CLI flag and CLAUDEZILLA_TOOL_MODE=all environment setting, eagerly exposing the complete tool catalog at startup for harnesses that discover tools once (Oh My Pi, Hermes Agent, Pi Agent). Default lazy loading preserved for Claude Code.
--resume, --session-id, and environment variables across Claude Code, OMP, Pi, and Hermes for focus-loop isolation.
--target <claude|omp|hermes|pi|all> with automated non-destructive configuration of OMP and Claude Code.
firefox_evaluate now awaits settings initialization before checking the allowEvaluate gate, eliminating false-disabled errors on tab attachment.
firefox_get_page_state now forwards parameter limits to the content script and provides explicit truncated: true flags and rawLength metadata on length-capped items while keeping password fields masked.
CLAUDEZILLA_AGENT_TIMEOUT_MS environment override for extended human-in-the-loop tab interactions without premature reaper cleanup.
Community contributions — tab attach, window persistence, screenshot save-to-disk
firefox_list_all_tabs, firefox_attach_tab, firefox_detach_tab — let an agent explicitly take control of a tab you already have open, instead of always opening a new one. Requires an explicit attach call; nothing is ever taken over automatically.
firefox_screenshot save-to-disk
Optional savePath parameter writes the captured screenshot directly to disk.
Stability, security, and AMO compliance — no new MCP tools
setTimeout handles in host/index.js, mcp/server.js, and extension/background.js are now tracked and cleared on response routing, socket close, and timeout fire. Long-lived sessions no longer accumulate retained timers.
unref()'d, post-navigate setTimeout(handleConsent, 600) is tracked and cleared on shutdown, and clearInterval precedes await sendGoodbye so the cleanup loop can't race the goodbye round-trip.
unhandledRejection no longer kills the MCP server
Previously called process.exit(1) on any unhandled promise rejection, ending the session if a single tool path missed a .catch(). Now logs and continues.
MUTEX_BUSY rejections on concurrent screenshots.
firefox_evaluate requires explicit opt-in
Disabled by default. Enable from the Claudezilla popup's new Security section. Documented in SECURITY.md §12 for AMO reviewers; the expression denylist remains as defense-in-depth.
watermarkShadow.innerHTML = ... with explicit <style>.textContent, DOMParser SVG import, and createElement subtree. Clears the UNSAFE_VAR_ASSIGNMENT lint warning. No visual change.
strict_min_version bumped 91 → 140 (required by tabs.group + data_collection_permissions); webRequestBlocking permission dropped (no blocking listener wired up); content_scripts.all_frames explicitly set to false.
worker/wrangler.toml previously shipped a placeholder D1 ID and a boot.industries FRONTEND_URL that redirected donors off-brand. Worker now points at claudezilla.com; deferred claudezilla-emails waitlist binding commented out with an activation runbook.
POST /webhook route with HMAC-SHA256 signature verification (5-min replay window, timing-safe comparison) handles checkout.session.completed, idempotent via stripe_event_id UNIQUE. Checkout session creation now sends Idempotency-Key derived from request body hash. donations + schema_version tables added.
robots.txt, sitemap.xml, self-hosted Mozilla install badge (was loading from blog.mozilla.org, contradicting zero-telemetry copy). _headers adds HSTS, CSP, Permissions-Policy, and immutable cache headers.
engines field
host/ and mcp/ now read version from package.json via import.meta.url; extension reads from browser.runtime.getManifest().version. Added "engines": {"node": ">=18.17"} to both Node packages.
node --test
Coverage for host/protocol.js framing (little-endian, UTF-8, 1 MB cap) and host/ipc.js path validation (null bytes, traversal, UNC). No test framework dependency. Run via pnpm test.
web-ext 9.2.0 → 10.4.0
Dropped mcp/task-detector.js (248 unreachable LOC), unused sessions Map + SESSION_COLORS, and placeholder CLAUDE.md files. extension/content.js switch-block function declarations hoisted to module scope.
Claude Code compatibility — closes the gap with upstream changes 2.1.129 → 2.1.138
CLAUDE_CODE_SESSION_ID (Claude Code 2.1.132+). Concurrent Claude Code sessions on the same machine no longer collide on a single /focus loop. Sessions without an ID fall back to a single __default__ bucket, preserving pre-v0.6.5 behavior.
/clear
When Claude Code reloads the MCP server after /clear, the gateway tool was previously the only thing visible, and the agent's first call to a known firefox_* tool would hard-fail with ACTIVATION_REQUIRED. The MCP server now auto-activates the matching category, emits notifications/tools/list_changed, and proceeds with the call transparently.
plugin/hooks/stop-hook.sh now bounds every socket round-trip with nc -w 2, validates JSON shape before parsing, and forwards the Claude Code session ID. The hook can no longer hang Claude Code's exit path on a stuck socket.
plugin/.claude-plugin/plugin.json bumped to v0.2.0 with homepage, bugs, and license fields populated for installation via Claude Code's --plugin-url flag (added in 2.1.129).
Supply chain hardening — closes ignore-scripts gap, hardens auth, upgrades MCP SDK
ignore-scripts=true to root .npmrc and per-workspace .npmrc files for mcp/ and worker/. Prevents postinstall hook execution — the primary supply-chain attack vector.
--ignore-scripts flag to npm install in install-macos.sh, install-linux.sh, and the windows-test.yml CI workflow. User-facing install paths were previously unprotected.
!== string comparison with crypto.timingSafeEqual() for socket auth token validation in the native host.
content_security_policy to extension/manifest.json (defense-in-depth over the MV2 default).
firefox_create_window now auto-falls back to non-private mode when Firefox incognito permission isn't granted, instead of hard-failing. Response includes isPrivate, privateFallback, and modeWarning fields so agents always know the actual mode.
firefox_get_window_mode command
Lightweight query for current window state and private mode capability. Pairs with firefox_create_window's new private parameter, which returns a structured MODE_MISMATCH error if the existing shared window's mode conflicts.
@modelcontextprotocol/sdk 1.25.2 → 1.29.0
Patches GHSA-345p-7cg4-v4c7 (cross-client data leak via shared server/transport). Claudezilla uses stdio transport (1:1 pipe), so was not exploitable in our architecture, but upgraded for hygiene.
Critical fix: native host fails to start on macOS (and Linux with non-standard node paths)
#!/usr/bin/env node failed with exit 127 when Node.js is installed via Homebrew (/opt/homebrew/bin), nvm, or any non-system path. Installer now resolves the absolute node path at install time and writes a host/run.sh wrapper with exec /absolute/path/to/node. Affects both macOS and Linux installers.
browserAction.onClicked listener
Removed listener that never fires because default_popup is defined in the manifest. Reconnection already handled by sendToHost() calling connect() when port is null.
Socket path reliability + Windows native messaging — community contributions
getSafeTempDir() now falls back to ~/.claudezilla/ (mode 0700) between XDG_RUNTIME_DIR and tmpdir(). Fixes socket path mismatch when macOS assigns different per-process TMPDIR values to Firefox vs Claude Desktop.
host/cli.js now uses getSocketPath() and getAuthTokenPath() from ipc.js instead of hardcoded /tmp/claudezilla.sock.
plugin/hooks/stop-hook.sh now mirrors the full 3-tier fallback (XDG > ~/.claudezilla/ > TMPDIR) matching the Node.js ipc.js logic.
host.bat wrapper instead of using the non-spec args manifest field. Fixes silent connection failure on Windows.
Linux support + reliability/security audit + lazy tool loading + consent automation
firefox_activate gateway tool: at session start, only this single tool (~50 tokens) is exposed instead of all 31 tools (~6,529 tokens). Tools organized into 8 categories (core, inspection, devtools, multiagent, loop, config, diagnose, all). Call firefox_activate() to load the default core category, or pass a specific subset. Server emits notifications/tools/list_changed so Claude Code updates its tool list immediately.
firefox_handle_consent MCP tool automatically detects and dismisses cookie/GDPR overlays via 4-pass strategy: CMP selectors (Google, OneTrust, Quantcast, Didomi, Cookiebot), text matching ("I agree", "Accept all"), shallow Shadow DOM traversal, and [role="dialog"] ARIA fallback. Can be enabled per-agent via firefox_set_config({ handleConsent: true }) to trigger fire-and-forget after every navigation.
#!/usr/bin/env node instead of hardcoded Homebrew path) and install-linux.sh installer that runs npm install in mcp/.
sendCommandOnce now calls socket.removeAllListeners() + socket.destroy() on every resolve/reject path. Previously, data/error/timeout/close listeners accumulated over many commands causing FD leaks.
server.maxConnections = 10 prevents FD exhaustion under DoS. Each socket tracks its pending request IDs in a Set; on socket close, all associated entries are removed from pendingCliRequests to prevent memory leaks on abrupt disconnect.
checkDomainAllowed now validates each domain pattern before constructing a regex: max 255 chars, only [a-zA-Z0-9*.\-] characters allowed. Pathological wildcard patterns previously could cause catastrophic backtracking.
icacls command injection fix (Windows)
host/ipc.js replaced exec() shell invocation with execFile('icacls', [...args]) array form, eliminating shell interpretation of file paths containing quotes or special characters.
screenshotMutexHolder = null is now inside a finally block, ensuring the mutex is always released even if the screenshot throws. Previously a mid-flight exception would leave the mutex permanently held.
Annotated screenshots, domain allowlists, smarter waiting, page state diffing
firefox_screenshot with annotate: true overlays numbered badges on every interactive element (buttons, links, inputs, form controls) using Shadow DOM isolation. The response includes a labels map keyed by badge number so agents can reference elements by number in follow-up commands. Badges are injected, the screenshot captured, and badges removed in one atomic sequence — no visual artifacts persist on the page.
firefox_set_config({ allowedDomains: ["*.example.com", "docs.stripe.com"] }). Supports exact matches and wildcard prefixes. Any createWindow or navigate call to an unapproved domain returns a DOMAIN_BLOCKED error. Opt-in per agent — no global config changes.
waitFor
firefox_wait_for now supports three modes: selector (CSS selector — existing behavior), text (substring match on visible page text), and url (glob match on window.location.href — useful for waiting on redirects or SPA navigation).
firefox_diff_page_state takes two snapshots (from firefox_get_page_state) and returns structured diffs: added/removed/changed headings, links, buttons, and form fields. Runs entirely in the MCP server with no extension round-trip needed — useful for verifying that a click or form submission actually changed the page.
waitFor chains), incorrectly cleaning up active agents' tabs.
captureVisibleTab and restored after, eliminating visual artifacts in screenshots.
CONTENT_SCRIPT_ERROR false positives
JSON, XML, PDF, and binary tabs no longer trigger content script injection errors. The extension now checks the tab's content type before attempting sendMessage and returns a descriptive NON_HTML_TAB error instead.
getNetworkRequests no longer includes raw request/response headers in the payload, reducing response size by ~60% for header-heavy pages.
Tab state bug fixes — eliminates stale-tab loops and session nukes
getSession() would null the entire session state, requiring a full extension reload to recover. Now throws a targeted NO_TABS error without destroying window state.
CONTENT_SCRIPT_UNAVAILABLE and retried forever. Now detects the closed tab and returns TAB_CLOSED with actionable guidance.
waitFor could exceed the 120s orphan timeout, deleting the agent's tabs mid-operation. Heartbeat now also refreshes immediately before the async operation.
TAB_UNAVAILABLE without destroying the window.
Community-reported install and runtime fixes
~/.mozilla/native-messaging-hosts/ (Linux path). Firefox on macOS expects ~/Library/Application Support/Mozilla/NativeMessagingHosts/. Resolves "No such native application" error on fresh macOS installs.
install-macos.sh now runs npm install in the mcp/ directory. Previously, a fresh git clone had no node_modules/, causing the MCP server to fail on first launch.
tabId as a JSON string ("6") rather than a number (6). Firefox's browser.tabs API requires a number — passing a string throws "Incorrect argument types". All 12 tab-targeting tool handlers now normalize via Number(), consistent with the existing closeTab and screenshot pattern.
Critical bug fixes + timeout flexibility
++messageId with crypto.randomUUID().
timeout parameter added to all tool schemas. Range: 5s–300s. Default: 150s.
Autonomous installation + slot reservation system
goodbye on exit, immediately freeing all owned tabs.
Windows support + auto-loop detection
Multi-agent coordination + focus loops