{"_id":"pluckor","_rev":"28-186b09de4530c4048a4a48108a3345b3","name":"pluckor","dist-tags":{"latest":"0.25.0"},"versions":{"0.0.1":{"name":"pluckor","version":"0.0.1","keywords":["pluckor","data-extraction","scraping","browser-extension"],"license":"MIT","_id":"pluckor@0.0.1","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"homepage":"https://pluckor.com","bugs":{"url":"https://github.com/pluckor/pluckor/issues"},"dist":{"shasum":"2cfeb3ab1f609da611abd95953c67c29fc44bcae","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.0.1.tgz","fileCount":2,"integrity":"sha512-TLY89sapEd2EYwAvE1Vjh1Vs6tRS/4xWD2gbRk7BsQ64tOUoP1oqopnMho5iV7eHhJ5sTvPQ1b9jM3zfNSB6CA==","signatures":[{"sig":"MEYCIQCKYx9EJyEP+tqeO7ZBJjVWONpKZwadnmLhwwc9iwCOqQIhAIq9aSkMGwJspGkQtVYbcZkZ52uQxvcREmV/FT+6nu1W","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":716},"gitHead":"f6d6f579cf438619f2db756f0866c34260375bc9","_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"repository":{"url":"git+https://github.com/pluckor/pluckor.git","type":"git"},"_npmVersion":"11.6.2","description":"Pluckor — point-and-click data extraction. Name reservation; see github.com/pluckor.","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.0.1_1776865779340_0.642943576925376","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"pluckor","version":"0.2.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.2.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"5d8a6d451c0207555206e23710c700fe514bbdb0","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.2.0.tgz","fileCount":26,"integrity":"sha512-4Xx1xKRbTJEl53HN9dS9igdundkOaGFGk4X7jLBTXGzn56sTm7GV1y9gWdA3aJE/mJ8GO1O4QqutUynFrfvZXw==","signatures":[{"sig":"MEUCIQCFiPqVSo1stw7HdnXFZBWjiIvmOMcIGK/VHdiIOuZI+wIgNlPe8qHI8jCDfxbtkRq4DVquT1Ft4EM92LUDlD+emmY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":265989},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"7af5a02b59a1a09a4845aa8c21e18501bcff8e70","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Agent-driven in-browser data extraction over MCP. Launches a real Chrome (Chrome for Testing) with the Pluckor extension so an AI agent can navigate, read rendered HTML, run JS, click, type, scroll, and wait — beating Cloudflare and sites that block headl","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.2.0_1781083390814_0.9470296768371775","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"pluckor","version":"0.2.1","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.2.1","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"a464ac84f57f4f9ad6887e9a204bee1e98e45f78","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.2.1.tgz","fileCount":27,"integrity":"sha512-qzZyzzbAVUGoU1IJlOHCpNWboTsOvsciZaYeBy8YjAPOdQ55TFKlFgrIGbBTVrfX3C6oor6vEF4FTm6wQeL+aQ==","signatures":[{"sig":"MEUCIFSA4F4eGlTBkXSQgFEwBtSz3cVMb4/H35uJdznSjMr0AiEAmzJE7iD4O5Zc0CReqJx+yXRqAlJnlqRQKkJOr1+f/xI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":273916},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"94bb2a4606dcbf630aa7c377869cbb541918829e","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Agent-driven in-browser data extraction over MCP. Launches a real Chrome (Chrome for Testing) with the Pluckor extension so an AI agent can navigate, read rendered HTML, run JS, click, type, scroll, and wait — beating Cloudflare and sites that block headl","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.2.1_1781090451087_0.9035660124203844","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"pluckor","version":"0.2.2","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.2.2","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"878bc0f1bcb5a9f11a30a3737b32d2dd2bc78de9","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.2.2.tgz","fileCount":27,"integrity":"sha512-nLhE+yFYZTsKXT7k6chjIKbIblwl/eQXzRvowquKTwouu0Hjb8IaV4lNJ4HJ0uUUOTtOfPiAFKjeKVxfp6Ku9w==","signatures":[{"sig":"MEQCIDXY1HxppsUg8O+RXeDtGWM4PuWdwwmnj6Em3dPAik2sAiAoOSp3KXLIB6sOcNqL478k+iUDQb1a9VdGlk/fZeFREQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":273965},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"c60091655b07d13969051f93646b2010f86395d6","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Agent-driven in-browser data extraction over MCP. Launches a real Chrome (Chrome for Testing) with the Pluckor extension so an AI agent can navigate, read rendered HTML, run JS, click, type, scroll, and wait — beating Cloudflare and sites that block headl","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.2.2_1781090837967_0.5362797946121611","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"pluckor","version":"0.3.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.3.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"a29928944e6fd1b833e26c0acfc815c26e6b7693","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.3.0.tgz","fileCount":28,"integrity":"sha512-RY0pEsjak4yg9aVpi9wL+3LYb/v8BJdwsg0wMY2KdlMotHZe7SMpJrA/GjUQAL5PAsWRig91oyumNmFHnYJSng==","signatures":[{"sig":"MEUCIB6DPEezBTjb5Xw3TNWWUJZi6hP9l4l721OS0C9Nx7flAiEAvphl2vFA4KqSaYikSiVc9XNaytAVBYikJ5QrM3er5Yw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":293179},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"d753b697fb1ce6e4c954a73f52fcd81641216cde","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Agent-driven in-browser data extraction over MCP. Launches a real Chrome (Chrome for Testing) with the Pluckor extension so an AI agent can navigate, read rendered HTML, run JS, click, type, scroll, and wait — beating Cloudflare and sites that block headl","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.3.0_1783399430381_0.886996505131336","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"pluckor","version":"0.4.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.4.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"18f4da55bbbb698b2a86d88cbab224543efcb813","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.4.0.tgz","fileCount":28,"integrity":"sha512-H8h4BrdJBgD0LXQVjA1RRCMCmuyQeGuksTEB98a7oUGMoeh4wBKzWYMUr08NrvjP8MF8qPHC33lD75DuDKBdag==","signatures":[{"sig":"MEQCIFMvFDak0NTwsHdx0E+Ni7mJKzrHkX4Iqe1D66YVjVxXAiBbgi8iXwwhQd3ImbglvA/pA3f9SY2kfhWKrR3XBQH8mg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":301981},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"ad1ff7707a85835bb6845f7300acd458d9a1d724","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Agent-driven in-browser data extraction over MCP. Launches a real Chrome (Chrome for Testing) with the Pluckor extension so an AI agent can navigate, read rendered HTML, run JS, click, type, scroll, and wait — beating Cloudflare and sites that block headl","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.4.0_1783402883419_0.9365873350257763","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"pluckor","version":"0.5.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.5.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"0913bd72224d9d491505a8c2495dcba9510543f2","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.5.0.tgz","fileCount":28,"integrity":"sha512-6EcA+ufTegd0hwD7Hj/w+hxzZkYotlBhRyV/IE/kFxB9jBO1ehC6pVb7A51QZBt7epCfm1u8yle5FR+Gq0qOxA==","signatures":[{"sig":"MEYCIQCynF2xtMH9sFq4otoGjbweGjQf/MTmPUX7SrH7tFAjbgIhAPunvj2P4lKRUpXwUYzlhj4UutdwPCtZIU2bX5EUIQqN","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":308279},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"016c9f67fe998956c2fad88f2aae472985907a1a","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Agent-driven in-browser data extraction over MCP. Launches a real Chrome (Chrome for Testing) with the Pluckor extension so an AI agent can navigate, read rendered HTML, run JS, click, type, scroll, and wait — beating Cloudflare and sites that block headl","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.5.0_1783404947008_0.7015679408650193","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"pluckor","version":"0.5.1","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.5.1","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"27214da602006fc859bc30d1b43ce7935049f70f","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.5.1.tgz","fileCount":28,"integrity":"sha512-aITgBqAGF6R2nKSJQvkLkE+1ewBr5PJOJ6H2p9ND4mMqR/R6ka3Ei76OYaEr3fYeqQAc14mPRkeeV9wkRxrgBA==","signatures":[{"sig":"MEYCIQCIZ/MW/HZQbDHzbTv/Spsano/1IO4I4DK0O8998e8vFwIhANFxnoE7CfnlJ0OOjjDh4vEje4Xb1KlpaoejnHkUMgnu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":308430},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"df047d65a40846a1fd72000b589aa81f958a803d","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.5.1_1783405060519_0.42300838621579295","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"pluckor","version":"0.6.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.6.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"2f2ad777b831c22d04fc8c1dcc3006318c344b0b","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.6.0.tgz","fileCount":28,"integrity":"sha512-9MJWbwWmWj5U+/Rhc3UZCUbXrKIOwOrHBk1rij/T4mZdwqEw4fowg5gUQZ7s7TOghVoRc3rTjEo63Nb3iLkkJw==","signatures":[{"sig":"MEYCIQDepzoXGt1Zugd4ohYkSl5WQgDHQG+IJvHComO/XaDh0AIhALkYM5iaVFpbpI2hP4cLJf8UxF6Pi6VzVNwM9ukqobww","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":319248},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"9f941fc32121ee25503971c5f0e4bd451b97a480","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.6.0_1783407101640_0.030578419693621184","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"pluckor","version":"0.7.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.7.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"43380ea11c5421cc4584061298ddf745cf0faefc","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.7.0.tgz","fileCount":28,"integrity":"sha512-OMZSWv0do55Ql1btHb56HeIVmnOgRDa7kwDrk4xkM99zRxl+6zZ1HKpDtbOXyLCVUMyPLvW45oF8OxDOVCjz7g==","signatures":[{"sig":"MEQCIGQIbRRxIiuwzjf9cXbgXtB1xMSz/k2WlsBmOPb3L/dQAiAf8dvTpvthYtc6pB+ED1byMtAnbWTvUQBTzPayN9dUbg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":321150},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"2483ac5c63cda771eed258c959c82693fa1dd34b","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.7.0_1783409884991_0.6171699038916016","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"pluckor","version":"0.8.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.8.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"469f331ad81514ab0a37a8919bf3ae86bcb69605","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.8.0.tgz","fileCount":29,"integrity":"sha512-aUmDm7isWYZn9vRCycYwkTXbVmgE9iagSZt3WFS03Oc6O+AU3iTf2kCYFCeiX226jyxjaxoQe/Zk79MieUkv6Q==","signatures":[{"sig":"MEUCIGhXkJenjd+szrhocTZ6Jl3/ZKJqlX10Cg3YhaP2/eA6AiEA2i/X6kDuGCfbu9y7VQL3EWp8D1g+8xA8YO+LgoQBbuk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":325427},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"f565565f5386016a6727884022a071c8176ba9bf","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.8.0_1783412009968_0.3222660837703615","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"pluckor","version":"0.9.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.9.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"61bf3b766e9a6a0c01843dba2ef6a12a918d62bd","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.9.0.tgz","fileCount":29,"integrity":"sha512-6tKL5eF4ZFCxqjv846DNsukJSJl4/5ZxCQy7p9rX3iFTx+Dm/iDdQRP4+8MmAuBA637eGZ1OlOqsEb2QDfzVZQ==","signatures":[{"sig":"MEUCID59jM7vs3QhRXbJPUSrD53fHutjPP0N+e5a+oCHySwhAiEAs/OWwBSVt6xV3y8FgqWydaqHxKFEXpL80+Pp3J5quKc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":331562},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"42393d74a7fd5c7c4d69df0a3504a1b65a6fd1f6","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.9.0_1783423153675_0.8885846770918067","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"pluckor","version":"0.10.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.10.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"c8b427535177839e8d96967bd6f4132a6b2db362","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.10.0.tgz","fileCount":29,"integrity":"sha512-jYhfLGSfTFv8yEpJMbjGFYiJQx2ahaVbVMTXnc+9H+bnw11o8WrG9j7VoNsuoI0hOWI8ukzgfYjdALFM5nDwEQ==","signatures":[{"sig":"MEQCIFXUXVmcBzw/6UHdHNUpcggkhODcs9Ip7NvpmV8KONXBAiBKL4/c282/6P1oNYAbSvLoTlieho00tGxWtabqCt0/ZQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":336401},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"e024e989cb9a705d1a7d380432616d62230eec3d","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.10.0_1783424161258_0.7840745596626864","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"pluckor","version":"0.11.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.11.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"8b2b5790ae8c4ad29120d6e34fe44259b866815f","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.11.0.tgz","fileCount":29,"integrity":"sha512-vlBrbXuAVnHFlleG0ttMeqWeY1YIMBrojJPC+OG6BTIGX0WbeRiQCQyOqK3STbUpCDNMZCI5jFsxcAu6vtvUwg==","signatures":[{"sig":"MEUCICa1jqjM1omTC2JrsUOX/bDsdtP0O3okJT4VjpKXDxWeAiEAlaLZ/PiIyjhMnogJlVrv6ZUUm3KPL5d5r5ZtIaUbxRI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":341216},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"b70ac7068e38c560a313963d0e97fc83f28c7af9","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.11.0_1783425158726_0.9305053775020125","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"pluckor","version":"0.12.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.12.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"72f5eca015b47a377ee914e4edf73284dc720eea","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.12.0.tgz","fileCount":29,"integrity":"sha512-/bHbkhMsFV7WssUSU5KO/FoOPn8dJd+PHW7f70Vhi70O3PegepisOW344BYjnSyqafI/4VoDSOAl57t6Y3iphg==","signatures":[{"sig":"MEUCIQDOm39H+ZaOVzzBKRYt2qR10Mh+Rp/iW/6Fm+w2VuFhDQIgJY7vs1VQEaLGv5Y9tKbZpCZ72zYFdSofb5M3Rh5HRIE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":345334},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"33b060a80013980f58c0342613d8e9bd9d6e3e49","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.12.0_1783429042561_0.9226323864260157","host":"s3://npm-registry-packages-npm-production"}},"0.13.0":{"name":"pluckor","version":"0.13.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.13.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"33d9ad11f658ff7df33f2c8ce126d8b5c0507fa3","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.13.0.tgz","fileCount":29,"integrity":"sha512-S46hzRX+36syoSRPEzfqXAGHBTA0uIHncNYg3rQgFmhk/Yq8RORSlVaplI+1RPmyrpvG101uXvMB+G6COrB4rg==","signatures":[{"sig":"MEUCIQCOHKVcif5Ma3ojvNEQq3xsItAqmdf3N17dNKriVwXhjwIgDCcDmCL+rQKtH33jrTUCJCpsI6GCHvps3pOY6GwB49w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":354287},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"86052b9b675bdf3f3612aca8bdfb330c9341e1b9","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP. Launches Chrome for Testing with the Pluckor extension so an agent can navigate, read rendered HTML, extract structured data, screenshot the page, run JS, click, type, scroll, and wait — getting through C","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.13.0_1783431975316_0.779641622393271","host":"s3://npm-registry-packages-npm-production"}},"0.14.0":{"name":"pluckor","version":"0.14.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.14.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"24e1754bce2aeddb67167c5f6fa9a44548e2a944","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.14.0.tgz","fileCount":29,"integrity":"sha512-yUS3JzLiNgNCOY411BDlcWXuG0XsQW370ARZ5m4dR6CzO7VxlLPfy7IN49pKRJoeJ3gDtAjx8+vNxGeyZ2Fpfw==","signatures":[{"sig":"MEUCIF65QwZ+E8NEtK1b63abOOWg8iDGZju6qygt8uZ2ZUQNAiEA1WgLTi3MkUKiYkqW3br03/9B2dzzHftAKtxGuAYSOsg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":361267},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"ecf43a8f6ab95579b7e7e64ec9a77bac07f9994d","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.14.0_1783437111159_0.7369224863371726","host":"s3://npm-registry-packages-npm-production"}},"0.15.0":{"name":"pluckor","version":"0.15.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.15.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"05090ec94e0e7df965fefdd2397101c811a43494","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.15.0.tgz","fileCount":29,"integrity":"sha512-myHwQO2+GDZmQ9gM7cwPQzn2CD/E+4xJQ52eKmYZ8nSfmYNdzOaAb6dyTRJ/5EaSCZ6hc9HwDx1n2kZSR+CbPA==","signatures":[{"sig":"MEUCIB8GM694R7IZAFTRXM58RVIECVCeNQTde8vGvhsEyIF6AiEA5y9YTFftjfcdPaR3sHBOQ+iXIRu0vJpW+0UmQCdZ/BA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":364005},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"ae771b9e9cd8d41f3e18c5ab77efae7a03716b19","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.15.0_1783438098336_0.3432881125024747","host":"s3://npm-registry-packages-npm-production"}},"0.16.0":{"name":"pluckor","version":"0.16.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.16.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"c3d1b9e86c11a5ef6558a33fdc259a29fc259ccf","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.16.0.tgz","fileCount":29,"integrity":"sha512-soyDqU9q90xAcqkHdvE1/fm5vjqjupKrNUo0taKJn3EB1hhRMKctKUTFahJfsvIgePBKcRVzwzZIFLUMbtTMfw==","signatures":[{"sig":"MEYCIQCAINIssqDO3G4wkskfoFvnlr1aOq0x5fbZJE8q8UZ4uwIhALmWjxniL51auuQMdNwIv63cOLmyYbX9Zv4h20HApyZT","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":370014},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"5227a0898e142a053348bce0730a0e3acb069d83","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.16.0_1783438939714_0.1150846487492092","host":"s3://npm-registry-packages-npm-production"}},"0.17.0":{"name":"pluckor","version":"0.17.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.17.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"dd7388c911e9bc52956309ef7122b8b45e4e1b56","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.17.0.tgz","fileCount":29,"integrity":"sha512-BOggEyQcW6ep3PfwUNeHx5k6C3i5k51KI5jaSZNaCnVhG1PKv0Gw/QIiPxe7GnqHLRwSdj82Zay7KKPT6f19Jg==","signatures":[{"sig":"MEUCIQDT7QrU/lxe4bzxZGC3w0xfUk9QiLk3Bbm5w6AtnVMeSgIgLRYx5hEHYxU40vBjvWGNka5XAj1wTxfVsy4m/LEF+vw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":378533},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"c6b8183de141b6329202901c70d6c626f926888e","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.17.0_1783442136123_0.28971642055904145","host":"s3://npm-registry-packages-npm-production"}},"0.18.0":{"name":"pluckor","version":"0.18.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.18.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"0054836c70f7f18ddac59c050a04128e8b098fe3","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.18.0.tgz","fileCount":29,"integrity":"sha512-9SLrzNj9hXHMc5JntLw6EXjXCYjBRis9TFvVp3yE0kvlos2u9s+O0BPcO3Um+UvM1Obxc5Bq48Byq55nVnc8Eg==","signatures":[{"sig":"MEUCIQCVe2yyKykiMjFfClwtmrIH2mfhzPyJmDVAd8R9WMy7gQIgC9HWEo/nUI9MNg7ejuVpP2heuQWLxammibbuTF8L6QM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":385103},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"56ff06a8faeb5c8f7a9ff8d11d96b9dd0b51ed1a","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.18.0_1783444809168_0.6797779749869945","host":"s3://npm-registry-packages-npm-production"}},"0.20.0":{"name":"pluckor","version":"0.20.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.20.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"75b744cb7149d8461ac34412aabd356acc99ca2d","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.20.0.tgz","fileCount":29,"integrity":"sha512-zHMNRGR0KByTJwjLNof1oCzk6hYUpeyJKQPeFYubk9tn+GYdwlwrJIXHUm/VwQZ6DCqrw8ifs9iodNP3E+irTQ==","signatures":[{"sig":"MEQCICuMyR8yYIs5lFtS+dvkHq1bIaOR2hlMePHzKmMYSCHuAiA9HYQc40skXow+iCbGUjgCPVK/p/su65ktzZD9MxzymA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":395107},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"83f20aa4ae50fdfe09ce1220d87a854cf03927f6","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.20.0_1783495925459_0.005503393948576463","host":"s3://npm-registry-packages-npm-production"}},"0.21.0":{"name":"pluckor","version":"0.21.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.21.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"f52197ce6078c23f88633218c984d2f06ce6c6bc","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.21.0.tgz","fileCount":29,"integrity":"sha512-Br8NXsnxF3ThUKt6XTQGg81hzXyFRChR0wazG1648nXZg1+FAtIOxmaRDWum/qmwl894G3NkOc3RbmzT0uS+5g==","signatures":[{"sig":"MEUCIQCisNob4DUdCvtCa+pwZ75tRYhB1b90XWO3Fqo123y2EgIgIt3RvErves8sPubAAWweaHv3M7pLbJ9MAvMtA/oE2fY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":397234},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"69c0a0e06234ae90b92aea6600b4d0bfbfaff8fe","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:cf":"tsx examples/cloudflare-test.ts","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.21.0_1783604567119_0.7027252064208565","host":"s3://npm-registry-packages-npm-production"}},"0.21.1":{"name":"pluckor","version":"0.21.1","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.21.1","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"2e3d7a42cf971d41b3be478a2242977160bc7b7c","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.21.1.tgz","fileCount":26,"integrity":"sha512-NV9uFfcu1hlZFzlfxEsg5aYZDVkqXef47uJWgPA34ZnOvvHBra7bk8927mh5hj1fHorVI5gJvNRFEf5LMWqezg==","signatures":[{"sig":"MEYCIQDAItDatkM37VErD+AE4+1v3oJ/wJCMVdmGG62GZ3j35wIhAPOUIOTcf1PAa7V2vdswdsPsoszlx/w08IvUSDms5Ssn","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":300999},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"1ec5b2076abcb1618a24bdf556a06ae22ffb0f05","scripts":{"mcp":"tsx src/mcp-server.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:cf":"tsx examples/cloudflare-test.ts","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.21.1_1783617818727_0.06919133573608427","host":"s3://npm-registry-packages-npm-production"}},"0.22.0":{"name":"pluckor","version":"0.22.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.22.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"682022cc1caa1af2c0c38dafba6520d85435aec4","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.22.0.tgz","fileCount":28,"integrity":"sha512-K5ZLMGoHREOqzsaTK70OGwyRBBXj/TqGqqf4+7kIsJWOHX7MDL2k3X1xo+hIXM4IDvi6bwF+TpReDiZ/MDSqRw==","signatures":[{"sig":"MEYCIQC5MhnNvSXIVvkZug+fCMttB1mTy9MPVQjKfvmx5sY3UgIhAMZHrPUYJtyHbaJAfvI1cPSXtHmH2qoA/sz8fNGx+SKW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":358063},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"d7d611d9850ea5c696ea3e57390585b87ac8fb0e","scripts":{"mcp":"tsx src/mcp-server.ts","test":"node --import tsx --test test/*.test.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","test:e2e":"node test/e2e/runner.e2e.mjs","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:cf":"tsx examples/cloudflare-test.ts","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.22.0_1785654218929_0.6476196803615462","host":"s3://npm-registry-packages-npm-production"}},"0.23.0":{"name":"pluckor","version":"0.23.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.23.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"18f721cceaeba3a5f46c21c186a99c1ac6495b0c","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.23.0.tgz","fileCount":29,"integrity":"sha512-Q+IwJWbnCvt7El85O75CnndOXO0c5AADwXfM3fo6YXLaihCJUS+pVZVBu2QeTJRE9VkCg1dEd085dzACXL6/qg==","signatures":[{"sig":"MEYCIQCjtIon8SkEH+oK+mmUxgWtcpkkOcXX86RZf10Bx2Kr6QIhALgIUIpwmapvOnlmenUqphYUmg1zTLGWxU/1zoztiKvQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":365261},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"0f20fc3630ab253ae24cc5bcc6fa991b83c9e0c5","scripts":{"mcp":"tsx src/mcp-server.ts","test":"node --import tsx --test test/*.test.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","test:e2e":"node test/e2e/runner.e2e.mjs","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:cf":"tsx examples/cloudflare-test.ts","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"11.6.2","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.23.0_1785656992329_0.22428459203602102","host":"s3://npm-registry-packages-npm-production"}},"0.24.0":{"name":"pluckor","version":"0.24.0","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","_id":"pluckor@0.24.0","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"bin":{"plk":"dist/cli.js","pluckor":"dist/cli.js"},"dist":{"shasum":"82f942dc7b04bd52a7a274f59e315ddb3f897319","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.24.0.tgz","fileCount":30,"integrity":"sha512-sDs0KM8iB8fT3o42Wbeuf57fQvGyv35hS2tRd/cbKayCtTSBHOeGMGfQ038/ViT1DbZPeieCQ6nvzhEA5x3NCQ==","signatures":[{"sig":"MEUCIHdUh4sRsZkPlcDo70gsZcbsLpelJ3cS+i0o3oX6emOZAiEA1jkiY5xYEwIYegg6AhaRjQ7tfoXjlc7DtfFEVkQHbVg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":394033},"type":"module","engines":{"node":">=20.11.0"},"gitHead":"df02bdd4394e4d10dfb8302456f205f8b4333cc2","scripts":{"mcp":"tsx src/mcp-server.ts","test":"node --import tsx --test test/*.test.ts","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","dev-ws":"tsx src/dev-ws-client.ts","build:ts":"tsc -p tsconfig.build.json","cdp-test":"tsx src/dev-cdp-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","test:e2e":"node test/e2e/runner.e2e.mjs","build:ext":"pnpm --filter extension build","typecheck":"tsc --noEmit","build:copy":"node scripts/copy-extension.mjs","example:cf":"tsx examples/cloudflare-test.ts","example:g2":"tsx examples/g2-extract.ts","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"_npmVersion":"9.8.1","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","directories":{},"_nodeVersion":"24.2.0","dependencies":{"ws":"^8.18.0","zod":"^3.23.8","@puppeteer/browsers":"^2.4.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","@types/ws":"^8.5.12","typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/pluckor_0.24.0_1786528781578_0.971013783810214","host":"s3://npm-registry-packages-npm-production"}},"0.25.0":{"name":"pluckor","version":"0.25.0","description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","type":"module","bin":{"pluckor":"dist/cli.js","plk":"dist/cli.js"},"engines":{"node":">=20.11.0"},"keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"license":"MIT","scripts":{"build:ext":"pnpm --filter extension build","build:copy":"node scripts/copy-extension.mjs","build:ts":"tsc -p tsconfig.build.json","build":"pnpm run build:ext && pnpm run build:copy && pnpm run build:ts","prepublishOnly":"pnpm run build","mcp":"tsx src/mcp-server.ts","dev-ws":"tsx src/dev-ws-client.ts","mcp-test":"tsx src/dev-mcp-client.ts","cdp-test":"tsx src/dev-cdp-client.ts","example:g2":"tsx examples/g2-extract.ts","example:cf":"tsx examples/cloudflare-test.ts","test":"node --import tsx --test test/*.test.ts","test:e2e":"node test/e2e/runner.e2e.mjs","typecheck":"tsc --noEmit"},"dependencies":{"@modelcontextprotocol/sdk":"^1.12.0","@puppeteer/browsers":"^2.4.0","ws":"^8.18.0","zod":"^3.23.8"},"devDependencies":{"@types/node":"^25.6.0","@types/ws":"^8.5.12","tsx":"^4.19.2","typescript":"^6.0.3"},"gitHead":"5970e6fbb22a4ca1ab9f293c8079e8655d35743a","_id":"pluckor@0.25.0","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-XXgKfTbYrfIH/TpUV5e3lsEnwdIlo1a0W6tow9M2uL/kjZ0HmK2AuYNQyNpAYcgZBiP1Vkb9rBJOji1CS+rgTg==","shasum":"6eabdc6cc83d704117ea19f389b81bb973d2600c","tarball":"https://registry.npmjs.org/pluckor/-/pluckor-0.25.0.tgz","fileCount":33,"unpackedSize":494348,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCsL5eBSuQjNkeR+iKbtldH2eDapUhB8GtDlRK9CrA3XgIhAKqcf+DchSYxMo06R8qfUtHmdudQFla7L1zig/QMpVRw"}]},"_npmUser":{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"},"directories":{},"maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pluckor_0.25.0_1787926041213_0.45765706496837866"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-22T13:49:39.339Z","modified":"2026-08-28T14:07:21.543Z","0.0.1":"2026-04-22T13:49:39.463Z","0.2.0":"2026-06-10T09:23:10.954Z","0.2.1":"2026-06-10T11:20:51.220Z","0.2.2":"2026-06-10T11:27:18.145Z","0.3.0":"2026-07-07T04:43:50.564Z","0.4.0":"2026-07-07T05:41:23.617Z","0.5.0":"2026-07-07T06:15:47.179Z","0.5.1":"2026-07-07T06:17:40.649Z","0.6.0":"2026-07-07T06:51:41.772Z","0.7.0":"2026-07-07T07:38:05.145Z","0.8.0":"2026-07-07T08:13:30.122Z","0.9.0":"2026-07-07T11:19:13.820Z","0.10.0":"2026-07-07T11:36:01.391Z","0.11.0":"2026-07-07T11:52:38.862Z","0.12.0":"2026-07-07T12:57:22.717Z","0.13.0":"2026-07-07T13:46:15.465Z","0.14.0":"2026-07-07T15:11:51.303Z","0.15.0":"2026-07-07T15:28:18.484Z","0.16.0":"2026-07-07T15:42:19.856Z","0.17.0":"2026-07-07T16:35:36.364Z","0.18.0":"2026-07-07T17:20:09.312Z","0.20.0":"2026-07-08T07:32:05.623Z","0.21.0":"2026-07-09T13:42:47.302Z","0.21.1":"2026-07-09T17:23:38.874Z","0.22.0":"2026-08-02T07:03:39.064Z","0.23.0":"2026-08-02T07:49:52.460Z","0.24.0":"2026-08-12T09:59:41.735Z","0.25.0":"2026-08-28T14:07:21.345Z"},"license":"MIT","keywords":["mcp","model-context-protocol","claude","claude-code","browser","scraping","web-scraping","extraction","cloudflare","chrome","automation","agent","ai"],"description":"Give an AI agent a real Chrome to drive, over MCP — browse, read, extract, and act on any page, getting through Cloudflare and sites that block headless/Playwright, with no automation fingerprint on reads.","maintainers":[{"name":"nawaaz-korvol","email":"nawaaz@korvol.com"}],"readme":"# pluckor\n\n**Give an AI agent a real browser. Extract from anything — even Cloudflare.**\n\n`pluckor` is an [MCP](https://modelcontextprotocol.io) server that hands an AI\nagent (Claude Code, Claude Desktop, or any MCP host) a **real Chrome** to drive.\nIt launches Chrome for Testing with the Pluckor extension loaded, then exposes\ntools to navigate, read rendered HTML, run JavaScript, click, type, scroll, and\nwait — and returns the extracted data to the agent.\n\nThe page loads in a real browser on your machine — real profile, real residential\nIP — and reads happen through a content script, so there's **no CDP and no\n`navigator.webdriver`**. That gets through sites that block headless browsers and\nPlaywright, **including Cloudflare-protected pages**.\n\n```text\n# Claude Code — one step:\n/plugin marketplace add pluckor/pluckor-plugin\n/plugin install pluckor@pluckor\n```\n\n---\n\n## Pluckor vs. Claude for Chrome\n\nShort version: **Claude for Chrome puts Claude in _your_ browser; Pluckor gives\n_your agent_ its own.** They're complementary, not competitors.\n\n- **Whose browser** — Claude for Chrome drives the everyday Chrome you already\n  use (your profile, tabs, logins). Pluckor launches a *separate, dedicated*\n  Chrome it owns, with its own persistent profile.\n- **What it is** — Claude for Chrome is a Claude product feature (you pairing\n  with Claude in your session). Pluckor is an open MCP server you wire into *any*\n  agent — Claude Code, Cursor, Codex, or your own harness.\n- **Primary job** — Claude for Chrome assists with general browsing. Pluckor is\n  built for data extraction/automation, and for getting *through* anti-bot: reads\n  use content-script/tab APIs with **no CDP and no automation fingerprint**, so it\n  clears Cloudflare and sites that block headless/Playwright.\n- **Isolation & scale** — Pluckor gives each agent its own tabs (lanes) and even\n  fully separate browsers (`PLUCKOR_INSTANCE`), so fleets of agents don't collide.\n  Claude for Chrome is your one browser.\n- **Where it runs** — Pluckor is self-hosted, `127.0.0.1`-only; you own the\n  browser and the data.\n\nThe soundbite: **Claude for Chrome automates _your_ browsing; Pluckor is a\nbrowser your agent can automate.** Reach for Pluckor when an autonomous agent\nneeds a clean, scraping-grade browser as a programmable tool.\n\n---\n\n## Install\n\nPluckor has two parts: the **MCP server** (the browser tools, run via\n`npx -y pluckor mcp`) and a **skill** ([`SKILL.md`](SKILL.md)) — the workflow\npatterns and gotchas (wait for async content, robust selectors, Cloudflare\nhandling, the persistent-login flow) that make an agent reliably good at\nextraction. Set up both for your tool. Requires **Node ≥ 20.11**; the first tool\ncall downloads Chrome for Testing (~150 MB).\n\n### Claude Code — one step (recommended)\n\nA [plugin](https://github.com/pluckor/pluckor-plugin) installs the server **and**\nthe skill together:\n\n```text\n/plugin marketplace add pluckor/pluckor-plugin\n/plugin install pluckor@pluckor\n```\n\nMCP-only alternative: `claude mcp add pluckor -- npx -y pluckor mcp`, then copy\n`SKILL.md` to `~/.claude/skills/pluckor/SKILL.md`.\n\n### Cursor\n\n1. **MCP server** — add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project):\n   ```json\n   { \"mcpServers\": { \"pluckor\": { \"command\": \"npx\", \"args\": [\"-y\", \"pluckor\", \"mcp\"] } } }\n   ```\n2. **Skill** — put `SKILL.md` at `.cursor/skills/pluckor/SKILL.md`.\n\n### Codex\n\n1. **MCP server**:\n   ```bash\n   codex mcp add pluckor -- npx -y pluckor mcp\n   ```\n2. **Skill** — put `SKILL.md` at `~/.codex/skills/pluckor/SKILL.md` (personal) or\n   `.agents/skills/pluckor/SKILL.md` (project).\n\n### Any other MCP host\n\n```jsonc\n{ \"mcpServers\": { \"pluckor\": { \"command\": \"npx\", \"args\": [\"-y\", \"pluckor\", \"mcp\"] } } }\n```\n\nThe `SKILL.md` ships in this package and in the\n[plugin repo](https://github.com/pluckor/pluckor-plugin), which carries it in\neach tool's skill location. Cookies/logins persist across runs, so log in once\nand every session inherits it.\n\n---\n\n## The `plk` CLI — a warm, shared browser\n\nUnder the hood there are two pieces: a **daemon** that owns the browser, and the\n**MCP server** the agent connects to. The daemon means the browser stays warm\nbetween sessions, multiple agents can share it, and you can log into sites and\nwatch what's happening.\n\n```bash\nplk start          # launch the browser daemon in the background\nplk start --tail   # …and follow its logs live\nplk status         # is it running? reachable? which version? browser connected?\nplk logs --tail    # follow the daemon log\nplk stop           # close the browser and stop the daemon\nplk restart        # stop then start — recovers a stale or outdated daemon\nplk mcp            # the MCP server the agent spawns (auto-starts the daemon)\n\nplk call <tool> [json-args]   # invoke one tool, print its JSON result\nplk pipe                      # a persistent NDJSON session on stdin/stdout\n```\n\nYou don't have to run `plk start` — `plk mcp` auto-starts the daemon on first use.\nBut starting it yourself lets you:\n\n- **Log in once.** Run `plk start`, log into the sites you care about in the\n  window that opens; every agent session reuses those sessions.\n- **Keep it warm.** No relaunch between agent sessions.\n- **Share it.** Multiple concurrent MCP sessions drive the same browser.\n- **Watch it.** `plk logs --tail` shows every navigation and tool call.\n\n(`pluckor` and `plk` are the same CLI — `pluckor mcp` ≡ `plk mcp`.)\n\n---\n\n## Driving it without MCP — `plk call` and `plk pipe`\n\nMCP is for agents. When the caller is a **program** — a Python orchestrator, a\njob runner, a shell script — `call` and `pipe` give it the same tools over the\nsame daemon and the same warm, logged-in browser. Both auto-start the daemon\nexactly like `plk mcp`, and both resolve tools through the one registry the MCP\nproxy uses, so a tool that exists for an agent exists here, with the same\nschema, the same `tab` / `timeoutMs` params, and the same typed errors.\n\n**Channels.** stdout is the machine channel and carries results only; every\nlog, warning, and diagnostic goes to stderr.\n\n### `plk call` — one shot\n\n```bash\nplk call navigate '{\"url\":\"https://example.com\"}'\nplk call extract  '{\"container\":\".product\",\"fields\":{\"name\":\"h2\",\"price\":\".price\"}}'\nplk call list_tabs\n```\n\n```jsonc\n// stdout — the result, and nothing else\n{\"url\":\"https://example.com\",\"finalUrl\":\"https://example.com/\",\"settled\":true}\n```\n\nExit `0` on success. On failure, exit `1` and stdout carries a machine-readable\nenvelope (stderr gets the human line):\n\n```jsonc\n{\"ok\":false,\"error\":{\"code\":\"SELECTOR_NOT_FOUND\",\"message\":\"…\",\"retryable\":true}}\n```\n\nBranch on `error.code` — `NO_TAB`, `TIMEOUT`, `NAV_TIMEOUT`, `NOT_CONNECTED`,\n`UNKNOWN_COMMAND`, `BAD_MESSAGE`, … — never on the message text. An unknown\ntool name lists the real ones in `error.detail.knownTools`.\n\n> **Quoting on Windows.** PowerShell: single-quote the JSON, as above. `cmd.exe`\n> has no single quotes — escape the inner ones:\n> `plk call navigate \"{\\\"url\\\":\\\"https://example.com\\\"}\"`. A caller that spawns\n> the process with an argv array (Python's `subprocess` with a list) has no\n> quoting problem at all.\n\n### `plk pipe` — a persistent session\n\n`call` pays for a daemon connection per invocation and gets a fresh lane (so a\nfresh default tab) each time. `pipe` keeps one session open: **one request per\nline in, one response per line out**, with the connection, its tabs, and their\nlogged-in state alive until stdin closes. This is the mode to build an\norchestrator on.\n\n```jsonc\n// stdin\n{\"id\":1,\"tool\":\"open_tab\",\"args\":{\"url\":\"https://example.com/list\"}}\n{\"id\":2,\"tool\":\"extract\",\"args\":{\"tab\":\"t2\",\"container\":\".row\",\"fields\":{\"t\":\"h2\"}}}\n\n// stdout\n{\"id\":1,\"ok\":true,\"result\":{\"tab\":\"t2\",\"finalUrl\":\"https://example.com/list\"}}\n{\"id\":2,\"ok\":true,\"result\":{\"records\":[]}}\n// …or, per request:\n{\"id\":2,\"ok\":false,\"error\":{\"code\":\"NO_TAB\",\"message\":\"…\",\"retryable\":true}}\n```\n\n- **Requests are not serialized.** They are dispatched as they arrive; the\n  daemon handles each control call independently and the extension dispatches\n  per command. Ten tabs can navigate and extract at once through one session\n  (measured: 10 parallel `navigate`s finish in the time of one).\n- **Responses come back in completion order** — correlate by `id`, never by\n  position.\n- **A malformed line costs that line, not the session.** It gets one\n  `{\"id\":null,\"ok\":false,\"error\":{\"code\":\"BAD_MESSAGE\",…}}` and the session\n  carries on. Blank lines are ignored.\n- **In-flight calls are drained** when stdin closes, so no response is lost.\n- **One session is one lane** (see [Multiple tabs](#multiple-tabs)) — every\n  request shares one default tab, so `open_tab` first and pass that `tab`\n  handle on every call rather than relying on the default.\n- Managing the daemon stays on the CLI: `plk status`, `plk restart`,\n  `plk logs --tail` — those are commands, not tools.\n\n### Replaying a script, and resuming a halted one\n\nThe scripting tools are callable too — `run_script` is the reason most\norchestrators want a session at all. Replay a saved script; when it halts, patch\nthe offending step and resume from exactly where it stopped:\n\n```jsonc\n// stdin — replay\n{\"id\":1,\"tool\":\"run_script\",\"args\":{\"script\":{\"version\":1,\"steps\":[…]},\"secrets\":{\"password\":\"…\"}}}\n// stdout — halted at step 2, with the failing contract and a page snapshot\n{\"id\":1,\"ok\":true,\"result\":{\"outcome\":\"halted\",\"haltedAt\":2,\"failure\":{…},\"steps\":[…]}}\n\n// stdin — patch step 2, then resume from the fault\n{\"id\":2,\"tool\":\"run_script\",\"args\":{\"script\":{\"version\":1,\"steps\":[\"…patched…\"]},\"from\":2}}\n{\"id\":2,\"ok\":true,\"result\":{\"outcome\":\"completed\",\"startedAt\":2,\"data\":[…]}}\n```\n\n- **`secrets` fills `${SECRET:name}`** in step params. Values reach the page and\n  nothing else — they appear in no result channel, and neither mode logs request\n  args.\n- **No overall time budget.** A script is many calls, so the per-call\n  `timeoutMs + 15_000` rule does not apply to it; each *step* carries its own,\n  exactly as under MCP. A long replay is never cut short by the front end.\n- **Safe resume.** A mutating step at the `from` boundary is not re-fired — its\n  state contracts are re-checked instead, so resuming can't double-submit.\n- **`record_start` / `record_stop` need `pipe`, not `call`**: a draft\n  accumulates across requests, so one-shot mode could only discard it and\n  returns a typed error saying so. Recording also assumes *sequential* requests\n  — don't fan out while one is open.\n\n```python\n# the shape of an orchestrator\nproc = subprocess.Popen([\"plk\", \"pipe\"], stdin=PIPE, stdout=PIPE, text=True, bufsize=1)\nproc.stdin.write(json.dumps({\"id\": 1, \"tool\": \"open_tab\", \"args\": {\"url\": url}}) + \"\\n\")\nresp = json.loads(proc.stdout.readline())   # match resp[\"id\"] against what you sent\n```\n\n---\n\n## Tools\n\n| Tool | What it does | Returns |\n|------|--------------|---------|\n| `navigate` | Load a URL; waits for load and settles past Cloudflare-style interstitials | `{ url, finalUrl, settled, onChallenge }` |\n| `get_html` | Rendered HTML of the page (or a CSS selector) — content script, no CDP | `{ html, url, truncated }` |\n| `get_markdown` | Clean, token-efficient Markdown of the page's main content (auto-detects the article/main root) — content script, no CDP. ~10× smaller than the HTML | `{ markdown, url, title, chars, truncated, root }` |\n| `run_js` | Evaluate a JS expression; returns its value. `captureConsole:true` also returns the script's own logs + any thrown error | `{ value }` (or `{ value, logs, error }`) |\n| `wait_for_selector` | Wait until a selector appears (optionally visible), or time out | `{ found, waitedMs }` |\n| `snapshot` | A ref-stamped map of the page's actionable elements (+ heading/landmark context) so you act by `ref`, not by guessing selectors. Content-script DOM walk, no CDP | `{ tree, count, url, title, truncated }` |\n| `click` | Trusted click (`isTrusted = true`) at an element's center — by CSS `selector` or a snapshot `ref` | `{ clicked }` |\n| `type` | Trusted text entry into a field (fires real input events) — by `selector` or `ref` | `{ typed, into }` |\n| `scroll` | Scroll the page (`wheel` default, or CDP `gesture` mode) | `{ scrolled, mode }` |\n| `screenshot` | Capture the page as an image — viewport (no CDP), `scroll:true` for a stitched long shot (no CDP), `fullPage:true` for a one-shot full page (CDP), or `selector` for an element (CDP). Pass `filename` (or `save:true` for a default name) to save it to disk instead of returning it inline | image + `{ width, height, format, bytes }`, or `{ path, filename, … }` when saved |\n| `extract` | Structured data from a field→selector map — add `container` for one record per element (a listing). No code, no CDP | `{ record }` or `{ records, count }` |\n| `extract_links` | Harvest deduped, absolute links (filter by `pattern`) for list→detail crawls. No CDP | `{ links, count }` |\n| `capture_requests` | Inspect the page's network — recent request metadata (no CDP), or `record`/`stop` a CDP session to capture response bodies (the JSON an API returned) | `{ requests, count }` |\n| `wait_for_response` | Block until a request matching `pattern` completes — a smarter wait for API-driven pages. No CDP | `{ matched, url, status, waitedMs }` |\n| `wait_for_network_idle` | Block until the network goes quiet (≤ `threshold` in-flight for `idleMs`) — the \"data loaded\" wait when no single request/selector fits. No CDP | `{ idle, inFlight, waitedMs }` |\n| `wait_for_human` | Hand off to a human for an interactive Cloudflare Turnstile, login, or 2FA — blocks until the challenge clears or an `until` selector appears. Focuses the window, notifies, and shows an on-page banner. No CDP | `{ resolved, reason, waitedMs, onChallenge }` |\n| `capture_console` | Read the page's own console output + uncaught errors, buffered since load. No CDP | `{ entries, count }` |\n| `press_key` | Press a key (trusted) — `Enter` to submit, `Escape`, `Tab`, arrows, or a character; optional `selector`/`ref` to focus first | `{ pressed }` |\n| `select_option` | Choose an option in a native `<select>` by value/label/index (fires change — React/Vue see it) — by `selector` or `ref`. No CDP | `{ selected, value, label }` |\n| `hover` | Move the mouse over an element to reveal menus/tooltips/hover content — by `selector` or `ref` | `{ hovered }` |\n| `go_back` / `go_forward` | Navigate history and wait for load. No CDP | `{ url, finalUrl, settled, onChallenge }` |\n| `reload` | Reload the tab (optional `bypassCache`) and wait for load. No CDP | `{ url, finalUrl, settled, onChallenge }` |\n| `wait_for_function` | Poll a JS expression until it's truthy, or time out | `{ satisfied, value, waitedMs }` |\n| `get_cookies` / `set_cookie` | Read/set cookies for the page (persist in the profile). No CDP | `{ cookies, count }` / `{ set, name }` |\n| `get_local_storage` / `set_local_storage` | Read/write the page's localStorage. No CDP | `{ items, count }` / `{ set, key }` |\n| `download` | Download a URL to disk (a \"Download CSV/export\" or media file) and return the path. No CDP. `filename` is relative to the download folder | `{ path, filename, mime, bytes }` |\n| `save_pdf` | Render the current page to a PDF and save it to disk (CDP). `filename` relative to the download folder | `{ path, filename, bytes }` |\n| `open_tab` | Open a new tab (optionally load a `url`) and get a handle to drive it. No CDP | `{ tab, url, finalUrl, settled, onChallenge, isLaneDefault }` |\n| `list_tabs` | List your tabs (handle, url, title, active, which is the default). No CDP | `{ tabs, count }` |\n| `close_tab` | Close one of your tabs by handle. No CDP | `{ closed, tab }` |\n| `run_script` | Replay a workflow: an ordered list of tool-call steps, each optionally guarded by `pre` / verified by an `expect` effect contract. `from` resumes from a step. No CDP beyond what each step's own tool uses | `{ ok, outcome, data, assertions, steps, failure? }` |\n| `record_start` / `record_stop` | Record your tool calls into a replayable draft script, with candidate assertions inferred from what actually changed | `{ recording }` / `{ script }` |\n\nReads (`navigate`, `get_html`, `get_markdown`, `wait_for_selector`, `snapshot`, `extract`, `extract_links`,\n`wait_for_response`, `wait_for_network_idle`, `wait_for_human`, `capture_console`, `select_option`, `go_back`, `go_forward`,\n`reload`, `get_cookies`, `set_cookie`, `get_local_storage`, `set_local_storage`,\n`download`, `capture_requests` metadata, and `screenshot`'s default\nviewport/`scroll` modes) never touch CDP. The interaction tools (`run_js`,\n`click`, `type`, `press_key`, `hover`, `wait_for_function`, `save_pdf`, `scroll`\ngesture, `screenshot`'s `fullPage`/`selector` modes, and `capture_requests`'s\nbody-recording session) attach `chrome.debugger` only while they run — which\nshows Chrome's \"started debugging this browser\" infobar during that call.\n\n`run_script`'s **assertions are CDP-free too** — they read the page with\n`chrome.scripting` and the passive network buffer — so guarding a scripted\nworkflow adds no automation fingerprint of its own. A step only uses CDP if the\nstep's own tool does.\n\nEvery tool also takes an optional **`timeoutMs`** to override its default time\nbudget — raise it for a slow `navigate` or a long `run_js`, or lower it to fail\nfast.\n\n## Scripting — replay a workflow, and know when it breaks\n\nOnce a workflow is known, an agent shouldn't re-derive it every time. `run_script`\nreplays an ordered list of tool-call steps in **one call** — no model turn per\nstep — and each step can carry an **effect contract** that says what it was\nsupposed to cause:\n\n```jsonc\n{ \"version\": 1, \"steps\": [\n  { \"tool\": \"navigate\", \"params\": { \"url\": \"https://example.com/login\" } },\n  { \"tool\": \"type\",  \"params\": { \"selector\": \"#user\", \"text\": \"${SECRET:user}\" } },\n  { \"tool\": \"type\",  \"params\": { \"selector\": \"#pass\", \"text\": \"${SECRET:pass}\" } },\n  { \"tool\": \"click\", \"params\": { \"selector\": \"button[type=submit]\" },\n    \"expect\": [\n      { \"assert\": \"network\", \"method\": \"POST\", \"url\": \"**/login\", \"status\": 302 },\n      { \"assert\": \"url\", \"pathEquals\": \"/\" },\n      { \"assert\": \"selector\", \"selector\": \"a[href='/logout']\", \"state\": \"present\" }\n    ] },\n  { \"tool\": \"extract\", \"params\": { \"container\": \".row\", \"fields\": { \"title\": \"h3\" } },\n    \"expect\": [ { \"assert\": \"count\", \"selector\": \".row\", \"min\": 1 } ] }\n] }\n```\n\n**Assertions** work at five layers — `network` (method + URL glob + status),\n`url`, `selector`, `text`, `count` — each with `onFail`: `halt` (default), `warn`,\nor `retry`. Prefer `network` where a step hits a server: it's the contract\nbetween client and server, where the state change actually happens, so it catches\nthe failures a DOM check can't — a page that renders \"Success!\" over a `402`.\n\n**The result has two channels**, joined but never blended: your data in `data`,\nthe verdicts in `assertions`, plus a per-step trace.\n\n**When reality diverges, it hands back the yoke.** A failed `halt` contract stops\nthe run and returns a `failure` payload — the failing contract plus a page\nsnapshot at the point of divergence — so the agent can fix the step and call\n`run_script { from: <haltedAt> }` to **resume from the fault**, not the top. A\nmutating step at the resume boundary is never silently re-fired, so you don't\ndouble-submit.\n\n**You don't have to write scripts by hand.** `record_start`, do the workflow\nnormally, `record_stop` — you get a draft with **candidate assertions inferred\nfrom what actually changed** (the real status a request returned, the URL it\nlanded on, how many rows came back), and password fields redacted to\n`${SECRET:…}`. Curate and save it.\n\nScripts are deliberately **linear** — no loops, no branching, no data flowing\nbetween steps. A script does the deterministic part; the moment something needs a\ndecision, that's the agent's job again.\n\nCredentials go in `secrets` at call time and are never stored in the script.\n\n## Multiple tabs\n\nThe daemon owns one shared browser, but tabs are isolated per connection: each\n`plk mcp` process is a **lane** with its own default tab. Separate agents that\neach run their own `plk mcp` share the one warm, logged-in browser without\ncolliding — no setup, existing single-tab code just works.\n\n> **Agents: work only in tabs you opened.** Subagents typically inherit their\n> parent session's MCP connection — so they share a lane *and its default tab*,\n> and will navigate it out from under each other. The collision is **silent**:\n> you get the other agent's page back under your own request, with no error.\n> Pluckor can't detect this (one connection carries no per-caller identity), so\n> the discipline is the control:\n>\n> 1. `open_tab` before your first navigation, and pass that handle on every call.\n> 2. Keep using it — one tab for the session, not one per step.\n> 3. Never drive a tab you didn't open — not another agent's, and not one the\n>    human has open. `list_tabs` showing a tab is not permission to use it.\n> 4. Open as many as you need, and `close_tab` each one you opened.\n> 5. On any `NO_TAB` your handle is dead (`tab t2 was closed …` if someone\n>    closed it, `unknown tab handle: t2` if you closed it or it was never\n>    yours) — open a new tab, never fall back to whatever tab happens to be there.\n\n`open_tab` returns a `tab` handle, and every tool accepts an optional **`tab`**\nto target it (omit it for your lane's default tab).\n\n```\nopen_tab { url: \"https://example.com/list\" }   → { tab: \"t2\" }\nextract  { container: \".row\", fields: {…}, tab: \"t2\" }\nnavigate { url: \"https://example.com/item/1\", tab: \"t3\" }\nlist_tabs                                        → your tabs\nclose_tab { tab: \"t2\" }\n```\n\nHandles and default tabs are lane-scoped: a connection only sees and drives its\nown tabs.\n\n## Multiple browsers (separate instances)\n\nWhen agents are doing *completely unrelated* work and shouldn't share a session\nat all, run **separate instances** — each its own browser, profile, logins,\ndaemon, and ports. Set **`PLUCKOR_INSTANCE`** (a name or number):\n\n```jsonc\n// two MCP servers → two independent browsers\n{\n  \"mcpServers\": {\n    \"pluckor\":      { \"command\": \"pluckor\", \"args\": [\"mcp\"] },\n    \"pluckor-work\": { \"command\": \"pluckor\", \"args\": [\"mcp\"],\n                      \"env\": { \"PLUCKOR_INSTANCE\": \"work\" } }\n  }\n}\n```\n\n`PLUCKOR_INSTANCE=work` gives that daemon its own home\n(`~/.pluckor-bridge-work`), profile, ports, and auth token — derived\ndeterministically, so `plk`/`plk mcp` agree with no discovery. Unset = the\ndefault instance, unchanged.\n\n- Ports: default `9234`/`9235`; integer `N` → `+2N`; a name → a stable hash.\n  Override with `PLUCKOR_WS_PORT` / `PLUCKOR_CONTROL_PORT`.\n- The Chrome download cache is shared (no re-download); profiles/logins are\n  per-instance. `plk status` / `plk stop` target the instance in the env.\n\nRule of thumb: **one browser, many lanes/tabs** (above) for related work that can\nshare logins; **separate instances** for unrelated work that shouldn't.\n\n## Running in a container / headless Linux\n\nPluckor runs a **real, headful Chrome** — never `--headless` (headless has a\ndetectable fingerprint, which defeats the point). On a server or container with\nno physical display, you keep Chrome headful and give it a **virtual display\n(Xvfb)**:\n\n- Provide a display: `Xvfb :99 & export DISPLAY=:99` (or wrap the command).\n- Set **`PLUCKOR_CHROME_FLAGS=\"--no-sandbox --disable-dev-shm-usage\"`** —\n  containers need `--no-sandbox` (no user namespaces as root) and\n  `--disable-dev-shm-usage` (tiny `/dev/shm`).\n- Build for **`linux/amd64`** — on Linux, Chrome for Testing is amd64-only\n  (there's no arm64 build), so on Apple Silicon / arm hosts build/run the image\n  with `--platform linux/amd64`.\n- Install Chrome's shared libraries (`libnss3`, `libgbm1`, `libatk-bridge2.0`,\n  fonts, …) and `unzip`.\n\nA ready-to-adapt **Dockerfile** and entrypoint live in\n[`examples/docker/`](examples/docker/). This exact setup is verified end-to-end\nin CI-style testing (headful Chrome under Xvfb drives a page inside the\ncontainer).\n\n### Driving it from outside the container\n\nBy default the daemon+browser and the `plk mcp` proxy must share one loopback\n(the control channel is `127.0.0.1`-only). To keep the **browser+daemon in the\ncontainer** and drive it from an agent **on the host** (or another machine),\nexpose the control port **with a token**:\n\n- In the container: `PLUCKOR_CONTROL_BIND=0.0.0.0` and `PLUCKOR_CONTROL_TOKEN=…`\n  (the daemon *refuses to start* exposed without a token), and publish the port —\n  `docker run -p 127.0.0.1:9235:9235 …`. Start the daemon inside (`plk start`).\n- On the host, point the proxy at it: `PLUCKOR_CONTROL_HOST=127.0.0.1` (the\n  published port), the same `PLUCKOR_CONTROL_TOKEN`, and `PLUCKOR_ATTACH=1` (don't\n  spawn a local daemon). For a daemon on another machine, set\n  `PLUCKOR_CONTROL_HOST` to its host/IP (and put the port on a trusted network or\n  behind a tunnel — the token is the gate).\n\nThe agent always drives the page from *outside* it (tool calls, never code in the\npage). This just lets the whole Pluckor unit live in a container while the agent\nruns elsewhere.\n\nTwo extra **management** tools let an agent recover on its own instead of getting\nstuck:\n\n| Tool | What it does | Returns |\n|------|--------------|---------|\n| `status` | Daemon health: proxy vs daemon version, whether the daemon is outdated, browser connected, control reachable | `{ proxyVersion, controlReachable, daemon, outdated }` |\n| `restart` | Stop the daemon — even a stale-pid or outdated one — start a fresh one, and reconnect | `{ restarted, daemon }` |\n\nIf a browser tool fails with `NO_BROWSER` / `NOT_CONNECTED` / `CONNECTION_LOST` /\na timeout, the error tells the agent to call `restart` and retry. A dropped\ncontrol socket reconnects on its own; `restart` is for a daemon that is stale,\nwedged, or an **older version** than the one you just installed. (Because the\nbrowser is shared, `restart` bounces it for every session.)\n\n---\n\n## How it works\n\n```\nagent   ── MCP/stdio ──▶  plk mcp (proxy)  ─┐\nprogram ── NDJSON/argv ─▶  plk call | pipe ─┤  WebSocket (control)\n                                            ▼\n                      plk daemon ──▶ Chrome for Testing + Pluckor extension\n                          │                      │\n                          │  WebSocket           │ content script (reads, no CDP)\n                          └────────────────────▶ │ chrome.debugger (run_js/click/type)\n                                                 ▼\n                                            the live page\n```\n\nThe caller invokes a tool → its front end (the MCP proxy, or `plk call`/`plk\npipe`) forwards it to the daemon → the daemon drives the extension → the\nextension acts on the page and sends the result back the same way. The two front\nends share one tool registry and one validation path, so they can't drift.\nEverything binds to `127.0.0.1` only; the browser is never exposed off-box.\n\nNeither front end queues: the daemon handles each control call independently and\nthe extension dispatches per command, so many tabs can be working at once —\nwhether that's several agents on their own `plk mcp`, or one `plk pipe` session\ndriving ten tabs in parallel.\n\n---\n\n## Example: scrape a Cloudflare-protected listing\n\n```\nnavigate           { \"url\": \"https://www.g2.com/categories/mortgage-crm\" }\nwait_for_selector  { \"selector\": \".product-card\" }\nrun_js             { \"expression\": \"Array.from(document.querySelectorAll('.product-card')).map(c => c.querySelector('a[href*=\\\"/products/\\\"]')?.textContent.trim())\" }\n```\n\n→ the agent gets back a JSON array of product names. (The repo's\n`examples/g2-extract.ts` shows a full list → detail-page pipeline pulling\nratings + review counts across multiple pages in one browser session.)\n\n---\n\n## Configuration\n\n| Env var | Default | Purpose |\n|---------|---------|---------|\n| `PLUCKOR_HOME` | `~/.pluckor-bridge` | Persistent Chrome profile + Chrome for Testing download |\n| `PLUCKOR_EXTENSION_DIST` | (bundled) | Override the extension directory (advanced) |\n| `PLUCKOR_NO_FEEDBACK` | (unset) | Set to `1` to remove the optional agent-feedback request (below) |\n\nThe extension ships **inside this package** (it's not a separate install), and\nthe persistent profile keeps cookies/logins across runs.\n\n### Agent feedback (optional, on by default)\n\nPluckor is driven by agents, so the ones best placed to notice that a tool is\nbuggy, confusingly named, or missing something are the agents using it — and they\nhave no way to tell us. At startup the MCP server therefore *invites* the agent to\nopen an issue at [github.com/pluckor/pluckor-feedbacks](https://github.com/pluckor/pluckor-feedbacks/issues)\nwhen it hits a bug, an awkward edge, a docs gap, or wishes a capability existed.\n\nIt's framed as a request, never a requirement, and explicitly ranked below the\nuser's actual task; it also tells the agent not to put credentials, personal data,\nor scraped page content into an issue. Set **`PLUCKOR_NO_FEEDBACK=1`** and the\nrequest is omitted entirely — it's sent as MCP server `instructions`, so the\nopt-out is real rather than advisory.\n\n---\n\n## Notes & limits\n\n- **First run** downloads Chrome for Testing; later runs reuse the cache.\n- The browser is **real and visible** — a window opens. Reads leave no automation\n  fingerprint; the `chrome.debugger` escalation is only for JS eval and trusted\n  input.\n- **One browser per machine.** The daemon runs a single browser on a fixed local\n  port; concurrent agent sessions share it (they don't each launch their own).\n- **Interactive Cloudflare Turnstile** (the checkbox) is a known boundary — a\n  CDP-dispatched click can be detected, so treat it as needing a human.\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}