{"_id":"@aiworker/web","_rev":"6-14aef0a2136f1c9e43e7232de3a1262b","name":"@aiworker/web","dist-tags":{"latest":"1.23.3"},"versions":{"1.22.0":{"name":"@aiworker/web","version":"1.22.0","_id":"@aiworker/web@1.22.0","maintainers":[{"name":"blockrepo","email":"wbluo@live.cn"}],"bin":{"aiworker":"bin/cli.js"},"dist":{"shasum":"6103a91bbd6f10a71876a01f6ef5f8bdabba1f99","tarball":"https://registry.npmjs.org/@aiworker/web/-/web-1.22.0.tgz","fileCount":1500,"integrity":"sha512-TuGke3sTWyaIQv2V8vjPc+DNP7e60CeufVxRl4Rmkv7GOudTThY6JZss5cfeXYa947MJOoCrmLPCCWa/6t2rSw==","signatures":[{"sig":"MEQCIAKrBoxN4x8owZgdBJYEfZxqG4CZS1LR/f8pFYqLFCsXAiBaDk3NaLyP6EssNJLOd4AmGkIQea7b+q81w3RC3pv7Jg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43580337},"main":"./server/index.js","type":"module","_from":"file:aiworker-web-1.22.0.tgz","types":"./server/index.d.ts","private":false,"scripts":{"dev":"bun run build:watch","lint":"eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js","test":"vitest run","build":"vite build","start":"node bin/cli.js serve","dev:server":"AIWORKER_RELAY_HOST=${AIWORKER_RELAY_HOST:-off} bun server/index.js --port ${AIWORKER_PORT:-3001}","type-check":"tsc --noEmit","build:watch":"vite build --watch","dev:server:watch":"AIWORKER_RELAY_HOST=${AIWORKER_RELAY_HOST:-off} nodemon --watch server --ext js --exec \"bun server/index.js --port ${AIWORKER_PORT:-3001}\""},"_npmUser":{"name":"blockrepo","email":"wbluo@live.cn"},"_resolved":"/Users/block/Downloads/aiworker-web-1.22.0.tgz","_integrity":"sha512-TuGke3sTWyaIQv2V8vjPc+DNP7e60CeufVxRl4Rmkv7GOudTThY6JZss5cfeXYa947MJOoCrmLPCCWa/6t2rSw==","_npmVersion":"10.8.2","description":"[![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1Ni","directories":{},"_nodeVersion":"20.19.0","dependencies":{"ws":"^8.18.3","jose":"^6.1.3","yaml":"^2.8.1","luxon":"^3.5.0","openai":"^4.79.0","bun-pty":"^0.4.5","express":"^5.1.0","node-pty":"1.2.0-beta.12","web-push":"^3.6.7","simple-git":"^3.36.0","compression":"^1.8.1","cron-parser":"^4.9.0","jsonc-parser":"^3.3.1","@octokit/rest":"^22.0.1","@clack/prompts":"^1.1.0","qrcode-terminal":"^0.12.0","@opencode-ai/sdk":"1.18.25","reflect-metadata":"^0.2.2","sherpa-onnx-node":"1.12.28","http-proxy-middleware":"^3.0.5","@simplewebauthn/server":"13.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.6","clsx":"^2.1.1","cmdk":"^1.1.1","cors":"^2.8.5","vite":"^7.1.2","react":"^19.1.1","eslint":"^9.33.0","sonner":"^2.0.7","vitest":"^4.1.4","globals":"^16.3.0","nodemon":"^3.1.7","zustand":"^5.0.8","cross-env":"^7.0.3","react-dom":"^19.1.1","supertest":"^7.2.2","@eslint/js":"^9.33.0","remark-gfm":"^4.0.1","typescript":"~5.9.0","@types/node":"^24.3.1","ghostty-web":"0.4.0","next-themes":"^0.4.6","tailwindcss":"^4.0.0","@types/react":"^19.1.10","autoprefixer":"^10.4.21","concurrently":"^9.2.1","@base-ui/react":"^1.4.0","react-markdown":"^10.1.0","tailwind-merge":"^3.3.1","tw-animate-css":"^1.3.8","workbox-window":"^7.4.0","vite-plugin-pwa":"^1.0.3","@remixicon/react":"^4.7.0","@types/react-dom":"^19.1.7","@types/supertest":"^7.2.0","typescript-eslint":"^8.39.1","@codemirror/lang-go":"^6.0.1","strip-json-comments":"^5.0.3","@codemirror/lang-cpp":"^6.0.3","@radix-ui/react-slot":"^1.2.3","@tailwindcss/postcss":"^4.0.0","@vitejs/plugin-react":"^5.0.0","@radix-ui/react-dialog":"^1.1.15","@radix-ui/react-select":"^2.2.6","@radix-ui/react-toggle":"^1.1.10","@radix-ui/react-tooltip":"^1.2.8","@simplewebauthn/browser":"13.3.0","class-variance-authority":"^0.7.1","@radix-ui/react-separator":"^1.1.7","eslint-plugin-react-hooks":"^5.2.0","@radix-ui/react-collapsible":"^1.1.12","@radix-ui/react-scroll-area":"^1.2.10","eslint-plugin-react-refresh":"^0.5.0","@radix-ui/react-dropdown-menu":"^2.1.16"},"_npmOperationalInternal":{"tmp":"tmp/web_1.22.0_1788359115872_0.06849351785144897","host":"s3://npm-registry-packages-npm-production"}},"1.22.2":{"name":"@aiworker/web","version":"1.22.2","_id":"@aiworker/web@1.22.2","maintainers":[{"name":"blockrepo","email":"wbluo@live.cn"}],"bin":{"aiworker":"bin/cli.js"},"dist":{"shasum":"955af945454ea844199f7fa7fdeb9935648e196f","tarball":"https://registry.npmjs.org/@aiworker/web/-/web-1.22.2.tgz","fileCount":1477,"integrity":"sha512-Df9PbdbNevYtfRc5MkXmsY83ZvMA9jqFu9pCWE9YgZLUpRgk/I78p5jPyGIDH9V1T4S9okR5b4LleZMJOYoSsA==","signatures":[{"sig":"MEYCIQChIfYgEaFACHzdQzF4UrbnYyW3TPDDDj3Z9GJKScjFFQIhAOGBJKZMQzMX+hjNzOYW7YnlZXwhs2pDMd1ZTfJCPqcY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43607346},"main":"./server/index.js","type":"module","types":"./server/index.d.ts","gitHead":"27ce083d57ca0adebbadf143a33bd66cfd5c6bfe","private":false,"scripts":{"dev":"bun run build:watch","lint":"eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js","test":"vitest run","build":"vite build","start":"node bin/cli.js serve","dev:server":"AIWORKER_RELAY_HOST=${AIWORKER_RELAY_HOST:-off} bun server/index.js --port ${AIWORKER_PORT:-3001}","type-check":"tsc --noEmit","build:watch":"vite build --watch","dev:server:watch":"node ./scripts/dev-server-watch.mjs"},"_npmUser":{"name":"blockrepo","email":"wbluo@live.cn"},"_npmVersion":"10.8.2","description":"[![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1Ni","directories":{},"_nodeVersion":"20.19.0","dependencies":{"ws":"^8.18.3","jose":"^6.1.3","yaml":"^2.8.1","luxon":"^3.5.0","openai":"^4.79.0","bun-pty":"^0.4.5","express":"^5.1.0","node-pty":"1.2.0-beta.12","web-push":"^3.6.7","simple-git":"^3.36.0","compression":"^1.8.1","cron-parser":"^4.9.0","jsonc-parser":"^3.3.1","@octokit/rest":"^22.0.1","@clack/prompts":"^1.1.0","qrcode-terminal":"^0.12.0","@opencode-ai/sdk":"1.18.29","reflect-metadata":"^0.2.2","sherpa-onnx-node":"1.12.28","http-proxy-middleware":"^3.0.5","@simplewebauthn/server":"13.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.6","clsx":"^2.1.1","cmdk":"^1.1.1","cors":"^2.8.5","vite":"^7.1.2","react":"^19.1.1","eslint":"^9.33.0","sonner":"^2.0.7","vitest":"^4.1.4","globals":"^16.3.0","nodemon":"^3.1.7","zustand":"^5.0.8","cross-env":"^7.0.3","react-dom":"^19.1.1","supertest":"^7.2.2","@eslint/js":"^9.33.0","remark-gfm":"^4.0.1","typescript":"~5.9.0","@types/node":"^24.3.1","ghostty-web":"0.4.0","next-themes":"^0.4.6","tailwindcss":"^4.0.0","@types/react":"^19.1.10","autoprefixer":"^10.4.21","concurrently":"^9.2.1","@base-ui/react":"^1.4.0","react-markdown":"^10.1.0","tailwind-merge":"^3.3.1","tw-animate-css":"^1.3.8","workbox-window":"^7.4.0","vite-plugin-pwa":"^1.0.3","@remixicon/react":"^4.7.0","@types/react-dom":"^19.1.7","@types/supertest":"^7.2.0","typescript-eslint":"^8.39.1","@codemirror/lang-go":"^6.0.1","strip-json-comments":"^5.0.3","@codemirror/lang-cpp":"^6.0.3","@radix-ui/react-slot":"^1.2.3","@tailwindcss/postcss":"^4.0.0","@vitejs/plugin-react":"^5.0.0","@radix-ui/react-dialog":"^1.1.15","@radix-ui/react-select":"^2.2.6","@radix-ui/react-toggle":"^1.1.10","@radix-ui/react-tooltip":"^1.2.8","@simplewebauthn/browser":"13.3.0","class-variance-authority":"^0.7.1","@radix-ui/react-separator":"^1.1.7","eslint-plugin-react-hooks":"^5.2.0","@radix-ui/react-collapsible":"^1.1.12","@radix-ui/react-scroll-area":"^1.2.10","eslint-plugin-react-refresh":"^0.5.0","@radix-ui/react-dropdown-menu":"^2.1.16"},"_npmOperationalInternal":{"tmp":"tmp/web_1.22.2_1788745692501_0.16411128497403538","host":"s3://npm-registry-packages-npm-production"}},"1.23.0":{"name":"@aiworker/web","version":"1.23.0","_id":"@aiworker/web@1.23.0","maintainers":[{"name":"blockrepo","email":"wbluo@live.cn"}],"bin":{"aiworker":"bin/cli.js"},"dist":{"shasum":"3131c8ef65dcc16a65e0c92721558d4ddb5e09dd","tarball":"https://registry.npmjs.org/@aiworker/web/-/web-1.23.0.tgz","fileCount":1496,"integrity":"sha512-VIzCBCHA4f46rKzzU2gg8j0zVWGlBSIEEX56aeLOSXiKUqOXxex2pZed7ee+O0p+ibpQFS9p5OUTgxZjj6FnbA==","signatures":[{"sig":"MEQCIALIwJgExL5cCdseb6uznHTOJ5u1KOXXulOfRaojrE7XAiBibb/oqliOIIspDGv2kUAbz8KcmNICdlnVIDjtyxkF/Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45271770},"main":"./server/index.js","type":"module","types":"./server/index.d.ts","gitHead":"8987e4d6c4f8dbe058e5e7edc979f71c96fae13d","private":false,"scripts":{"dev":"bun run build:watch","lint":"eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js","test":"vitest run","build":"vite build","start":"node bin/cli.js serve","dev:server":"AIWORKER_RELAY_HOST=${AIWORKER_RELAY_HOST:-off} bun server/index.js --port ${AIWORKER_PORT:-3001}","type-check":"tsc --noEmit","build:watch":"vite build --watch","dev:server:watch":"node ./scripts/dev-server-watch.mjs"},"_npmUser":{"name":"blockrepo","email":"wbluo@live.cn"},"_npmVersion":"10.8.2","description":"[![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1Ni","directories":{},"_nodeVersion":"20.19.0","dependencies":{"ws":"^8.18.3","jose":"^6.1.3","yaml":"^2.8.1","luxon":"^3.5.0","openai":"^4.79.0","bun-pty":"^0.4.5","express":"^5.1.0","node-pty":"1.2.0-beta.12","web-push":"^3.6.7","simple-git":"^3.36.0","compression":"^1.8.1","cron-parser":"^4.9.0","jsonc-parser":"^3.3.1","@octokit/rest":"^22.0.1","@clack/prompts":"^1.1.0","qrcode-terminal":"^0.12.0","@opencode-ai/sdk":"1.18.30","reflect-metadata":"^0.2.2","sherpa-onnx-node":"1.12.28","http-proxy-middleware":"^3.0.5","@simplewebauthn/server":"13.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.6","clsx":"^2.1.1","cmdk":"^1.1.1","cors":"^2.8.5","vite":"^7.1.2","react":"^19.1.1","eslint":"^9.33.0","sonner":"^2.0.7","vitest":"^4.1.4","globals":"^16.3.0","nodemon":"^3.1.7","zustand":"^5.0.8","cross-env":"^7.0.3","react-dom":"^19.1.1","supertest":"^7.2.2","@eslint/js":"^9.33.0","remark-gfm":"^4.0.1","typescript":"~5.9.0","@types/node":"^24.3.1","next-themes":"^0.4.6","tailwindcss":"^4.0.0","@types/react":"^19.1.10","autoprefixer":"^10.4.21","concurrently":"^9.2.1","@base-ui/react":"^1.4.0","react-markdown":"^10.1.0","tailwind-merge":"^3.3.1","tw-animate-css":"^1.3.8","workbox-window":"^7.4.0","vite-plugin-pwa":"^1.0.3","@remixicon/react":"^4.7.0","@types/react-dom":"^19.1.7","@types/supertest":"^7.2.0","typescript-eslint":"^8.39.1","@codemirror/lang-go":"^6.0.1","strip-json-comments":"^5.0.3","@codemirror/lang-cpp":"^6.0.3","@radix-ui/react-slot":"^1.2.3","@tailwindcss/postcss":"^4.0.0","@vitejs/plugin-react":"^5.0.0","@radix-ui/react-dialog":"^1.1.15","@radix-ui/react-select":"^2.2.6","@radix-ui/react-toggle":"^1.1.10","@radix-ui/react-tooltip":"^1.2.8","@simplewebauthn/browser":"13.3.0","class-variance-authority":"^0.7.1","@radix-ui/react-separator":"^1.1.7","eslint-plugin-react-hooks":"^5.2.0","@radix-ui/react-collapsible":"^1.1.12","@radix-ui/react-scroll-area":"^1.2.10","eslint-plugin-react-refresh":"^0.5.0","@radix-ui/react-dropdown-menu":"^2.1.16"},"_npmOperationalInternal":{"tmp":"tmp/web_1.23.0_1789049834461_0.4852547455290952","host":"s3://npm-registry-packages-npm-production"}},"1.23.1":{"name":"@aiworker/web","version":"1.23.1","_id":"@aiworker/web@1.23.1","maintainers":[{"name":"blockrepo","email":"wbluo@live.cn"}],"bin":{"aiworker":"bin/cli.js"},"dist":{"shasum":"17b613075c866073bd3efd3bfc2d6446a8109eca","tarball":"https://registry.npmjs.org/@aiworker/web/-/web-1.23.1.tgz","fileCount":1499,"integrity":"sha512-Qgp2DWkO/BWfcZv2Pk1tuLNUqgZwtRHWvpUGP+FJ16bFMcvAY/So1DyMa8roww9In1wAb+VHmodiYwa2HpRrjg==","signatures":[{"sig":"MEUCICG+O/qiQZKSLfYU4ea8FgIVisXi4JXSNflmC5t+cR0gAiEA+EwBilf7LTteMNrT4yBoCkGFQNZpuKbeItvoiakgj5o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45422311},"main":"./server/index.js","type":"module","_from":"file:aiworker-web-1.23.1.tgz","types":"./server/index.d.ts","private":false,"scripts":{"dev":"bun run build:watch","lint":"eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js","test":"vitest run","build":"vite build","start":"node bin/cli.js serve","dev:server":"AIWORKER_RELAY_HOST=${AIWORKER_RELAY_HOST:-off} bun server/index.js --port ${AIWORKER_PORT:-3001}","type-check":"tsc --noEmit","build:watch":"vite build --watch","dev:server:watch":"node ./scripts/dev-server-watch.mjs"},"_npmUser":{"name":"blockrepo","email":"wbluo@live.cn"},"_resolved":"/Users/block/Downloads/aiworker-web-1.23.1.tgz","_integrity":"sha512-Qgp2DWkO/BWfcZv2Pk1tuLNUqgZwtRHWvpUGP+FJ16bFMcvAY/So1DyMa8roww9In1wAb+VHmodiYwa2HpRrjg==","_npmVersion":"10.8.2","description":"[![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1Ni","directories":{},"_nodeVersion":"20.19.0","dependencies":{"ws":"^8.18.3","jose":"^6.1.3","yaml":"^2.8.1","luxon":"^3.5.0","openai":"^4.79.0","bun-pty":"^0.4.5","express":"^5.1.0","node-pty":"1.2.0-beta.12","web-push":"^3.6.7","simple-git":"^3.36.0","compression":"^1.8.1","cron-parser":"^4.9.0","jsonc-parser":"^3.3.1","@octokit/rest":"^22.0.1","@clack/prompts":"^1.1.0","qrcode-terminal":"^0.12.0","@opencode-ai/sdk":"1.18.30","reflect-metadata":"^0.2.2","sherpa-onnx-node":"1.12.28","http-proxy-middleware":"^3.0.5","@simplewebauthn/server":"13.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.6","clsx":"^2.1.1","cmdk":"^1.1.1","cors":"^2.8.5","vite":"^7.1.2","react":"^19.1.1","eslint":"^9.33.0","sonner":"^2.0.7","vitest":"^4.1.4","globals":"^16.3.0","nodemon":"^3.1.7","zustand":"^5.0.8","cross-env":"^7.0.3","react-dom":"^19.1.1","supertest":"^7.2.2","@eslint/js":"^9.33.0","remark-gfm":"^4.0.1","typescript":"~5.9.0","@types/node":"^24.3.1","next-themes":"^0.4.6","tailwindcss":"^4.0.0","@types/react":"^19.1.10","autoprefixer":"^10.4.21","concurrently":"^9.2.1","@base-ui/react":"^1.4.0","react-markdown":"^10.1.0","tailwind-merge":"^3.3.1","tw-animate-css":"^1.3.8","workbox-window":"^7.4.0","vite-plugin-pwa":"^1.0.3","@remixicon/react":"^4.7.0","@types/react-dom":"^19.1.7","@types/supertest":"^7.2.0","typescript-eslint":"^8.39.1","@codemirror/lang-go":"^6.0.1","strip-json-comments":"^5.0.3","@codemirror/lang-cpp":"^6.0.3","@radix-ui/react-slot":"^1.2.3","@tailwindcss/postcss":"^4.0.0","@vitejs/plugin-react":"^5.0.0","@radix-ui/react-dialog":"^1.1.15","@radix-ui/react-select":"^2.2.6","@radix-ui/react-toggle":"^1.1.10","@radix-ui/react-tooltip":"^1.2.8","@simplewebauthn/browser":"13.3.0","class-variance-authority":"^0.7.1","@radix-ui/react-separator":"^1.1.7","eslint-plugin-react-hooks":"^5.2.0","@radix-ui/react-collapsible":"^1.1.12","@radix-ui/react-scroll-area":"^1.2.10","eslint-plugin-react-refresh":"^0.5.0","@radix-ui/react-dropdown-menu":"^2.1.16"},"_npmOperationalInternal":{"tmp":"tmp/web_1.23.1_1789225896747_0.3832781480510299","host":"s3://npm-registry-packages-npm-production"}},"1.23.2":{"name":"@aiworker/web","version":"1.23.2","_id":"@aiworker/web@1.23.2","maintainers":[{"name":"blockrepo","email":"wbluo@live.cn"}],"bin":{"aiworker":"bin/cli.js"},"dist":{"shasum":"e95be0b272a6f72708e2cc74e63af612a513cdaa","tarball":"https://registry.npmjs.org/@aiworker/web/-/web-1.23.2.tgz","fileCount":1499,"integrity":"sha512-F26Z1FiUZ1IvAi3i4Ge5j3IAaDHmZfLtTWdW0at4Yz4SdbBiXWngedaVWXxtHVIjsDzBS5nO1Q/ERd/19qATmA==","signatures":[{"sig":"MEQCIB37ibdj4g4kiQa0h5DdsQ3HuKW8Ap0Ad5nKlHk3F6XQAiB9ys1qIplkah9jcDIk95w1r77AGNB2GXyRGud6hi4eMw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45422293},"main":"./server/index.js","type":"module","_from":"file:aiworker-web-1.23.2.tgz","types":"./server/index.d.ts","private":false,"scripts":{"dev":"bun run build:watch","lint":"eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js","test":"vitest run","build":"vite build","start":"node bin/cli.js serve","dev:server":"AIWORKER_RELAY_HOST=${AIWORKER_RELAY_HOST:-off} bun server/index.js --port ${AIWORKER_PORT:-3001}","type-check":"tsc --noEmit","build:watch":"vite build --watch","dev:server:watch":"node ./scripts/dev-server-watch.mjs"},"_npmUser":{"name":"blockrepo","email":"wbluo@live.cn"},"_resolved":"/Users/block/Downloads/aiworker-web-1.23.2.tgz","_integrity":"sha512-F26Z1FiUZ1IvAi3i4Ge5j3IAaDHmZfLtTWdW0at4Yz4SdbBiXWngedaVWXxtHVIjsDzBS5nO1Q/ERd/19qATmA==","_npmVersion":"10.8.2","description":"[![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1Ni","directories":{},"_nodeVersion":"20.19.0","dependencies":{"ws":"^8.18.3","jose":"^6.1.3","yaml":"^2.8.1","luxon":"^3.5.0","openai":"^4.79.0","bun-pty":"^0.4.5","express":"^5.1.0","node-pty":"1.2.0-beta.12","web-push":"^3.6.7","simple-git":"^3.36.0","compression":"^1.8.1","cron-parser":"^4.9.0","jsonc-parser":"^3.3.1","@octokit/rest":"^22.0.1","@clack/prompts":"^1.1.0","qrcode-terminal":"^0.12.0","@opencode-ai/sdk":"1.18.30","reflect-metadata":"^0.2.2","sherpa-onnx-node":"1.12.28","http-proxy-middleware":"^3.0.5","@simplewebauthn/server":"13.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.6","clsx":"^2.1.1","cmdk":"^1.1.1","cors":"^2.8.5","vite":"^7.1.2","react":"^19.1.1","eslint":"^9.33.0","sonner":"^2.0.7","vitest":"^4.1.4","globals":"^16.3.0","nodemon":"^3.1.7","zustand":"^5.0.8","cross-env":"^7.0.3","react-dom":"^19.1.1","supertest":"^7.2.2","@eslint/js":"^9.33.0","remark-gfm":"^4.0.1","typescript":"~5.9.0","@types/node":"^24.3.1","next-themes":"^0.4.6","tailwindcss":"^4.0.0","@types/react":"^19.1.10","autoprefixer":"^10.4.21","concurrently":"^9.2.1","@base-ui/react":"^1.4.0","react-markdown":"^10.1.0","tailwind-merge":"^3.3.1","tw-animate-css":"^1.3.8","workbox-window":"^7.4.0","vite-plugin-pwa":"^1.0.3","@remixicon/react":"^4.7.0","@types/react-dom":"^19.1.7","@types/supertest":"^7.2.0","typescript-eslint":"^8.39.1","@codemirror/lang-go":"^6.0.1","strip-json-comments":"^5.0.3","@codemirror/lang-cpp":"^6.0.3","@radix-ui/react-slot":"^1.2.3","@tailwindcss/postcss":"^4.0.0","@vitejs/plugin-react":"^5.0.0","@radix-ui/react-dialog":"^1.1.15","@radix-ui/react-select":"^2.2.6","@radix-ui/react-toggle":"^1.1.10","@radix-ui/react-tooltip":"^1.2.8","@simplewebauthn/browser":"13.3.0","class-variance-authority":"^0.7.1","@radix-ui/react-separator":"^1.1.7","eslint-plugin-react-hooks":"^5.2.0","@radix-ui/react-collapsible":"^1.1.12","@radix-ui/react-scroll-area":"^1.2.10","eslint-plugin-react-refresh":"^0.5.0","@radix-ui/react-dropdown-menu":"^2.1.16"},"_npmOperationalInternal":{"tmp":"tmp/web_1.23.2_1789365958523_0.0710955432267153","host":"s3://npm-registry-packages-npm-production"}},"1.23.3":{"_id":"@aiworker/web@1.23.3","bin":{"aiworker":"bin/cli.js"},"dist":{"shasum":"abe12702e0eafd10d7c5531b49ae1c4eee29394b","tarball":"https://registry.npmjs.org/@aiworker/web/-/web-1.23.3.tgz","fileCount":1499,"integrity":"sha512-YHdUDS1VpepFLGm8WfFmDN2e8Z3RXAOckPv1O+r2whP9poRgpHtxSNzwLjpCmghd3PzD/suQXFzP/EyRZ2Miiw==","signatures":[{"sig":"MEQCIGRzYuG7IZiOTz64wh54c3gphh9zp7SvwT1xo7hc+7y8AiAm9YQL5jNvgu8XTT8FvZ2MbO5ZKE6hluTXmscRG7ns/w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIH0VbrRDmRJA74ugsRD+h3o4G/+ENDLI3/ifSB6NWkNZAiAOY+VuECPWI9U2fs6C1Cwzph0VIhtTj1esnlUrZll/mA=="}],"unpackedSize":45453634},"main":"./server/index.js","name":"@aiworker/web","type":"module","_from":"file:aiworker-web-1.23.03.tgz","types":"./server/index.d.ts","private":false,"scripts":{"dev":"bun run build:watch","lint":"eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js","test":"vitest run","build":"vite build","start":"node bin/cli.js serve","dev:server":"AIWORKER_RELAY_HOST=${AIWORKER_RELAY_HOST:-off} bun server/index.js --port ${AIWORKER_PORT:-3001}","type-check":"tsc --noEmit","build:watch":"vite build --watch","dev:server:watch":"node ./scripts/dev-server-watch.mjs"},"version":"1.23.3","_npmUser":{"name":"blockrepo","email":"wbluo@live.cn"},"_resolved":"/Users/block/Downloads/aiworker-web-1.23.03.tgz","_integrity":"sha512-YHdUDS1VpepFLGm8WfFmDN2e8Z3RXAOckPv1O+r2whP9poRgpHtxSNzwLjpCmghd3PzD/suQXFzP/EyRZ2Miiw==","_npmVersion":"10.8.2","description":"[![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1Ni","directories":{},"maintainers":[{"name":"blockrepo","email":"wbluo@live.cn"}],"_nodeVersion":"20.19.0","dependencies":{"ws":"^8.18.3","jose":"^6.1.3","yaml":"^2.8.1","luxon":"^3.5.0","openai":"^4.79.0","bun-pty":"^0.4.5","express":"^5.1.0","node-pty":"1.2.0-beta.12","web-push":"^3.6.7","simple-git":"^3.36.0","compression":"^1.8.1","cron-parser":"^4.9.0","jsonc-parser":"^3.3.1","@octokit/rest":"^22.0.1","@clack/prompts":"^1.1.0","qrcode-terminal":"^0.12.0","@opencode-ai/sdk":"1.18.31","reflect-metadata":"^0.2.2","sherpa-onnx-node":"1.12.28","http-proxy-middleware":"^3.0.5","@simplewebauthn/server":"13.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.6","clsx":"^2.1.1","cmdk":"^1.1.1","cors":"^2.8.5","vite":"^7.1.2","react":"^19.1.1","eslint":"^9.33.0","sonner":"^2.0.7","vitest":"^4.1.4","globals":"^16.3.0","nodemon":"^3.1.7","zustand":"^5.0.8","cross-env":"^7.0.3","react-dom":"^19.1.1","supertest":"^7.2.2","@eslint/js":"^9.33.0","remark-gfm":"^4.0.1","typescript":"~5.9.0","@types/node":"^24.3.1","next-themes":"^0.4.6","tailwindcss":"^4.0.0","@types/react":"^19.1.10","autoprefixer":"^10.4.21","concurrently":"^9.2.1","@base-ui/react":"^1.4.0","react-markdown":"^10.1.0","tailwind-merge":"^3.3.1","tw-animate-css":"^1.3.8","workbox-window":"^7.4.0","vite-plugin-pwa":"^1.0.3","@remixicon/react":"^4.7.0","@types/react-dom":"^19.1.7","@types/supertest":"^7.2.0","typescript-eslint":"^8.39.1","@codemirror/lang-go":"^6.0.1","strip-json-comments":"^5.0.3","@codemirror/lang-cpp":"^6.0.3","@radix-ui/react-slot":"^1.2.3","@tailwindcss/postcss":"^4.0.0","@vitejs/plugin-react":"^5.0.0","@radix-ui/react-dialog":"^1.1.15","@radix-ui/react-select":"^2.2.6","@radix-ui/react-toggle":"^1.1.10","@radix-ui/react-tooltip":"^1.2.8","@simplewebauthn/browser":"13.3.0","class-variance-authority":"^0.7.1","@radix-ui/react-separator":"^1.1.7","eslint-plugin-react-hooks":"^5.2.0","@radix-ui/react-collapsible":"^1.1.12","@radix-ui/react-scroll-area":"^1.2.10","eslint-plugin-react-refresh":"^0.5.0","@radix-ui/react-dropdown-menu":"^2.1.16"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/web_1.23.3_1789448566618_0.38960372623437856"}}},"time":{"created":"2026-09-02T14:25:15.632Z","modified":"2026-09-15T05:02:47.072Z","1.22.0":"2026-09-02T14:25:16.194Z","1.22.2":"2026-09-07T01:48:12.810Z","1.23.0":"2026-09-10T14:17:14.766Z","1.23.1":"2026-09-12T15:11:37.038Z","1.23.2":"2026-09-14T06:05:58.796Z","1.23.3":"2026-09-15T05:02:46.880Z"},"description":"[![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1Ni","maintainers":[{"name":"blockrepo","email":"wbluo@live.cn"}],"readme":"# <picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://roweb.cn/roweb/openchamber/raw/HEAD/docs/references/badges/openchamber-logo-dark.svg\"><img src=\"https://roweb.cn/roweb/openchamber/raw/HEAD/docs/references/badges/openchamber-logo-light.svg\" width=\"32\" height=\"32\" align=\"absmiddle\" /></picture> @aiworker/web\n\n[![GitHub stars](https://img.shields.io/github/stars/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0yMjkuMDYsMTA4Ljc5bC00OC43LDQyLDE0Ljg4LDYyLjc5YTguNCw4LjQsMCwwLDEtMTIuNTIsOS4xN0wxMjgsMTg5LjA5LDczLjI4LDIyMi43NGE4LjQsOC40LDAsMCwxLTEyLjUyLTkuMTdsMTQuODgtNjIuNzktNDguNy00MkE4LjQ2LDguNDYsMCwwLDEsMzEuNzMsOTRMOTUuNjQsODguOGwyNC42Mi01OS42YTguMzYsOC4zNiwwLDAsMSwxNS40OCwwbDI0LjYyLDU5LjZMMjI0LjI3LDk0QTguNDYsOC40NiwwLDAsMSwyMjkuMDYsMTA4Ljc5WiIgb3BhY2l0eT0iMC4yIj48L3BhdGg%2BPHBhdGggZD0iTTIzOS4xOCw5Ny4yNkExNi4zOCwxNi4zOCwwLDAsMCwyMjQuOTIsODZsLTU5LTQuNzZMMTQzLjE0LDI2LjE1YTE2LjM2LDE2LjM2LDAsMCwwLTMwLjI3LDBMOTAuMTEsODEuMjMsMzEuMDgsODZhMTYuNDYsMTYuNDYsMCwwLDAtOS4zNywyOC44Nmw0NSwzOC44M0w1MywyMTEuNzVhMTYuMzgsMTYuMzgsMCwwLDAsMjQuNSwxNy44MkwxMjgsMTk4LjQ5bDUwLjUzLDMxLjA4QTE2LjQsMTYuNCwwLDAsMCwyMDMsMjExLjc1bC0xMy43Ni01OC4wNyw0NS0zOC44M0ExNi40MywxNi40MywwLDAsMCwyMzkuMTgsOTcuMjZabS0xNS4zNCw1LjQ3LTQ4LjcsNDJhOCw4LDAsMCwwLTIuNTYsNy45MWwxNC44OCw2Mi44YS4zNy4zNywwLDAsMS0uMTcuNDhjLS4xOC4xNC0uMjMuMTEtLjM4LDBsLTU0LjcyLTMzLjY1YTgsOCwwLDAsMC04LjM4LDBMNjkuMDksMjE1Ljk0Yy0uMTUuMDktLjE5LjEyLS4zOCwwYS4zNy4zNywwLDAsMS0uMTctLjQ4bDE0Ljg4LTYyLjhhOCw4LDAsMCwwLTIuNTYtNy45MWwtNDguNy00MmMtLjEyLS4xLS4yMy0uMTktLjEzLS41cy4xOC0uMjcuMzMtLjI5bDYzLjkyLTUuMTZBOCw4LDAsMCwwLDEwMyw5MS44NmwyNC42Mi01OS42MWMuMDgtLjE3LjExLS4yNS4zNS0uMjVzLjI3LjA4LjM1LjI1TDE1Myw5MS44NmE4LDgsMCwwLDAsNi43NSw0LjkybDYzLjkyLDUuMTZjLjE1LDAsLjI0LDAsLjMzLjI5UzIyNCwxMDIuNjMsMjIzLjg0LDEwMi43M1oiPjwvcGF0aD48L3N2Zz4%3D&logoColor=FFFCF0&labelColor=100F0F&color=66800B)](https://roweb.cn/roweb/openchamber/stargazers)\n[![GitHub release](https://img.shields.io/github/v/release/openchamber/openchamber?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0xMjgsMTI5LjA5VjIzMmE4LDgsMCwwLDEtMy44NC0xbC04OC00OC4xOGE4LDgsMCwwLDEtNC4xNi03VjgwLjE4YTgsOCwwLDAsMSwuNy0zLjI1WiIgb3BhY2l0eT0iMC4yIj48L3BhdGg%2BPHBhdGggZD0iTTIyMy42OCw2Ni4xNSwxMzUuNjgsMThhMTUuODgsMTUuODgsMCwwLDAtMTUuMzYsMGwtODgsNDguMTdhMTYsMTYsMCwwLDAtOC4zMiwxNHY5NS42NGExNiwxNiwwLDAsMCw4LjMyLDE0bDg4LDQ4LjE3YTE1Ljg4LDE1Ljg4LDAsMCwwLDE1LjM2LDBsODgtNDguMTdhMTYsMTYsMCwwLDAsOC4zMi0xNFY4MC4xOEExNiwxNiwwLDAsMCwyMjMuNjgsNjYuMTVaTTEyOCwzMmw4MC4zNCw0NC0yOS43NywxNi4zLTgwLjM1LTQ0Wk0xMjgsMTIwLDQ3LjY2LDc2bDMzLjktMTguNTYsODAuMzQsNDRaTTQwLDkwbDgwLDQzLjc4djg1Ljc5TDQwLDE3NS44MlptMTc2LDg1Ljc4aDBsLTgwLDQzLjc5VjEzMy44MmwzMi0xNy41MVYxNTJhOCw4LDAsMCwwLDE2LDBWMTA3LjU1TDIxNiw5MHY4NS43N1oiPjwvcGF0aD48L3N2Zz4%3D&logoColor=FFFCF0&labelColor=100F0F&color=205EA6)](https://roweb.cn/roweb/openchamber/releases/latest)\n[![Discord](https://img.shields.io/badge/Discord-join.svg?style=flat&labelColor=100F0F&color=8B7EC8&logo=discord&logoColor=FFFCF0)](https://discord.gg/ZYRSdnwwKA)\n\nRun [OpenCode](https://opencode.ai) in your browser. Install the CLI, open `localhost:3000`, done. Works on desktop browsers, tablets, and phones as a PWA.\n\nFull project overview, screenshots, and all features: [roweb.cn/roweb/openchamber](https://roweb.cn/roweb/openchamber)\n\n## Install\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/openchamber/openchamber/main/scripts/install.sh | bash\n```\n\nOr install manually: `bun add -g @aiworker/web` (or npm, pnpm, yarn).\n\n> **Prerequisites:** [OpenCode CLI](https://opencode.ai) installed, Node.js 22+.\n\n## Usage\n\n```bash\naiworker                          # Start on port 3000\naiworker --port 8080              # Custom port\naiworker --lan --port 3000        # Listen on LAN (0.0.0.0)\naiworker --ui-password secret     # Password-protect UI\naiworker startup enable           # Start at login as a native service\nAIWORKER_UI_PASSWORD=secret aiworker startup enable # Save service password env\naiworker startup status           # Show startup service status\naiworker startup disable          # Remove startup service\naiworker tunnel help              # Tunnel lifecycle commands\naiworker tunnel providers         # Show provider capabilities\naiworker tunnel profile add --provider cloudflare --mode managed-remote --name prod-main --hostname app.example.com --token <token>\naiworker tunnel start --profile prod-main\naiworker tunnel start --provider cloudflare --mode quick --qr\naiworker tunnel start --provider cloudflare --mode managed-local --config ~/.cloudflared/config.yml\naiworker tunnel status --all      # Show tunnel state across instances\naiworker tunnel stop --port 3000  # Stop tunnel only (server stays running)\naiworker connect-url --port 3000  # Add this server to AiWorker Desktop\naiworker connect-url --server http://host:3000 --qr\naiworker connect-url --port 3000 --qr\naiworker logs                     # Follow latest instance logs\nOPENCODE_PORT=4096 OPENCODE_SKIP_START=true aiworker                    # Connect to external OpenCode server\nOPENCODE_HOST=https://myhost:4096 OPENCODE_SKIP_START=true aiworker  # Connect via custom host/HTTPS\naiworker stop                     # Stop server\naiworker update                   # Update to latest version\n```\n\n`startup enable` snapshots your current environment into the native service so startup behaves like you launched `aiworker` from the same shell. This preserves provider tokens, PATH, SSH agent settings, and other CLI auth/config env vars. Use `--no-env-snapshot` for a minimal service env.\n\nWhen AiWorker launches the local OpenCode server, it also registers a native\n`aiworker` agent tool for project, session, and scheduled-task orchestration.\nThe tool is not injected when connecting to an external OpenCode server.\nBehavior settings can optionally inject a managed system-prompt optimizer on\nthe next OpenCode restart. It is disabled by default and is not available for\nexternal OpenCode servers.\n\n### Tunnel behavior notes\n\n- One active tunnel per running AiWorker instance (port).\n- Starting a different tunnel mode/provider on the same instance replaces the active tunnel.\n- Replacing or stopping a tunnel revokes existing connect links and invalidates remote tunnel sessions.\n- Connect links are one-time tokens; generating a new link revokes the previous unused link.\n\n### Connect other AiWorker apps\n\nUse `connect-url` when a web/API server should be added to AiWorker Desktop or another AiWorker app. If no server is running on the selected port, AiWorker starts one first.\n\n```bash\naiworker connect-url --port 3000\naiworker connect-url --port 3000 --qr\naiworker connect-url --port 3000 --json\naiworker connect-url --port 3000 --name \"Workstation\"\naiworker connect-url --port 3000 --lan --server http://workstation.local:3000 --qr\n```\n\n### Headless/API-only server for Desktop\n\nUse this on a remote machine when you want AiWorker running as a web/API server, then connect to it from AiWorker Desktop on another machine:\n\n```bash\naiworker connect-url --port 3000 --api-only --lan --server http://workstation.local:3000 --qr --ui-password your-password\n```\n\n`--api-only` starts API routes without serving browser UI assets. `--lan` binds the server so other machines can reach it. `--server` is the address saved into the Desktop connection link. `--ui-password` protects browser access if UI routes are enabled elsewhere; the generated client token is what Desktop uses for API access.\n\nThis creates a remote client token and prints an `aiworker://connect?...` link. The link contains the server URL, token, label, and payload version. In AiWorker Desktop, paste it in **Settings -> Remote Instances -> Direct Instances -> Import Link** to add that server as an Instance.\n\nIf the server was started with `--lan` or `--host 0.0.0.0`, `connect-url` automatically advertises a detected LAN IP instead of `127.0.0.1`. Use `--server <url>` when you want to advertise a specific DNS name, Tailscale address, reverse proxy URL, or HTTPS endpoint.\n\nIf you are exposing the server beyond localhost, start it with a password:\n\n```bash\naiworker serve --lan --port 3000 --ui-password your-password\n```\n\nGenerating a client token does not automatically password-protect the hosted browser UI. `--ui-password` protects browser access; the client token lets another AiWorker app connect to this server.\n\n<details>\n<summary>Connect to external OpenCode server</summary>\n\n```bash\nOPENCODE_PORT=4096 OPENCODE_SKIP_START=true aiworker\nOPENCODE_HOST=https://myhost:4096 OPENCODE_SKIP_START=true aiworker\n```\n\n| Variable | Description |\n|----------|-------------|\n| `OPENCODE_HOST` | Full base URL of external server (overrides `OPENCODE_PORT`) |\n| `OPENCODE_PORT` | Port of external server |\n| `OPENCODE_SKIP_START` | Skip starting embedded OpenCode server |\n| `AIWORKER_OPENCODE_HOSTNAME` | Bind hostname for managed OpenCode server (default: `127.0.0.1`, use `0.0.0.0` for LAN/remote access — trusted networks only). Invalid values are rejected with an error and fall back to loopback |\n| `AIWORKER_HOST` | Bind hostname for the AiWorker web server (default: `127.0.0.1`; use `0.0.0.0` for LAN/remote access — trusted networks only) |\n| `AIWORKER_VERBOSE_REQUEST_LOGS` | Set to `true` to log every HTTP request; disabled by default to keep user logs small |\n| `AIWORKER_SKIP_API_COMPRESSION` | Set to `true` to disable gzip compression for `/api/*` responses |\n| `AIWORKER_COMPRESS_API` | Set to `true` to force `/api/*` compression, or `false` to disable it. Desktop runtime disables API compression by default to reduce local sidecar CPU use |\n| `AIWORKER_FS_UPLOAD_MAX_BYTES` | Maximum file upload size in bytes (default: 100 MiB) |\n| `AIWORKER_TERMINAL_SHELL` | Preferred terminal shell executable used by the `Auto` setting before platform defaults |\n\n</details>\n\n<details>\n<summary>Bind managed OpenCode to LAN / Tailscale</summary>\n\n```bash\nAIWORKER_OPENCODE_HOSTNAME=0.0.0.0 aiworker --port 3000\n```\n\n**Security note:** binding to `0.0.0.0` exposes the server on all network interfaces — use only on trusted networks and protect with firewall rules or `--ui-password`.\n\n</details>\n\n**Optional env vars:**\n```yaml\nenvironment:\n  UI_PASSWORD: your_secure_password\n  AIWORKER_TUNNEL_MODE: quick # quick | managed-remote | managed-local\n  AIWORKER_TUNNEL_PROVIDER: cloudflare\n```\n\nFor `managed-remote` mode, also set:\n\n```yaml\nenvironment:\n  AIWORKER_TUNNEL_MODE: managed-remote\n  AIWORKER_TUNNEL_HOSTNAME: app.example.com\n  AIWORKER_TUNNEL_TOKEN: <token>\n```\n\nFor `managed-local` mode, you can set:\n\n```yaml\nenvironment:\n  AIWORKER_TUNNEL_MODE: managed-local\n  AIWORKER_TUNNEL_CONFIG: /home/openchamber/.cloudflared/config.yml\n```\n\nManaged-local path note: `AIWORKER_TUNNEL_CONFIG` must use a container path under `/home/openchamber/...`. If the config file references `credentials-file`, ensure that JSON path is also mounted and reachable inside the container.\n\n**Data directory:** mount `data/` for persistent storage. Ensure permissions:\n```bash\nmkdir -p data/openchamber data/opencode/share data/opencode/config data/ssh\nchown -R 1000:1000 data/\n```\n\n</details>\n\n<details>\n<summary>Background & daemon mode</summary>\n\n```bash\naiworker             # Runs in background by default\naiworker stop        # Stop background server\n```\n\n</details>\n\n<details>\n<summary>systemd service (VPN / LAN access)</summary>\n\nUse `--foreground` to keep the CLI process alive so systemd (or any other process manager) can track and restart it. Combine with `OPENCODE_HOST` to connect to an OpenCode instance running as a separate service.\n\n**`~/.config/systemd/user/opencode.service`**\n```ini\n[Unit]\nDescription=OpenCode Server\n\n[Service]\nType=simple\nExecStart=opencode serve --port 4095\nEnvironment=\"PATH=/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/YOU/.local/bin:/home/YOU/.npm-global/bin:/usr/local/bin:/usr/bin:/bin\"\nEnvironment=SSH_AUTH_SOCK=%t/ssh-agent.socket\nRestart=on-failure\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n```\n\n> **Why set `PATH` and `SSH_AUTH_SOCK`?**\n> systemd user services start with a minimal environment — no shell profile is sourced.\n> Without an explicit `PATH`, OpenCode won't find tools installed via Homebrew, npm, or `~/.local/bin`.\n> Without `SSH_AUTH_SOCK`, git operations over SSH (push, pull, clone) will fail.\n> `%t` expands to `$XDG_RUNTIME_DIR` (e.g. `/run/user/1000`), where most SSH agents write their socket.\n\n**`~/.config/systemd/user/openchamber.service`**\n```ini\n[Unit]\nDescription=AiWorker Web Server\nAfter=opencode.service\n\n[Service]\nType=simple\nExecStart=aiworker serve --port 3000 --host 0.0.0.0 --ui-password your-password --foreground\nEnvironment=\"OPENCODE_HOST=http://localhost:4095\"\nEnvironment=\"OPENCODE_SKIP_START=true\"\nRestart=on-failure\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n```\n\n```bash\nsystemctl --user daemon-reload\nsystemctl --user enable --now opencode aiworker\n```\n\n`--host 0.0.0.0` is required to listen on all interfaces (the default is `127.0.0.1`). Use `--host <ip>` or `AIWORKER_HOST=<ip>` to bind to a specific interface instead.\n\n</details>\n\n## What makes the web version special\n\n- **Remote access** - Cloudflare tunnel with QR onboarding. Scan from your phone, start coding.\n- **Mobile-first PWA** - optimized chat controls, keyboard-safe layouts, drag-to-reorder projects\n- **Background notifications** - know when your agent finishes, even from another tab\n- **Self-update** - update and restart from the UI, server settings stay intact\n- **Cross-tab tracking** - session activity stays in sync across browser tabs\n\n- Cloudflare tunnel access with quick, managed-remote, and managed-local modes\n- One-scan onboarding with tunnel QR + password URL helpers\n- Mobile-first experience: optimized chat controls, keyboard-safe layouts, and attachment-friendly UI\n- Background notifications plus reliable cross-tab session activity tracking\n- Built-in self-update + restart flow that keeps your server settings intact\n\n## License\n\nMIT\n","readmeFilename":"README.md"}