{"_id":"8remo","_rev":"9-63047496ed73a8fc3a6e64f95ead1ad3","name":"8remo","dist-tags":{"latest":"1.1.5"},"versions":{"1.1.0":{"name":"8remo","version":"1.1.0","_id":"8remo@1.1.0","maintainers":[{"name":"nhathao95","email":"haotruongnhat@gmail.com"}],"bin":{"8remo":"app/cli/index.js"},"dist":{"shasum":"20f56a41953cdef28d8703729212ea8bb74947e6","tarball":"https://registry.npmjs.org/8remo/-/8remo-1.1.0.tgz","fileCount":58,"integrity":"sha512-2MCSWFVKYX6ETET/VaspsXGfbiIsJxWPWn7+rHabDSjOaxx2IyLk3ZAjQSV7Cyz5WkyY62yZO1kPbQ6jFMHTMg==","signatures":[{"sig":"MEQCIFyyxknpSGdci9qottLrVo48Z3y3Zj/B5ZlJ9/39p5ZCAiAtR1sNXoL8GMq8grYATswT2x9JwzGyvs9TxPVMBYwh2g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1879739},"type":"module","_from":"file:8remo-1.1.0.tgz","engines":{"node":">=20"},"scripts":{"dev":"tsx src/cli/index.ts","test":"tsx --test --test-concurrency=1 src/**/*.test.ts","build":"npm run build:server && npm run build:web && npm run build:app-web","start":"node app/cli/index.js","prepack":"npm run build","build:web":"next build web","typecheck":"tsc -p tsconfig.node.json && tsc -p web/tsconfig.json --noEmit","build:server":"npm run clean:server && tsc -p tsconfig.node.json","clean:server":"node -e \"require('node:fs').rmSync('app', { recursive: true, force: true })\"","deploy:relay":"npx wrangler deploy","build:app-web":"node scripts/copy-web-out-to-app.mjs"},"_npmUser":{"name":"nhathao95","email":"haotruongnhat@gmail.com"},"_resolved":"E:\\Work\\Projects\\8remo\\8remo-1.1.0.tgz","_integrity":"sha512-2MCSWFVKYX6ETET/VaspsXGfbiIsJxWPWn7+rHabDSjOaxx2IyLk3ZAjQSV7Cyz5WkyY62yZO1kPbQ6jFMHTMg==","_npmVersion":"11.12.1","description":"Remote AgentCLI and web client.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mime":"^4.1.0","next":"^16.2.4","open":"^10.2.0","react":"^19.2.3","qrcode":"^1.5.4","express":"^5.2.1","systray":"^1.0.5","node-pty":"^1.1.0","react-dom":"^19.2.3","socket.io":"^4.8.3","@xterm/xterm":"^6.0.0","lucide-react":"^0.561.0","@types/qrcode":"^1.5.6","react-markdown":"^10.1.0","qrcode-terminal":"^0.12.0","@xterm/addon-fit":"^0.11.0","socket.io-client":"^4.8.3","react-simple-keyboard":"^3.8.198"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^5.9.3","@types/node":"^25.0.3","@types/react":"^19.2.7","@types/express":"^5.0.6","@types/react-dom":"^19.2.3","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/8remo_1.1.0_1777956007203_0.14615196922107754","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"8remo","version":"1.1.1","_id":"8remo@1.1.1","maintainers":[{"name":"nhathao95","email":"haotruongnhat@gmail.com"}],"bin":{"8remo":"app/cli/index.js"},"dist":{"shasum":"f559fb1e535886db5bc0340d49ff936e8a5afd91","tarball":"https://registry.npmjs.org/8remo/-/8remo-1.1.1.tgz","fileCount":58,"integrity":"sha512-ajCvz4dSEnE7pKJiSf4dlIpK3ulle9GveI/SUiFk8n51mF1fOIK4YbrHHOlg+u4hW7wmFMMN90K0FVn2Nfo4lg==","signatures":[{"sig":"MEQCIHP/1Jg/KKKy21vHhmLHNj+c9VBCzejGKxle2pxOwdkiAiAO52IB/DmZse7ojh+e+QZemJPY42GO2B1u22X8XrwFog==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1885113},"type":"module","_from":"file:8remo-1.1.1.tgz","engines":{"node":">=20"},"scripts":{"dev":"tsx src/cli/index.ts","test":"tsx --test --test-concurrency=1 src/**/*.test.ts","build":"npm run build:server && npm run build:web && npm run build:app-web","start":"node app/cli/index.js","prepack":"npm run build","build:web":"next build web","typecheck":"tsc -p tsconfig.node.json && tsc -p web/tsconfig.json --noEmit","build:server":"npm run clean:server && tsc -p tsconfig.node.json","clean:server":"node -e \"require('node:fs').rmSync('app', { recursive: true, force: true })\"","deploy:relay":"npx wrangler deploy","build:app-web":"node scripts/copy-web-out-to-app.mjs"},"_npmUser":{"name":"nhathao95","email":"haotruongnhat@gmail.com"},"_resolved":"E:\\Work\\Projects\\8remo\\8remo-1.1.1.tgz","_integrity":"sha512-ajCvz4dSEnE7pKJiSf4dlIpK3ulle9GveI/SUiFk8n51mF1fOIK4YbrHHOlg+u4hW7wmFMMN90K0FVn2Nfo4lg==","_npmVersion":"11.12.1","description":"Remote AgentCLI and web client.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mime":"^4.1.0","next":"^16.2.4","open":"^10.2.0","react":"^19.2.3","qrcode":"^1.5.4","express":"^5.2.1","systray":"^1.0.5","node-pty":"^1.1.0","react-dom":"^19.2.3","socket.io":"^4.8.3","@xterm/xterm":"^6.0.0","lucide-react":"^0.561.0","@types/qrcode":"^1.5.6","react-markdown":"^10.1.0","qrcode-terminal":"^0.12.0","@xterm/addon-fit":"^0.11.0","socket.io-client":"^4.8.3","react-simple-keyboard":"^3.8.198"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^5.9.3","@types/node":"^25.0.3","@types/react":"^19.2.7","@types/express":"^5.0.6","@types/react-dom":"^19.2.3","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/8remo_1.1.1_1777962803249_0.8364755236430088","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"8remo","version":"1.1.2","_id":"8remo@1.1.2","maintainers":[{"name":"nhathao95","email":"haotruongnhat@gmail.com"}],"bin":{"8remo":"app/cli/index.js"},"dist":{"shasum":"f715cb83fea6ea14564aafad1781b7f235bb705f","tarball":"https://registry.npmjs.org/8remo/-/8remo-1.1.2.tgz","fileCount":58,"integrity":"sha512-nYv4luhWtM7+Mm3G/B+rtqb5PgGpyascQnbJ+t6RHFzvrUYUGFwnyBCQ5x0Y9zQem4cLY9hC6AkRqAL0hp/T1A==","signatures":[{"sig":"MEYCIQCx2I+wWQLitEGX+yrp8TbkydoUUAn0rIQDfS0cxAHozAIhAKErM+DtHPcgKoNSGksn9OzFPYJmvewkfRn9p3dbP+OV","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1885371},"type":"module","_from":"file:8remo-1.1.2.tgz","engines":{"node":">=20"},"scripts":{"dev":"tsx src/cli/index.ts","test":"tsx --test --test-concurrency=1 src/**/*.test.ts","build":"npm run build:server && npm run build:web && npm run build:app-web","start":"node app/cli/index.js","prepack":"npm run build","build:web":"next build web","typecheck":"tsc -p tsconfig.node.json && tsc -p web/tsconfig.json --noEmit","build:server":"npm run clean:server && tsc -p tsconfig.node.json","clean:server":"node -e \"require('node:fs').rmSync('app', { recursive: true, force: true })\"","deploy:relay":"npx wrangler deploy","build:app-web":"node scripts/copy-web-out-to-app.mjs"},"_npmUser":{"name":"nhathao95","email":"haotruongnhat@gmail.com"},"_resolved":"E:\\Work\\Projects\\8remo\\8remo-1.1.2.tgz","_integrity":"sha512-nYv4luhWtM7+Mm3G/B+rtqb5PgGpyascQnbJ+t6RHFzvrUYUGFwnyBCQ5x0Y9zQem4cLY9hC6AkRqAL0hp/T1A==","_npmVersion":"11.12.1","description":"Remote AgentCLI and web client.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mime":"^4.1.0","next":"^16.2.4","open":"^10.2.0","react":"^19.2.3","qrcode":"^1.5.4","express":"^5.2.1","systray":"^1.0.5","node-pty":"^1.1.0","react-dom":"^19.2.3","socket.io":"^4.8.3","@xterm/xterm":"^6.0.0","lucide-react":"^0.561.0","@types/qrcode":"^1.5.6","react-markdown":"^10.1.0","qrcode-terminal":"^0.12.0","@xterm/addon-fit":"^0.11.0","socket.io-client":"^4.8.3","react-simple-keyboard":"^3.8.198"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^5.9.3","@types/node":"^25.0.3","@types/react":"^19.2.7","@types/express":"^5.0.6","@types/react-dom":"^19.2.3","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/8remo_1.1.2_1777963479082_0.055445707242346653","host":"s3://npm-registry-packages-npm-production"}},"1.1.3":{"name":"8remo","version":"1.1.3","_id":"8remo@1.1.3","maintainers":[{"name":"nhathao95","email":"haotruongnhat@gmail.com"}],"bin":{"8remo":"app/cli/index.js"},"dist":{"shasum":"3fdffd7871c10412b72c8684fab294bc921b41a1","tarball":"https://registry.npmjs.org/8remo/-/8remo-1.1.3.tgz","fileCount":58,"integrity":"sha512-J7oIqD5cN98JoNEi0Cbo8LG5YjS26s3BXBY50JSPVHIJCWIzKl4SfbOQnFyr0snEN8niG/LQowqV4DLpGbtrrw==","signatures":[{"sig":"MEYCIQDe/rQJxyQGNF9jhz8cBcg1hb9LZ2x27Az/fX65yUoiGgIhAPoBap/YmqXPgd02dd8HQRQfqUsOyriJiamJ01RNrxhE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1884565},"type":"module","_from":"file:8remo-1.1.3.tgz","engines":{"node":">=20"},"scripts":{"dev":"tsx src/cli/index.ts","test":"tsx --test --test-concurrency=1 src/**/*.test.ts","build":"npm run build:server && npm run build:web && npm run build:app-web","start":"node app/cli/index.js","prepack":"npm run build","build:web":"next build web","typecheck":"tsc -p tsconfig.node.json && tsc -p web/tsconfig.json --noEmit","build:server":"npm run clean:server && tsc -p tsconfig.node.json","clean:server":"node -e \"require('node:fs').rmSync('app', { recursive: true, force: true })\"","deploy:relay":"npx wrangler deploy","build:app-web":"node scripts/copy-web-out-to-app.mjs"},"_npmUser":{"name":"nhathao95","email":"haotruongnhat@gmail.com"},"_resolved":"E:\\Work\\Projects\\8remo\\8remo-1.1.3.tgz","_integrity":"sha512-J7oIqD5cN98JoNEi0Cbo8LG5YjS26s3BXBY50JSPVHIJCWIzKl4SfbOQnFyr0snEN8niG/LQowqV4DLpGbtrrw==","_npmVersion":"11.12.1","description":"Remote AgentCLI and web client.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mime":"^4.1.0","next":"^16.2.4","open":"^10.2.0","react":"^19.2.3","qrcode":"^1.5.4","express":"^5.2.1","systray":"^1.0.5","node-pty":"^1.1.0","react-dom":"^19.2.3","socket.io":"^4.8.3","@xterm/xterm":"^6.0.0","lucide-react":"^0.561.0","@types/qrcode":"^1.5.6","react-markdown":"^10.1.0","qrcode-terminal":"^0.12.0","@xterm/addon-fit":"^0.11.0","socket.io-client":"^4.8.3","react-simple-keyboard":"^3.8.198"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^5.9.3","@types/node":"^25.0.3","@types/react":"^19.2.7","@types/express":"^5.0.6","@types/react-dom":"^19.2.3","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/8remo_1.1.3_1777964649605_0.8777232035689844","host":"s3://npm-registry-packages-npm-production"}},"1.1.4":{"name":"8remo","version":"1.1.4","_id":"8remo@1.1.4","maintainers":[{"name":"nhathao95","email":"haotruongnhat@gmail.com"}],"bin":{"8remo":"app/cli/index.js"},"dist":{"shasum":"3b41424712b8ad14672c854bb0f790cb36ce4402","tarball":"https://registry.npmjs.org/8remo/-/8remo-1.1.4.tgz","fileCount":58,"integrity":"sha512-M14x9RR4nxIt9aHHdSoZZJ+QV2gvA3+K/4jPLZZDrORFZaMrvqgNI40dYWe1JCioCKKPx/iW1fVeKDb/7bxCDQ==","signatures":[{"sig":"MEUCIGW025469N+YceNlrq5ers4YElg2V2nWSm6Tk0dKqq8OAiEAr+YIrI8N+661QN1vZzGVAlZqz2sGlN5cRoUqDFq1KSY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1890001},"type":"module","_from":"file:.packs/8remo-1.1.4.tgz","engines":{"node":">=20"},"scripts":{"dev":"tsx src/cli/index.ts","test":"tsx --test --test-concurrency=1 src/**/*.test.ts","build":"npm run build:server && npm run build:web && npm run build:app-web","start":"node app/cli/index.js","prepack":"npm run build","build:web":"next build web","typecheck":"tsc -p tsconfig.node.json && tsc -p web/tsconfig.json --noEmit","pack:local":"node -e \"require('node:fs').mkdirSync('.packs', { recursive: true })\" && npm pack --pack-destination .packs","build:server":"npm run clean:server && tsc -p tsconfig.node.json","clean:server":"node -e \"require('node:fs').rmSync('app', { recursive: true, force: true })\"","deploy:relay":"npx wrangler deploy","build:app-web":"node scripts/copy-web-out-to-app.mjs"},"_npmUser":{"name":"nhathao95","email":"haotruongnhat@gmail.com"},"_resolved":"E:\\Work\\Projects\\8remo\\.packs\\8remo-1.1.4.tgz","_integrity":"sha512-M14x9RR4nxIt9aHHdSoZZJ+QV2gvA3+K/4jPLZZDrORFZaMrvqgNI40dYWe1JCioCKKPx/iW1fVeKDb/7bxCDQ==","_npmVersion":"11.12.1","description":"Remote AgentCLI and web client.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mime":"^4.1.0","next":"^16.2.4","open":"^10.2.0","react":"^19.2.3","qrcode":"^1.5.4","express":"^5.2.1","systray":"^1.0.5","node-pty":"^1.1.0","react-dom":"^19.2.3","socket.io":"^4.8.3","@xterm/xterm":"^6.0.0","lucide-react":"^0.561.0","@types/qrcode":"^1.5.6","react-markdown":"^10.1.0","qrcode-terminal":"^0.12.0","@xterm/addon-fit":"^0.11.0","socket.io-client":"^4.8.3","react-simple-keyboard":"^3.8.198"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^5.9.3","@types/node":"^25.0.3","@types/react":"^19.2.7","@types/express":"^5.0.6","@types/react-dom":"^19.2.3","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/8remo_1.1.4_1777968859340_0.3512653473317269","host":"s3://npm-registry-packages-npm-production"}},"1.1.5":{"name":"8remo","version":"1.1.5","description":"Remote AgentCLI and web client.","type":"module","bin":{"8remo":"app/cli/index.js"},"scripts":{"dev":"tsx src/cli/index.ts","build":"npm run build:server && npm run build:web && npm run build:app-web","clean:server":"node -e \"require('node:fs').rmSync('app', { recursive: true, force: true })\"","build:server":"npm run clean:server && tsc -p tsconfig.node.json","build:web":"next build web","build:app-web":"node scripts/copy-web-out-to-app.mjs","pack:local":"node -e \"require('node:fs').mkdirSync('.packs', { recursive: true })\" && npm pack --pack-destination .packs","deploy:relay":"npx wrangler deploy","prepack":"npm run build","test":"tsx --test --test-concurrency=1 src/**/*.test.ts","start":"node app/cli/index.js","typecheck":"tsc -p tsconfig.node.json && tsc -p web/tsconfig.json --noEmit"},"dependencies":{"@types/qrcode":"^1.5.6","@xterm/addon-fit":"^0.11.0","@xterm/xterm":"^6.0.0","express":"^5.2.1","lucide-react":"^0.561.0","mime":"^4.1.0","next":"^16.2.4","node-pty":"^1.1.0","open":"^10.2.0","qrcode":"^1.5.4","qrcode-terminal":"^0.12.0","react":"^19.2.3","react-dom":"^19.2.3","react-markdown":"^10.1.0","react-simple-keyboard":"^3.8.198","socket.io":"^4.8.3","socket.io-client":"^4.8.3","systray":"^1.0.5"},"devDependencies":{"@types/express":"^5.0.6","@types/node":"^25.0.3","@types/qrcode-terminal":"^0.12.2","@types/react":"^19.2.7","@types/react-dom":"^19.2.3","tsx":"^4.21.0","typescript":"^5.9.3"},"engines":{"node":">=20"},"_id":"8remo@1.1.5","_integrity":"sha512-ijWn7PbMteqX1ADmr/ijcM1Dg8YWDAvve9D7ZOhlzTVkMM7iLVxROP3zzPZDRMWfj9AgA1Q2BKrklXR4Cb+imA==","_resolved":"E:\\Work\\Projects\\8remo\\.packs\\8remo-1.1.5.tgz","_from":"file:.packs/8remo-1.1.5.tgz","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-ijWn7PbMteqX1ADmr/ijcM1Dg8YWDAvve9D7ZOhlzTVkMM7iLVxROP3zzPZDRMWfj9AgA1Q2BKrklXR4Cb+imA==","shasum":"1d6c9c96251dc74f31ab62cdf21728c4fcdf9f68","tarball":"https://registry.npmjs.org/8remo/-/8remo-1.1.5.tgz","fileCount":58,"unpackedSize":1890941,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDjr3K+URuvyY0zrIm87MC1uiNF9RwtOk0jkIjvtihZ1AIgT+ApGcJa1CTpNdGpS+ELSsTletBlCblPRjFdVjiCmF4="}]},"_npmUser":{"name":"nhathao95","email":"haotruongnhat@gmail.com"},"directories":{},"maintainers":[{"name":"nhathao95","email":"haotruongnhat@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/8remo_1.1.5_1777969623084_0.2777748311159396"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-05T04:40:07.127Z","modified":"2026-05-05T08:27:03.409Z","1.0.0":"2026-05-04T04:26:06.273Z","1.1.0":"2026-05-05T04:40:07.455Z","1.1.1":"2026-05-05T06:33:23.527Z","1.1.2":"2026-05-05T06:44:39.265Z","1.1.3":"2026-05-05T07:04:09.847Z","1.1.4":"2026-05-05T08:14:19.550Z","1.1.5":"2026-05-05T08:27:03.285Z"},"description":"Remote AgentCLI and web client.","maintainers":[{"name":"nhathao95","email":"haotruongnhat@gmail.com"}],"readme":"# Vibe-Coding Anywhere with 8remo\r\n\r\n<p align=\"center\">\r\n  <img src=\"https://raw.githubusercontent.com/haotruongnhat/8remo/master/web/app/icon.png\" alt=\"8remo app icon\" width=\"96\" height=\"96\">\r\n  <br>\r\n  <strong>8remo - Vibe-Coding Anywhere.</strong>\r\n</p>\r\n\r\n8remo is a local-first remote workspace tool: one npm command starts a host process and serves a browser client for terminal, files, and local site proxy workflows.\r\n\r\n## Install and start\r\n\r\n```bash\r\nnpm install -g 8remo\r\n8remo setup\r\n8remo --root <project-directory>\r\n```\r\n\r\nUse `--root` to choose the directory that 8remo can expose. The browser client can browse files, preview file contents, and create terminal sessions only inside that selected root. By default, 8remo starts a Cloudflare Quick Tunnel and shows an 8remo Quick URL, relay URL, access key, and QR code in the terminal UI.\r\n\r\nFor local-only access, pass `--no-tunnel`:\r\n\r\n```bash\r\n8remo --root <project-directory> --no-tunnel\r\n```\r\n\r\nTo keep 8remo running in the background with a notification-area icon:\r\n\r\n```bash\r\n8remo background --tray --root <project-directory>\r\n```\r\n\r\nThe default local host is `http://localhost:2208`.\r\n\r\n## Commands\r\n\r\n```bash\r\n8remo --root <project-directory>          # start with Cloudflare Quick Tunnel\r\n8remo --root <project-directory> --no-tunnel # start for local browser access only\r\n8remo                                  # return to the detached host UI when one is already running\r\n8remo ui --root <project-directory>       # start and open the local Web UI\r\n8remo background --root <project-directory>\r\n8remo background --tray --root <project-directory>\r\n8remo status                          # show detached background host status\r\n8remo stop                            # stop the detached background host\r\n8remo update                          # update a global install\r\n8remo otp setup                       # create a Google Authenticator compatible OTP key\r\n8remo otp status                      # show whether OTP unlock is enabled\r\n8remo otp renew                       # rotate the persistent OTP key\r\n8remo otp revoke                      # disable OTP unlock\r\n8remo doctor                          # check runtime tools and generated assets\r\n8remo setup                           # install cloudflared for tunnel support\r\n```\r\n\r\nOptions:\r\n\r\n```bash\r\n8remo --port 3308 --root <project-directory>\r\n8remo ui --host 0.0.0.0\r\n8remo --root <project-directory> --no-tunnel\r\n8remo --root <project-directory> --relay-url https://8remo.online\r\n8remo --tray --root <project-directory>\r\n8remo setup --skip-cloudflared\r\n```\r\n\r\nIf the CLI is started in a non-interactive shell, pass `--root <directory>` or set `EIGHT_REMO_ROOT`.\r\n\r\n## Host terminal UI\r\n\r\nWhen 8remo runs in an interactive terminal, the host process shows a colorized keyboard menu. Use arrow keys to move, Enter to select, Esc to go back, and Ctrl+C to stop the host.\r\n\r\nBefore the host starts, an initial setup stage appears when TOTP or Telegram credentials are missing. It can create the authenticator QR code and save dedicated 8remo Telegram settings under `~/.8remo/telegram.json`. Non-interactive runs skip this stage; configure TOTP with the dedicated `otp` command and Telegram with `EIGHT_REMO_TELEGRAM_BOT_TOKEN` / `EIGHT_REMO_TELEGRAM_CHAT_ID` or the host terminal UI instead.\r\n\r\nThe host menu can open the Web UI, review access requests, inspect trusted OTP devices, remove approved devices, manage Telegram notifications, run initial setup, refresh pairing state, hide to the system tray when supported, keep running in the current terminal as a fallback, or exit. Multi-select screens use Space to toggle items and Enter to continue.\r\n\r\nAccess request and trusted-device removal actions ask for confirmation before changing state.\r\n\r\n## Background and tray\r\n\r\n`8remo background --root <directory>` starts the same host server as a detached npm process and returns control to the terminal. It writes process metadata and logs under `~/.8remo`.\r\n\r\n```bash\r\n8remo background --root <project-directory>\r\n8remo background --tray --root <project-directory>\r\n8remo --tray --root <project-directory>\r\n8remo status\r\n8remo stop\r\n```\r\n\r\nThe background command still serves the Web UI on the selected host and port, and it starts Cloudflare Quick Tunnel by default. Use `--no-tunnel` for local-only background mode. Use Telegram approval replies for remote approval workflows when the terminal UI is not visible.\r\n\r\nTray mode keeps 8remo as an npm CLI while exposing a notification-area icon when the OS session supports one. In an interactive terminal session with tray support, 8remo starts or reuses a detached tray host first, then shows the terminal UI as a controller for that background host. Hide / Keep Running closes only the controller menu; the server and Cloudflare tunnel keep running in the detached host. Run `8remo` again to return to that detached session. The tray menu can copy the active URL, toggle launch-at-login, and quit the host. On headless Linux or unsupported sessions, 8remo keeps running without the tray icon.\r\n\r\nUpdate a global npm install with:\r\n\r\n```bash\r\n8remo update\r\nnpm install -g 8remo\r\n```\r\n\r\n## Browser workspace\r\n\r\nThe web client has Tree, File, and Agent views on mobile. Selecting a file opens the File view with parsed Markdown rendering for `.md`, `.markdown`, and `.mdx` files; other files render as wrapped monospace text. On desktop, the file preview is merged into the Tree workspace so the tree and selected file stay visible together.\r\n\r\nThe Agent CLI supports multiple terminal sessions. On mobile, use the paste button in the Agent CLI header to send clipboard text to the active terminal, or use the copy button to enter line-copy mode. Tap a visible terminal line to copy it, or long press to copy the wrapped output block.\r\n\r\n## OTP credential unlock\r\n\r\n8remo can accept a 6-digit TOTP code from Google Authenticator or another compatible authenticator app on the credential screen. The existing short-lived pairing URL still works as a bootstrap fallback.\r\n\r\nCreate or inspect the persistent OTP credential from the host machine:\r\n\r\n```bash\r\n8remo otp setup\r\n8remo otp status\r\n8remo otp show --reveal-secret\r\n8remo otp renew\r\n8remo otp revoke\r\n```\r\n\r\nThe OTP seed is stored in `~/.8remo/otp.json` by default. Set `EIGHT_REMO_OTP_FILE` to use another file. `setup` and `renew` print an enrollment QR code; treat that output like a password because the seed remains valid until `renew` or `revoke`.\r\n\r\nOTP attempts are rate-limited before they can create the normal 24-hour browser session.\r\n\r\nAfter a remote browser signs in with OTP through a valid relay access key, 8remo remembers that browser as a trusted device and opens the workspace without a second host-approval step. On later visits through a fresh valid relay access key, the same browser can skip TOTP because the access key proves the current route and the browser-held trusted-device cookie proves the remembered device. Revoking the trusted device in the host UI forces TOTP again. Direct tunnel/origin requests cannot use a trusted-device cookie alone to skip OTP.\r\n\r\nTrusted devices are stored in `~/.8remo/trusted-devices.json` by default. Set `EIGHT_REMO_TRUSTED_DEVICES_FILE` to use another file. The store contains hashed device fingerprints and hashed tunnel client signals, not raw browser device secrets, IP addresses, user agents, OTP codes, or pairing tokens. If the browser, network address, or user-agent changes, 8remo may require host approval again. Use the host terminal UI to remove selected approved devices or remove all trusted devices.\r\n\r\n## Local setup checks\r\n\r\nUse `doctor` to check the local runtime and optional tunnel tooling:\r\n\r\n```bash\r\n8remo doctor\r\n```\r\n\r\nThe command checks Node.js, `cloudflared`, the compiled server, and the exported web client. Missing core runtime tools return a failing exit code. Missing optional tools or generated assets are reported with fix suggestions.\r\n\r\nUse `setup` to install optional tunnel tooling:\r\n\r\n```bash\r\n8remo setup\r\n```\r\n\r\nThe command installs `cloudflared` when it is missing. It does not run `npm install`, install dev-time tooling, build the project, or validate generated server/web assets. Use a built 8remo package for normal runtime setup; in a development checkout, run `npm install` once and `npm run build` separately when source files change.\r\n\r\nOn Windows it uses:\r\n\r\n```powershell\r\nwinget install --id Cloudflare.cloudflared --accept-package-agreements --accept-source-agreements\r\n```\r\n\r\nOn macOS it uses Homebrew when `brew` is available. On Ubuntu and Debian-style Linux systems with `apt-get`, it adds Cloudflare's apt repository and installs `cloudflared` with `apt-get install -y cloudflared`. On Debian-style Linux systems without `apt-get`, it downloads the latest Cloudflare `.deb` package and installs it with `sudo dpkg -i`. Other Linux distributions should install `cloudflared` manually, or use:\r\n\r\n```bash\r\n8remo setup --skip-cloudflared\r\n```\r\n\r\n## Remote access through Cloudflare Tunnel\r\n\r\nInstall `cloudflared`, then start 8remo with `--tunnel`:\r\n\r\n```bash\r\n8remo --root <project-directory>\r\n```\r\n\r\nThe CLI still serves the local UI on `localhost`, then starts a Cloudflare Quick Tunnel to that local Node host. When `cloudflared` prints the generated `trycloudflare.com` address, 8remo prints an `8remo Quick URL`, an `8remo Relay URL`, a manual access key, and the direct `Cloudflare Tunnel URL`. Open the quick URL or scan the QR code to reach the current tunnel through `https://8remo.online`.\r\n\r\nAccess keys are short-lived routing envelopes. The hosted relay is a Cloudflare Worker that reads the access key, stores it in an HTTP-only `8remo.online` relay cookie, and proxies requests to the current `trycloudflare.com` tunnel so the browser can stay on `https://8remo.online`. If OTP is enabled, the first untrusted browser sees a TOTP prompt in the 8remo app. After a valid TOTP code, 8remo creates a 24-hour session and stores the browser as trusted. Authenticated browsers can keep using the relay for that session even after the original access key expires; unauthenticated browsers still need a fresh access key. Later visits from that browser through a valid relay access key open without TOTP. If OTP is not enabled, the Worker injects the current pairing token server-side while proxying, including Socket.IO/WebSocket handshakes. Remote tunnel clients cannot regenerate pairing tokens.\r\n\r\nTreat relay URLs and access keys as temporary secrets. 8remo periodically checks the public tunnel through `/api/health`. If `cloudflared` exits, no public URL appears during startup, or health checks fail repeatedly, 8remo restarts the tunnel, drops stale tunnel URLs from the host UI, and generates a fresh relay URL and access key for the new route.\r\n\r\nIf `EIGHT_REMO_TELEGRAM_BOT_TOKEN` and `EIGHT_REMO_TELEGRAM_CHAT_ID` are available in the process environment, or if credentials are saved in `~/.8remo/telegram.json`, 8remo sends the relay quick URL and a QR image to that Telegram chat. Telegram delivery is optional; startup continues if the credentials are missing or the send fails. The host terminal UI includes a Telegram Notifications menu for setting, testing, or clearing the dedicated 8remo bot credentials without touching Claude task-completion hook settings.\r\n\r\nIf `cloudflared` is not on `PATH`, pass its location:\r\n\r\n```bash\r\n8remo --root <project-directory> --cloudflared <cloudflared-path>\r\n```\r\n\r\nTo point generated relay links at another connect page:\r\n\r\n```bash\r\n8remo --root <project-directory> --relay-url https://8remo.online\r\n```\r\n\r\nTo deploy the hosted relay Worker:\r\n\r\n```bash\r\nnpm run deploy:relay\r\n```\r\n\r\nThe Worker configuration is in `wrangler.toml`. It serves the static access-key page from `relay/` when no key is present, then proxies keyed sessions through `8remo.online` without redirecting the browser to the raw tunnel host.\r\n\r\n## Develop from source\r\n\r\nUse these commands only when working inside this checkout:\r\n\r\n```bash\r\nnpm install\r\nnpm run dev\r\nnpm run build\r\nnpm start\r\n```\r\n\r\n`npm run dev` starts the CLI host from TypeScript. `npm run build` compiles the CLI/server and static web client. `npm start` runs the built CLI.\r\n\r\n## MVP features\r\n\r\n- Paired local browser URL with a 30-minute token.\r\n- Multiple WebSocket terminal sessions backed by the host shell.\r\n- File explorer and folder creation under the selected root, with real-path checks to block `..` traversal and symlink/junction escapes.\r\n- Local dev-server proxy at `/proxy/:port/`.\r\n- Optional Cloudflare Quick Tunnel and relay access key for remote browser access.\r\n\r\n## Later stage\r\n\r\n- Hosted edge broker.\r\n- Real PTY persistence via a native PTY backend.\r\n- Remote desktop streaming and input control.\r\n- Tauri desktop app.\r\n- React Native / Expo mobile app.\r\n","readmeFilename":"README.md"}