{"_id":"@akhil_a.k17/tetherd","_rev":"2-680c70cd8527da916d0e4a8861235d48","name":"@akhil_a.k17/tetherd","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@akhil_a.k17/tetherd","version":"0.2.0","keywords":["claude-code","cursor","codex","ai-agent","remote","mirror","hooks"],"license":"MIT","_id":"@akhil_a.k17/tetherd@0.2.0","maintainers":[{"name":"akhil_a.k17","email":"akhilkella17@gmail.com"}],"homepage":"https://github.com/AkhilAbhilashKella1711/tether#readme","bugs":{"url":"https://github.com/AkhilAbhilashKella1711/tether/issues"},"os":["darwin","linux","win32"],"bin":{"tetherd":"daemon/tetherd.mjs"},"dist":{"shasum":"4e667f3e4da144be3dffa96f150393e7cbe892d3","tarball":"https://registry.npmjs.org/@akhil_a.k17/tetherd/-/tetherd-0.2.0.tgz","fileCount":23,"integrity":"sha512-H+oaKjMdtAeDvz5u8KSQDbKaJZ0vFj7IANhKgQ/saF0/DFpamhw82aP5zrEcmynhie8NLMNEUnHWACtmuphcMg==","signatures":[{"sig":"MEYCIQDTWBFhRwxAZ6C/NzNsfHO/i1utel/9zM679nS2dJAm2wIhAJ3/Z3nrZoyWUfVK8TErDXeXH38L+tz+Q+57fOZSPt9A","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":351089},"type":"module","engines":{"node":">=22.5.0"},"scripts":{"relay":"node relay/server.mjs","daemon":"node daemon/tetherd.mjs run"},"_npmUser":{"name":"akhil_a.k17","email":"akhilkella17@gmail.com"},"repository":{"url":"git+https://github.com/AkhilAbhilashKella1711/tether.git","type":"git"},"_npmVersion":"10.9.4","description":"Mirror your local AI coding sessions (Claude Code, Cursor, Codex) to a web UI — watch them, answer their prompts, and steer them from anywhere. End-to-end encrypted.","directories":{},"_nodeVersion":"22.21.1","dependencies":{"ws":"^8.18.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/tetherd_0.2.0_1788425682251_0.2116608922520653","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @astrakratos/tetherd"}},"time":{"created":"2026-09-03T08:54:42.002Z","modified":"2026-09-03T09:26:06.757Z","0.2.0":"2026-09-03T08:54:42.374Z"},"bugs":{"url":"https://github.com/AkhilAbhilashKella1711/tether/issues"},"license":"MIT","homepage":"https://github.com/AkhilAbhilashKella1711/tether#readme","keywords":["claude-code","cursor","codex","ai-agent","remote","mirror","hooks"],"repository":{"url":"git+https://github.com/AkhilAbhilashKella1711/tether.git","type":"git"},"description":"Mirror your local AI coding sessions (Claude Code, Cursor, Codex) to a web UI — watch them, answer their prompts, and steer them from anywhere. End-to-end encrypted.","maintainers":[{"name":"akhil_a.k17","email":"akhilkella17@gmail.com"}],"readme":"# Tether 📡\n\nMirror your local AI coding sessions — **Claude Code**, **Cursor**, **Codex** — to a web app you\ncan open from your phone, get notified the moment one needs you, and answer its questions from\nanywhere.\n\nTether **observes and relays; it never intervenes.** Its hooks emit nothing, so every agent's own\npermission logic runs exactly as if Tether were not installed. It mirrors a question only when the\nagent genuinely asks one.\n\nTranscripts are **end-to-end encrypted**: the relay stores ciphertext and routing metadata only.\nThe account key lives in your browser and on paired machines; it travels only inside pairing\ncodes you copy yourself.\n\n## Layout\n\n- `daemon/` — `tetherd`, runs on each machine: tails each agent's transcripts, installs\n  and removes their hooks, mirrors the questions they ask, and relays your answers back.\n  Zero third-party dependencies.\n- `daemon/agents.mjs` — per-agent integration (Claude Code, Codex, Cursor): where each keeps\n  its hooks, the shape they take, and which transcripts are tailable.\n- `daemon/service.mjs` — keeping it running per OS: launchd (macOS), systemd user unit\n  (Linux), Task Scheduler (Windows).\n- `relay/` — WebSocket gateway + SQLite store + serves the app. Deliberately blind.\n- `app/` — the web client (vanilla ES modules, no build step).\n- `test/client.mjs` — headless client speaking the same protocol; used for e2e tests.\n\n## Quick start (single machine)\n\n```bash\nnpm install                      # one dependency: ws\nnode relay/server.mjs            # relay on http://127.0.0.1:8787\n# open http://127.0.0.1:8787 in a browser -> Create account -> \"Pair a machine\"\n# run the printed command on the machine:\nnode daemon/tetherd.mjs pair 'TETHER1.…' --relay http://127.0.0.1:8787 --name my-mac\nnode daemon/tetherd.mjs run      # or: node daemon/tetherd.mjs launchd install\n```\n\n### Reaching it from a phone / tablet\n\nWebSockets work from any browser on any device — the app connects to whatever origin served\nit. Two deployment requirements:\n\n1. The relay must be reachable: `HOST=0.0.0.0 PORT=8787 node relay/server.mjs` (LAN) or a\n   proper deploy (small VM, Fly, Railway).\n2. **HTTPS is required on anything that isn't localhost** — browsers only expose\n   `crypto.subtle` (used for E2E decryption) on secure origins, and `wss://` comes with it.\n   Quick test: `cloudflared tunnel --url http://127.0.0.1:8787`. Permanent: Caddy/nginx +\n   Let's Encrypt, or Tailscale Serve for private-to-your-devices access.\n\nThen pair daemons with `--relay https://<your-host>`.\n\n## Accounts: sign up, log in, link devices\n\nTether is end-to-end encrypted, so there is no email/password login — the server never has\nyour key, so it cannot \"log you in\". Instead (like Signal/WhatsApp device linking):\n\n- **Sign up** — first device: *Create account* generates the account id, encryption key and\n  client token locally (browser localStorage).\n- **Log in** — every other browser/phone: on a logged-in device press **Link a device**, move\n  the one-time `TETHERC.…` code over a channel you trust, and paste it into **Log in** on the\n  new device. The new device gets its own revocable client token; the relay only ever sees a\n  hash of the code. Codes are one-time and expire in 10 minutes.\n- **Log out** — forgets the account on that browser. The key is unrecoverable from the server\n  by design, so keep at least one linked device (or a saved login code).\n\n## Remote approvals\n\nInstall the hooks where you want approval gating (per project, or globally):\n\n```bash\nnode daemon/tetherd.mjs hooks install --settings <project>/.claude/settings.json   # one project\nnode daemon/tetherd.mjs hooks install --settings ~/.claude/settings.json          # everywhere\n```\n\n`PreToolUse` (matcher `Bash|Write|Edit|NotebookEdit`) blocks up to 4 minutes waiting for a\nremote decision; if none arrives, it answers nothing and the normal local permission flow\ntakes over. Tether can only ever *add* a way to answer, never lock you out. `Stop` /\n`Notification` hooks make state changes (finished / needs input) instant; sessions without\nhooks fall back to a 90s inactivity timer.\n\n## Failure doctrine\n\nEvery mechanism degrades to exactly what happens without Tether: daemon down → sessions run\nlocally and the mirror catches up on reconnect (transcript files are the durable log);\nrelay down → daemon retries with backoff; hook timeout → local prompt.\n\n## Security notes (v1)\n\n- Relay DB holds ciphertext only (AES-256-GCM, per-scope keys via HKDF from the account secret).\n- Daemons authenticate with Ed25519 device keys (challenge/response); clients with a bearer token.\n- The daemon's remote surface is narrow by design: resume/spawn `claude`, answer its own hooks — no generic shell.\n- Account secret sits in browser localStorage and `~/.tether/identity.json` (0600): fine for\n  personal use behind TLS; multi-user hardening is future work (plan M6).\n\n## Status\n\nM0–M4 of the build plan implemented and verified locally (mirror, pairing+E2E, hook\nnotifications, remote approvals, remote prompting incl. new sessions). Not yet done:\nWeb Push to a locked phone (M2 leg), Codex adapter (M5), hardening (M6).\n\n\n## Install\n\n```bash\nnpm i -g @akhil_a.k17/tetherd\ntetherd connect <pairing-code> --relay https://your-relay\n```\n\n`connect` pairs the machine, installs hooks for every agent it finds, registers their transcript\ndirectories, and starts the background service. `tetherd disconnect` reverses all of it and leaves\nthird-party hooks untouched.\n\n## Self-hosting the relay\n\n```bash\nTETHER_DB=/var/lib/tether/relay.sqlite HOST=0.0.0.0 PORT=8787 tetherd relay\n```\n\nPut TLS in front of it — pairing codes carry your encryption key. Give `TETHER_DB` a persistent\nvolume; it is SQLite, so an ephemeral container loses everything on redeploy.\n\n## Platform support\n\n| | macOS | Linux | Windows |\n|---|---|---|---|\n| Mirror sessions | ✅ | ✅ | ✅ |\n| Agent hooks | ✅ | ✅ | ✅ (named pipe) |\n| Background service | launchd | systemd (user) | Task Scheduler |\n| Answer prompts remotely | ✅ tmux | ✅ tmux | via WSL only |\n\nAnswering a live prompt means typing into a running TUI, which needs tmux. Windows has no\nequivalent that can be driven safely from outside, so on Windows the question is still mirrored —\nyou just answer it on the machine (or run agents under WSL).\n","readmeFilename":"README.md"}