{"_id":"@digital-gravy/etch-connector","_rev":"10-d6866b849e9628cc78328020b7aa159b","name":"@digital-gravy/etch-connector","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.1":{"name":"@digital-gravy/etch-connector","version":"0.1.1","author":{"name":"Digital Gravy LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@digital-gravy/etch-connector@0.1.1","maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"homepage":"https://github.com/Digital-Gravy/etch-connector#readme","bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"bin":{"etch-connector":"dist/cli.js"},"dist":{"shasum":"20852ac3241e8c9b43e84b99f18863ed7f7f90ba","tarball":"https://registry.npmjs.org/@digital-gravy/etch-connector/-/etch-connector-0.1.1.tgz","fileCount":10,"integrity":"sha512-NyQ+folcwwRa3Gje8W2wQiYcr8hU0o+AMRHgG0db18LO12wC7Dp/F2WOhMzY7ay5zhG1GHurIdgjgLJne7NGTQ==","signatures":[{"sig":"MEUCIQC1YdwyqfsVo2SxkfwTAb4Au3GOVQzKDEulhiEFo8nkMQIga3Y5rcEb4G+igSFGYJQFhOcNV8LJnLRBfEwdDV/F9pM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64453},"main":"./dist/index.js","type":"module","engines":{"node":">=18"},"exports":{".":"./dist/index.js"},"gitHead":"05c029976be40d6bf4401302b797e13dee0bf6e5","scripts":{"cli":"tsx src/cli.ts","dev":"tsx --watch src/cli.ts serve","lint":"bun run eslint && bun run format:check","test":"vitest run","build":"tsc","serve":"tsx src/cli.ts serve","eslint":"eslint .","format":"prettier --write .","compile":"bun build ./src/cli.ts --compile --outfile etch-connector","prepare":"husky","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"christophsanz","email":"chris@digitalgravy.co"},"repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"_npmVersion":"11.16.0","description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","directories":{},"lint-staged":{"*":"prettier --write --ignore-unknown"},"_nodeVersion":"22.22.2","dependencies":{"ws":"^8.18.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","eslint":"^9.39.2","vitest":"^4.0.18","globals":"^17.1.0","prettier":"^3.8.1","@types/ws":"^8.5.13","@eslint/js":"^9.39.2","typescript":"^5.7.0","@types/node":"^22.10.0","lint-staged":"^16.2.7","typescript-eslint":"^8.53.1","eslint-config-prettier":"^10.1.8"},"_npmOperationalInternal":{"tmp":"tmp/etch-connector_0.1.1_1781786422941_0.7589309514265774","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@digital-gravy/etch-connector","version":"0.1.2","author":{"name":"Digital Gravy LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@digital-gravy/etch-connector@0.1.2","maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"homepage":"https://github.com/Digital-Gravy/etch-connector#readme","bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"bin":{"etch-connector":"dist/cli.js"},"dist":{"shasum":"7d162fed942e561f5ea8efd8cb981be8c1100501","tarball":"https://registry.npmjs.org/@digital-gravy/etch-connector/-/etch-connector-0.1.2.tgz","fileCount":10,"integrity":"sha512-MtdI96RMY8FLh7SJeJd3PdA9kMNpu2UaQP4Wd3z6PMh2c7gJ+BGc72tq1ZyWBaGUylGcM0T4WDfMLo1kyUDzoQ==","signatures":[{"sig":"MEQCIEQLla0pK3WShQXBBo80hdMOAeqEuIIoQPf23OMM4IzCAiAHHzMV7mwGeZfxr+Uif6tuoa4TcOujOG1PVfAs3wOt9g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":65096},"main":"./dist/index.js","type":"module","engines":{"node":">=18"},"exports":{".":"./dist/index.js"},"gitHead":"36c434c6d4586d911d77bdb35bff1aed39a955a8","scripts":{"cli":"tsx src/cli.ts","dev":"tsx --watch src/cli.ts serve","lint":"bun run eslint && bun run format:check","test":"vitest run","build":"tsc","serve":"tsx src/cli.ts serve","eslint":"eslint .","format":"prettier --write .","compile":"bun build ./src/cli.ts --compile --outfile etch-connector","prepare":"husky","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"christophsanz","email":"chris@digitalgravy.co"},"repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"_npmVersion":"11.16.0","description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","directories":{},"lint-staged":{"*":"prettier --write --ignore-unknown"},"_nodeVersion":"22.22.2","dependencies":{"ws":"^8.18.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","eslint":"^9.39.2","vitest":"^4.0.18","globals":"^17.1.0","prettier":"^3.8.1","@types/ws":"^8.5.13","@eslint/js":"^9.39.2","typescript":"^5.7.0","@types/node":"^22.10.0","lint-staged":"^16.2.7","typescript-eslint":"^8.53.1","eslint-config-prettier":"^10.1.8"},"_npmOperationalInternal":{"tmp":"tmp/etch-connector_0.1.2_1781788054624_0.2238715008842247","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@digital-gravy/etch-connector","version":"0.1.3","author":{"name":"Digital Gravy LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@digital-gravy/etch-connector@0.1.3","maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"homepage":"https://github.com/Digital-Gravy/etch-connector#readme","bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"bin":{"etch-connector":"dist/cli.js"},"dist":{"shasum":"3f8920221a8431785f767df4dd2ac2db77991907","tarball":"https://registry.npmjs.org/@digital-gravy/etch-connector/-/etch-connector-0.1.3.tgz","fileCount":10,"integrity":"sha512-aw9QJcw4ZFnlGq0NpSwQnwY20V1z7VhXo+12QH0p5EEf16emAKa2MZYPoTNNOi2vnqsN8rmjnrsD3AVDVv5f9g==","signatures":[{"sig":"MEUCICOdp/2G9dEUyAlD36VRcRVPx81bV/P2eBvzbl7wvP15AiEAuR5GfBlHbruQgWgVNGLJHf1fje3okb//8mLBq6h0emo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":66925},"main":"./dist/index.js","type":"module","engines":{"node":">=18"},"exports":{".":"./dist/index.js"},"gitHead":"9bae4af84df1609053c3dd08a592f1f88eb263b8","scripts":{"cli":"tsx src/cli.ts","dev":"tsx --watch src/cli.ts serve","lint":"bun run eslint && bun run format:check","test":"vitest run","build":"tsc","serve":"tsx src/cli.ts serve","eslint":"eslint .","format":"prettier --write .","compile":"bun build ./src/cli.ts --compile --outfile etch-connector","prepare":"husky","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"christophsanz","email":"chris@digitalgravy.co"},"repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"_npmVersion":"11.16.0","description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","directories":{},"lint-staged":{"*":"prettier --write --ignore-unknown"},"_nodeVersion":"22.22.2","dependencies":{"ws":"^8.18.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","eslint":"^9.39.2","vitest":"^4.0.18","globals":"^17.1.0","prettier":"^3.8.1","@types/ws":"^8.5.13","@eslint/js":"^9.39.2","typescript":"^5.7.0","@types/node":"^22.10.0","lint-staged":"^16.2.7","typescript-eslint":"^8.53.1","eslint-config-prettier":"^10.1.8"},"_npmOperationalInternal":{"tmp":"tmp/etch-connector_0.1.3_1781796631966_0.872093582128523","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@digital-gravy/etch-connector","version":"0.1.4","author":{"name":"Digital Gravy LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@digital-gravy/etch-connector@0.1.4","maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"homepage":"https://github.com/Digital-Gravy/etch-connector#readme","bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"bin":{"etch-connector":"dist/cli.js"},"dist":{"shasum":"dad6bc781b88b48a72045c3c71104ccf8ce29d75","tarball":"https://registry.npmjs.org/@digital-gravy/etch-connector/-/etch-connector-0.1.4.tgz","fileCount":10,"integrity":"sha512-2EaUAM4sfumVR8y5FZuSQNk+dA8QkE67o89m16ANzKELdY7L+Zfc5LQytfoSBk73YKpAQGjy4mlpnQ7KTrTH3Q==","signatures":[{"sig":"MEYCIQC4hN2WveYwHXWFDjhF0FhNHlpjUuUEOmk2kH32O5qtTgIhAKKF3qrpHPuTiau8jF1BvPbJvkSHRSy9nN115J+HHbx2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67310},"main":"./dist/index.js","type":"module","engines":{"node":">=18"},"exports":{".":"./dist/index.js"},"gitHead":"120754fb6219ab59bd019fd3d5d5f08a693deed1","scripts":{"cli":"tsx src/cli.ts","dev":"tsx --watch src/cli.ts serve","lint":"bun run eslint && bun run format:check","test":"vitest run","build":"tsc","serve":"tsx src/cli.ts serve","eslint":"eslint .","format":"prettier --write .","compile":"bun build ./src/cli.ts --compile --outfile etch-connector","prepare":"husky","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"christophsanz","email":"chris@digitalgravy.co"},"repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"_npmVersion":"11.16.0","description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","directories":{},"lint-staged":{"*":"prettier --write --ignore-unknown"},"_nodeVersion":"22.22.2","dependencies":{"ws":"^8.18.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","eslint":"^9.39.2","vitest":"^4.0.18","globals":"^17.1.0","prettier":"^3.8.1","@types/ws":"^8.5.13","@eslint/js":"^9.39.2","typescript":"^5.7.0","@types/node":"^22.10.0","lint-staged":"^16.2.7","typescript-eslint":"^8.53.1","eslint-config-prettier":"^10.1.8"},"_npmOperationalInternal":{"tmp":"tmp/etch-connector_0.1.4_1782140239804_0.5728192252236199","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@digital-gravy/etch-connector","version":"0.1.5","author":{"name":"Digital Gravy LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@digital-gravy/etch-connector@0.1.5","maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"homepage":"https://github.com/Digital-Gravy/etch-connector#readme","bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"bin":{"etch-connector":"dist/cli.js"},"dist":{"shasum":"00d79e80980e3748857b12af2af4fa32218931e2","tarball":"https://registry.npmjs.org/@digital-gravy/etch-connector/-/etch-connector-0.1.5.tgz","fileCount":9,"integrity":"sha512-FPrf2hC72d5wlZicRb1btfPV+aamd9hYkeG1oC0PW2szEhlIh9qUxtna8A2QIZf89EQ6lzqQ7nyHoZIfPBPDfw==","signatures":[{"sig":"MEQCIDzu50CogAsx7hHsatZvFN8luPfWuxhDCs8SF3lVYzE8AiBs3tYiBTu2ooOEGETultEQrAjZTd5HnjimQ2x+EZdPEw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":62846},"main":"./dist/index.js","type":"module","engines":{"node":">=18"},"exports":{".":"./dist/index.js"},"gitHead":"dd58b8cd00c6c06a74f48e3c663aede87a64292f","scripts":{"cli":"tsx src/cli.ts","dev":"tsx --watch src/cli.ts serve","lint":"bun run eslint && bun run format:check","test":"vitest run","build":"tsc","serve":"tsx src/cli.ts serve","eslint":"eslint .","format":"prettier --write .","compile":"bun build ./src/cli.ts --compile --outfile etch-connector","prepare":"husky","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:373d3375-f46b-4615-90b0-c1a3a3539d9e"}},"repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"_npmVersion":"11.18.0","description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","directories":{},"lint-staged":{"*":"prettier --write --ignore-unknown"},"_nodeVersion":"22.23.0","dependencies":{"ws":"^8.18.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","eslint":"^9.39.2","vitest":"^4.0.18","globals":"^17.1.0","prettier":"^3.8.1","@types/ws":"^8.5.13","@eslint/js":"^9.39.2","typescript":"^5.7.0","@types/node":"^22.10.0","lint-staged":"^16.2.7","typescript-eslint":"^8.53.1","eslint-config-prettier":"^10.1.8"},"_npmOperationalInternal":{"tmp":"tmp/etch-connector_0.1.5_1782828112595_0.43725386782760634","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@digital-gravy/etch-connector","version":"0.2.0","author":{"name":"Digital Gravy LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@digital-gravy/etch-connector@0.2.0","maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"homepage":"https://github.com/Digital-Gravy/etch-connector#readme","bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"bin":{"etch-connector":"dist/cli.js"},"dist":{"shasum":"4ae2a8bd1cb25e0cbc50ce598dafce2ef12ee5fa","tarball":"https://registry.npmjs.org/@digital-gravy/etch-connector/-/etch-connector-0.2.0.tgz","fileCount":10,"integrity":"sha512-uptmkoBlYbfsuxx1PKofjU5WhM6lJHEh/xFSU8HWXSEhxi5WWwYDOBe8SgLmS0XR3zD4KPuJxvPxfSF0ySUctg==","signatures":[{"sig":"MEYCIQCIPQQ0APRSTo1+Op9iJLyY5az+jmGWvxZx27/ajyUi/wIhAJ03Hjsf7afb55WTKAnycIGnhiDFPFqeDhkgkf9b8Emx","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74501},"main":"./dist/index.js","type":"module","engines":{"node":">=18"},"exports":{".":"./dist/index.js"},"gitHead":"cf7b03907acc75e9b2c1bb39925a456bb07fc90a","scripts":{"cli":"tsx src/cli.ts","dev":"tsx --watch src/cli.ts serve","lint":"bun run eslint && bun run format:check","test":"vitest run","build":"tsc","serve":"tsx src/cli.ts serve","eslint":"eslint .","format":"prettier --write .","compile":"bun build ./src/cli.ts --compile --outfile etch-connector","prepare":"husky","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:373d3375-f46b-4615-90b0-c1a3a3539d9e"}},"repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"_npmVersion":"12.0.2","description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","directories":{},"lint-staged":{"*":"prettier --write --ignore-unknown"},"_nodeVersion":"22.23.2","dependencies":{"ws":"^8.18.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","eslint":"^9.39.2","vitest":"^4.0.18","globals":"^17.1.0","prettier":"^3.8.1","@types/ws":"^8.5.13","@eslint/js":"^9.39.2","typescript":"^5.7.0","@types/node":"^22.10.0","lint-staged":"^16.2.7","typescript-eslint":"^8.53.1","eslint-config-prettier":"^10.1.8"},"_npmOperationalInternal":{"tmp":"tmp/etch-connector_0.2.0_1788167008485_0.19448361579356277","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@digital-gravy/etch-connector","version":"0.2.1","author":{"name":"Digital Gravy LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@digital-gravy/etch-connector@0.2.1","maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"homepage":"https://github.com/Digital-Gravy/etch-connector#readme","bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"bin":{"etch-connector":"dist/cli.js"},"dist":{"shasum":"81638a29b4f9ada03031e49d32c63ea33a3f8b0f","tarball":"https://registry.npmjs.org/@digital-gravy/etch-connector/-/etch-connector-0.2.1.tgz","fileCount":10,"integrity":"sha512-lbBLS57/I2o/3tH8wHjJSt7V+dgebLe5QxMY+hcLicn1HtCPbX4W8nbzr4m2L3g7XZFQkadZokz/IGETzUthKw==","signatures":[{"sig":"MEUCIHj60HNG56gm4Rhx2WI/mPjEhSTuw+9Avt7W/lYEO0Z7AiEAq69yansSnYfWCqbJbWw73uo1rdXqjyTk0GUAWV5/JTw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIDZuJH+p5AfC+XQYmmLu2U+ui3Iq4pq+JpCob08WoctZAiEA3wzxvs3EFihBS4NfkymjSzB1mt8E1aABNh8z1XTnb9A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":79314},"main":"./dist/index.js","type":"module","engines":{"node":">=18"},"exports":{".":"./dist/index.js"},"gitHead":"52c18d32e0c3bfc76cc50fec56265c3ce17ae5ed","scripts":{"cli":"tsx src/cli.ts","dev":"tsx --watch src/cli.ts serve","lint":"bun run eslint && bun run format:check","test":"vitest run","build":"tsc","serve":"tsx src/cli.ts serve","eslint":"eslint .","format":"prettier --write .","compile":"bun build ./src/cli.ts --compile --outfile etch-connector","prepare":"husky","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:373d3375-f46b-4615-90b0-c1a3a3539d9e"}},"repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"_npmVersion":"12.0.2","description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","directories":{},"lint-staged":{"*":"prettier --write --ignore-unknown"},"_nodeVersion":"22.23.2","dependencies":{"ws":"^8.18.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","eslint":"^9.39.2","vitest":"^4.0.18","globals":"^17.1.0","prettier":"^3.8.1","@types/ws":"^8.5.13","@eslint/js":"^9.39.2","typescript":"^5.7.0","@types/node":"^22.10.0","lint-staged":"^16.2.7","typescript-eslint":"^8.53.1","eslint-config-prettier":"^10.1.8"},"_npmOperationalInternal":{"tmp":"tmp/etch-connector_0.2.1_1789655770134_0.2936398200087105","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"_id":"@digital-gravy/etch-connector@0.2.2","bin":{"etch-connector":"dist/cli.js"},"bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"dist":{"shasum":"1f758335c389a89ca9235b6c34d4c82ec7b639eb","tarball":"https://registry.npmjs.org/@digital-gravy/etch-connector/-/etch-connector-0.2.2.tgz","fileCount":10,"integrity":"sha512-MUKJ5f8I24iEBm7UHMI05SEhQvfptC+it54uZiqoUbqQRgdRTGFjzUAooiukieky8o3tvke34SO3XhsVyp1Zlg==","signatures":[{"sig":"MEQCIEWMJg6iL3+2yzjPG7qJM6WSsiAxbccSwGuCKQWUFwd9AiA11BB8LJD3OTuNWLxjTQwvc7RL3GnpMPUcd1hVXSqG+g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCHrEPFzALhFnRwpK6yoC4JJKT7L17WYk3peagkd0O27wIgbk8Bppctxs+kx8Mw5kRmM+Sp7T7b8SonYeMR5j8qN4o="}],"unpackedSize":79908},"main":"./dist/index.js","name":"@digital-gravy/etch-connector","type":"module","author":{"name":"Digital Gravy LLC"},"engines":{"node":">=18"},"exports":{".":"./dist/index.js"},"gitHead":"2735625add2b2aa86318337159d8a111f841fb75","license":"SEE LICENSE IN LICENSE","scripts":{"cli":"tsx src/cli.ts","dev":"tsx --watch src/cli.ts serve","lint":"bun run eslint && bun run format:check","test":"vitest run","build":"tsc","serve":"tsx src/cli.ts serve","eslint":"eslint .","format":"prettier --write .","compile":"bun build ./src/cli.ts --compile --outfile etch-connector","prepare":"husky","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run build"},"version":"0.2.2","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:373d3375-f46b-4615-90b0-c1a3a3539d9e"}},"homepage":"https://github.com/Digital-Gravy/etch-connector#readme","repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"_npmVersion":"12.0.2","description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","directories":{},"lint-staged":{"*":"prettier --write --ignore-unknown"},"maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"_nodeVersion":"22.23.2","dependencies":{"ws":"^8.18.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","eslint":"^9.39.2","vitest":"^4.0.18","globals":"^17.1.0","prettier":"^3.8.1","@types/ws":"^8.5.13","@eslint/js":"^9.39.2","typescript":"^5.7.0","@types/node":"^22.10.0","lint-staged":"^16.2.7","typescript-eslint":"^8.53.1","eslint-config-prettier":"^10.1.8"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/etch-connector_0.2.2_1790005098412_0.8575676254878031"}}},"time":{"created":"2026-06-18T12:30:45.322Z","modified":"2026-09-21T15:38:18.748Z","0.1.0":"2026-06-18T12:30:45.614Z","0.1.1":"2026-06-18T12:40:23.080Z","0.1.2":"2026-06-18T13:07:34.761Z","0.1.3":"2026-06-18T15:30:32.101Z","0.1.4":"2026-06-22T14:57:19.944Z","0.1.5":"2026-06-30T14:01:52.830Z","0.2.0":"2026-08-31T09:03:28.598Z","0.2.1":"2026-09-17T14:36:10.227Z","0.2.2":"2026-09-21T15:38:18.508Z"},"bugs":{"url":"https://github.com/Digital-Gravy/etch-connector/issues"},"author":{"name":"Digital Gravy LLC"},"license":"SEE LICENSE IN LICENSE","homepage":"https://github.com/Digital-Gravy/etch-connector#readme","repository":{"url":"git+https://github.com/Digital-Gravy/etch-connector.git","type":"git"},"description":"Local bridge that lets an AI harness drive a live Etch tab by evaluating scripts against the etch-public-api over a WebSocket.","maintainers":[{"name":"jrmyfranck","email":"jrmyfranck@gmail.com"},{"name":"christophsanz","email":"chris@digitalgravy.co"},{"name":"reinhard-sanz","email":"reinhard@sanz.at"},{"name":"matteo-greco","email":"matteo@digitalgravy.co"}],"readme":"# etch-connector\n\n> **AGENT: read this first.** Before interacting with Etch in any way, run\n> `etch-connector --help` (or `npx @digital-gravy/etch-connector --help`) and\n> read the **entire** output. It documents the backends, commands, flags, the\n> stdout/stderr/exit-code contract, and how to pull the current Etch docs —\n> everything you need to drive a tab correctly. Do not call any other command\n> until you have read it.\n\nA tiny local bridge that lets an AI harness — Claude Code, Cowork, or any tool\nthat can run a shell command — **drive a live Etch builder tab** by evaluating\nscripts against the [`etch-public-api`](https://www.npmjs.com/package/@digital-gravy/etch-public-api)\nsurface (`window.etch.*`).\n\nEtch's scriptable API only exists _inside the browser_. There is no server you\ncan call directly. So this connector inverts the usual direction: the browser\n**dials out** to the connector over a WebSocket (the same way Chrome remote\ndebugging works, but in reverse), and the connector relays scripts into the tab\nand streams the result back.\n\n```\nClaude Code / Cowork\n      │  shell:  etch-connector eval -t homepage \"return ...\"\n      ▼\n  etch-connector  (the `serve` daemon)\n      │  ▲   WebSocket  (tab dials in via etch.connectAs)\n      ▼  │\n  Etch builder tab  ──►  window.etch.*\n```\n\n## Status\n\nThis is an **eval relay**: the harness sends a JavaScript snippet, the page runs\nit as an async function, and the return value + console output come back. It is\nnot an MCP server yet — see [Going to MCP](#going-to-mcp-later).\n\nScripts run in a **page-enforced safe mode**: the script sees only `etch` and\nthe standard JS built-ins. `window`, `document`, `fetch`, storage, `eval`, … are\nwithheld.\n\n## Install & run\n\nNo install needed — run it on demand with `npx` (npm) or `bunx` (Bun):\n\n```bash\nnpx @digital-gravy/etch-connector serve\n# or\nbunx @digital-gravy/etch-connector serve\n```\n\nTo get the short `etch-connector` command on your `PATH`, install it globally:\n\n```bash\nnpm install -g @digital-gravy/etch-connector   # or: bun install -g …\netch-connector serve\n```\n\n> Using the connector requires a valid, active Etch license — see\n> [`LICENSE`](LICENSE).\n\nThe examples below use the bare `etch-connector` command; if you're running via\n`npx`/`bunx` instead, prefix them with `npx @digital-gravy/etch-connector` (or\n`bunx …`).\n\n## Use\n\n### 1. Start the daemon (once)\n\n```bash\netch-connector serve\n# bridge   ws://127.0.0.1:7331\n# control  http://127.0.0.1:7332\n```\n\n### 2. Connect a tab\n\n**Primary way — the AI button.** Enable the **AI Connector** in the Etch\nSettings, then open an Etch builder page and click the **AI button** in the left\nsidebar. It connects this tab for you, registering it under your site name (it\njust calls `connectAs` under the hood). Click it again to disconnect.\n\n**Secondary way — the console.** You can also connect manually from the browser\nconsole:\n\n```js\netch.connectAs('homepage');\n```\n\n(`connectAs` is part of the public API; it opens the WebSocket back to the\ndaemon and registers this tab under the given name. Pass `{ port: <n> }` if you\nstarted the daemon on a non-default WebSocket port.)\n\n### 3. Drive it\n\n```bash\n# list connected tabs\netch-connector tabs\n\n# run a script (value → stdout, console output → stderr).\n# reference the API as `etch.*`.\netch-connector eval -t homepage \"return etch.apiVersion\"\n\n# multi-line / from a file / from stdin\netch-connector eval -t homepage -f ./script.js\necho \"return await etch.blocks.getTree()\" | etch-connector eval -t homepage\n```\n\nThe script body runs as an **async function**, so it can `return` a value and\nuse top-level `await`. Write scripts against the `etch-public-api` surface via\nthe `etch` binding (`window` is not available). Examples:\n\n```js\nreturn etch.apiVersion;\nreturn await etch.blocks.getTree();\netch.blocks.select('block-id-123');\nconst groups = await etch.fields.listGroupsAsync();\nreturn groups.length;\n```\n\n### Output contract (for agents)\n\n`eval` keeps stdout clean so a harness can capture it as the result:\n\n- **stdout** — the script's return value, as pretty JSON.\n- **stderr** — forwarded `console.*` output, prefixed with the level, plus\n  connector notes that carry no such prefix (the runtime banner, warnings).\n- **exit code** — `0` success · `2` the script threw · `1` operational failure\n  (no such tab, ambiguous target, timeout, daemon unreachable).\n\n## For AI agents\n\n`etch-connector tabs` reports, per tab, which Etch runtime it is and which\nsurfaces that runtime backs (read off `etch.environment`), then prints the\nauthoring rules that follow from it: the dynamic-data model (data sources vs\nloops), the media lookup, the namespaces that throw `NOT_AVAILABLE`, and the\nblock types the runtime can construct. Not every runtime backs every surface, so\nread that before writing scripts — and branch on a capability, never on the\nproduct name. `eval` names the runtime it targets on stderr as a reminder, and\n`tabs --quiet` drops the prose when you are only checking that a tab is still\nconnected.\n\nThe authoritative agent instructions live in **`etch-connector --help`** — read\nthe entire output before interacting with Etch. It covers the backends, commands\nand flags, the stdout/stderr/exit-code contract, how to pull the current Etch\ndocs (Context7 MCP or <https://docs.etchwp.com/public-api>), and the conventions\nfor structuring pages (e.g. the section/container layout pattern). The public API\nmay also expose ready-made skills for common tasks — check the docs before\nimprovising. Project conventions for working on this repo live in\n[`AGENTS.md`](AGENTS.md).\n\n## CLI\n\n```\netch-connector — drive a live Etch tab from the command line\n\nUsage:\n  etch-connector serve [--ws-port 7331] [--control-port 7332] [--ws-host 127.0.0.1]\n  etch-connector tabs  [--json] [--quiet] [--control-port 7332] [--cdp]\n  etch-connector eval  [code] [-t|--tab name] [-f|--file path] [--timeout ms] [--cdp]\n  etch-connector shot      [-t name] [-s|--selector css] [--full] [--jpeg] [-o|--out file] [--freeze=false]   (CDP)\n  etch-connector html      <selector> [-t name]                                              (CDP)\n  etch-connector computed  <selector> [-t name] [--props a,b,c]                               (CDP)\n\nTwo backends:\n  bridge  (default) the tab dials in via etch.connectAs(); page-sandboxed.\n          Scripts see only \"etch\" + the standard JS built-ins.\n  cdp     connect OUT to a Chrome started with --remote-debugging-port=9222.\n          No daemon. Runs at DevTools privilege: full \"window\", plus screenshots,\n          rendered HTML, and computed styles. Opt in with --cdp (or --cdp-port /\n          --remote-debugging-port / --cdp-host). Target a tab with -t <url|title substring>.\n\nExamples:\n  etch-connector serve\n  etch-connector tabs\n  etch-connector eval -t homepage \"return etch.apiVersion\"\n  echo \"return await etch.blocks.getTree()\" | etch-connector eval -t homepage\n  etch-connector eval -t homepage -f ./script.js\n  # CDP backend (Chrome launched with --remote-debugging-port=9222):\n  etch-connector tabs --cdp\n  etch-connector eval --cdp -t etch \"return document.title\"\n  etch-connector shot --cdp -t etch -s .orbit -o orbit.png\n  etch-connector computed --cdp -t etch -s .orbit__chip --props transform,animation-duration\n```\n\nWhen exactly one tab is connected, `-t` is optional. With several tabs you must\nname one.\n\n## HTTP control API\n\nThe daemon also exposes a loopback HTTP API (this is the seam the CLI uses, and\nthe same one a future MCP server would call):\n\n| Method | Path      | Body                                | Returns      |\n| ------ | --------- | ----------------------------------- | ------------ |\n| GET    | `/health` | —                                   | `{ ok }`     |\n| GET    | `/tabs`   | —                                   | `{ tabs }`   |\n| POST   | `/eval`   | `{ tab?, code, timeoutMs?, mode? }` | `EvalResult` |\n\n## Architecture\n\n- [`src/protocol.ts`](src/protocol.ts) — the wire format, mirrored from the\n  Etch-side `bridge.ts`. Keep the two in sync.\n- [`src/bridge-server.ts`](src/bridge-server.ts) — `BridgeServer`, the\n  transport-agnostic core: owns the sockets, tracks tabs by name, correlates\n  requests, handles timeouts and disconnects. **This is the reusable piece.**\n- [`src/control-server.ts`](src/control-server.ts) — the HTTP control API over\n  the core.\n- [`src/guidance.ts`](src/guidance.ts) — turns a tab's `etch.environment`\n  descriptor into the authoring instructions for that runtime.\n- [`src/cli.ts`](src/cli.ts) — the `serve` / `tabs` / `eval` commands.\n\n## Going to MCP later\n\nToday this is a CLI eval relay. A future version will expose the same bridge as\na proper MCP server, so an AI harness can call first-class tools (list tabs, run\na script) directly instead of shelling out — without changing how you connect a\ntab.\n\n## Security\n\nTwo layers, neither a substitute for the other:\n\n**Transport.** Everything binds to `127.0.0.1`, so any local process can reach\nthe daemon. Run it only on a trusted machine and do not expose the ports beyond\nloopback.\n\n**Execution.** Bridge mode runs the script inside a `with`-bound Proxy that\nexposes only `etch` plus the standard JS built-ins and throws on `window`,\n`document`, `fetch`, storage, `eval`, `Function`, … This is a **guardrail, not a\nhardened sandbox**: because the script shares the page's JS realm, a _determined_\nauthor can still reach globals through prototype / constructor chains (e.g.\n`({}).constructor.constructor`). It reliably keeps casual and AI-authored\nscripts on the `etch` surface and closes the obvious escape hatches; it does\n**not** contain hostile code. For a true boundary against adversarial scripts,\nrun the daemon only on a trusted machine.\n","readmeFilename":"README.md"}