Observe and drive GitHub Copilot from your phone — with zero code-sync to GitHub.
CloakCode is a local-to-remote bridge that lets you observe and drive GitHub Copilot in your local VS Code from a phone (a React PWA) or another machine. Your code never syncs to GitHub or any third party — CloakCode adds no new egress: it mirrors Copilot's own chat transcript and relays your prompts over a secure tunnel to your own devices, and never logs secrets or raw code.
You keep VS Code's own Copilot chat — the interactive session you prefer, where you select code, point at specific things, and attach files or screenshots — which has no remote of its own. CloakCode adds one, and you switch fluidly between the desktop and your phone. When a long agent run stalls on a blocker — a confirmation, a multiple-choice question, or a tool-call approval — you get pinged and answer it remotely so the run keeps moving, instead of walking back hours later to find it waiting on a one-word answer. GitHub now ships native remote for Copilot too, but it streams your session up to GitHub and needs cloud session storage enabled by policy; CloakCode keeps the session on your machine with nothing synced and nothing to enable, in the VS Code Copilot UI with your own models.
Screenshots are the real PWA running against the repo's UI playground fixtures — sample sessions, not anyone's code.
Status — 1.0, shipped. The observer (list · live mirror · blocker detection), the actuator (answer · approve · steer · queue · stop) and the security core (operator TOTP, per-window provider tokens,
wss://with certificate pinning) are all released on the Marketplace, npm and Docker. What comes next is tracked in docs/05 — Roadmap.
Why this exists, and what it was like to build: Your Copilot agent is waiting for you — and you're not at your desk — part 1 of the Driving Copilot from anywhere series (all parts).
- Models: the stable
vscode.lmAPI gives consented access to Copilot models. - Observation: Copilot writes a live, structured transcript to disk per session — CloakCode tails it (works even for stock Copilot sessions).
- Blocker detection: an awaiting-input prompt shows up as an unmatched interactive tool call carrying the full question + options — enough to render richly on a phone.
The full empirical account (experiments and wrong turns included) is in docs/02 — Research findings.
- Extension (the desktop side): install CloakCode from the
VS Code Marketplace, or run
code --install-extension rexwel.cloakcode. Each window serves its own phone PWA + bridge on loopback; run CloakCode: Set Up Phone Tunnel to get a phone-reachable URL. - Gateway (optional hub for many windows / machines):
@cloakcode/gatewayvianpx @cloakcode/gateway, or the Docker image. It serves the phone on the operator listener (3543) and accepts extensions on the provider listener (wss://<host>:3544). Don't hand-write that address — run Connect an extension in the app and paste the pairing URL it shows into"cloakcode.gatewayUrl"; it carries the gateway's certificate fingerprint as a#fp=…fragment so the first connection is pinned, not trusted blindly.
Why the gateway exists and when you actually need one: One phone link for every window.
Open in the dev container (VS Code: Dev Containers: Reopen in Container). It mounts the repo at
/workspaces/cloakcode, sets up a persisted cache volume, and installs Node + pnpm + tooling. Then:
pnpm install
pnpm build
pnpm -r test # Vitest
pnpm -r test:coverage # coverage gate (85% statements/lines/functions, 75% branches)Common build/package/run flows are wrapped in a Taskfile.yml — the dev container
installs task, so run task (or task --list) to see them all:
| Task | What |
|---|---|
task build · task check |
build all · full gate (typecheck + lint + test) |
task package |
package everything — extension .vsix + assembled gateway |
task extension:install / extension:uninstall |
install / remove the packaged extension (+ its Copilot hook) |
task gateway:dev -- --help |
list dev-gateway switches: --devtunnel, --mfa, --bind, --port, and optional --instance-id |
task gateway:dev -- --devtunnel --mfa |
build + run the dev gateway with a private tunnel and operator TOTP |
task gateway:run -- --tunnel |
run the assembled gateway with a private tunnel |
task playground · task web:dev |
UI playground · PWA dev server |
task docker:gateway |
build the gateway image — run from your WSL/host (Docker isn't in the container) |
Try the research tools against your local Copilot sessions:
python3 research/list_sessions.py
python3 research/inspect_session.py <session-id-prefix>.devcontainer/ Dev container: fixed /workspaces/cloakcode mount + persisted cache volume
docs/ Design & the full research record (read docs/README.md first)
research/ Validated Python PoCs (session lister + blocker detector)
packages/
protocol/ SessionPart union + RPC schema (zod) — the contract
agent/ (planned) pausable tool-calling + confirmation loop — reserved, no source yet
extension/ VS Code host: vscode.lm + transcript observer + localhost bridge
web/ Phone-first React/Vite PWA client
web-playground/ Dev-only: the real PWA against in-browser fixtures, no gateway needed
gateway/ Standalone hub: serves the PWA + a WebSocket hub for many windows
- Only
@cloakcode/extensionimportsvscode;protocolandagentstay pure and unit-testable. - Shared types come from
@cloakcode/protocol— never duplicated across packages.
CloakCode binds 127.0.0.1 by default and reaches your phone through a private tunnel — so
nothing sits on your LAN. When you do widen it (LAN / container / WSL), the listeners are
authenticated: the phone proves itself with TOTP, each extension with a provider token, and
the provider link is wss:// with the certificate pinned by the pairing URL. Even so, prefer
forward, don't widen — the smallest exposure is still the best one.
- Docker gateway tunnel: the image already contains the
devtunnelCLI. Enable it withCLOAKCODE_TUNNEL=devtunnel; finish the device-code sign-in shown indocker logs. Mount-v cloakcode-devtunnel:/home/app/.local/share/DevTunnelsto retain the login when the container is replaced. This volume stores login tokens, not the CLI binary. See gateway Docker setup for a complete command and the separate volume for the operator TOTP secret. - Deployment options (embedded vs gateway, per-client addressing, dev-container / WSL forwarding, host-firewall rules): docs/07 — Deployment.
- Security model (zero code-sync, bounded egress, provenance tagging, threat model): docs/04 — Security & compliance.
The same ground in prose — the reasoning, and the traps found on the way: Deploying the gateway without opening doors you shouldn't and Security by construction.
- Vision & requirements
- Research findings — the empirical record (+
02.xtopic files) - Architecture
- Security & compliance
- Roadmap & open questions
- Field notes — build/tooling gotchas & verified practices
- Deployment
The docs above are the reference and track main. The blog series is the narrative — why each
decision was made, and what was tried first. Driving Copilot from anywhere:
- Your Copilot agent is waiting for you — and you're not at your desk — the problem, and why an agent that stalls on a one-word answer is the thing worth fixing.
- One phone link for every window — now behind a code — the standalone gateway, and the operator sign-in in front of it.
- Deploying the gateway: containers, WSL, and your LAN — forwarding rather than widening, and what each shape actually exposes.
- Security by construction: drive it from your phone, keep your code on your machine — zero code-sync as an architectural property, certificate pinning, and message provenance.
Work milestone by milestone and slice by slice, following the dependency direction
protocol → agent/extension → web. Write the failing test first (TDD), keep the pure packages highly
covered, and run the narrowest relevant check before continuing (pnpm --filter @cloakcode/... test,
poetry run pytest research). See .github/copilot-instructions.md
for the full engineering discipline and the non-negotiable security rules.
Built by Likhan Siddiquee — likhansiddiquee.com · LinkedIn. Questions, ideas and bug reports are welcome as issues.




