feat: remote access via Tailscale + HMAC (no SSH)#24
Open
james-s-hedwig[bot] wants to merge 3 commits intomainfrom
Open
feat: remote access via Tailscale + HMAC (no SSH)#24james-s-hedwig[bot] wants to merge 3 commits intomainfrom
james-s-hedwig[bot] wants to merge 3 commits intomainfrom
Conversation
Implements a minimal HTTP proxy server (RemoteServer) in cuad that lets a remote agent drive a local cuad over Tailscale using HMAC challenge-response authentication — no SSH required. What's new: - RemoteServer (CUADaemonLib): GET /handshake → challenge, POST /auth → session token (HMAC-SHA256), POST /rpc → proxy to local UDS socket. IP-level filtering for "tailscale" / "localhost" / "0.0.0.0" bind modes. Single-use challenges, ±30s replay protection, configurable TTL. - RemoteClient (CUACore): client with HMAC auth flow and disk-cached session tokens (~/.cua/remote-sessions/<name>.json) so each CLI invocation reuses a valid token without re-authenticating. - CUAConfig: new RemoteServerConfig and RemoteTarget types loaded from ~/.cua/config.json under "remote" and "remote_targets" keys. - cua remote setup: prints config snippets for both machines with a freshly generated secret and the current Tailscale IP. - --remote <target> flag on status, list, snapshot, act, pipe, screenshot; also reads CUA_REMOTE env var. - 20 new tests covering HMAC generation, challenge expiry, replay protection, session TTL, blocked apps, and config decoding.
…air) Remove 'cua remote setup' (JSON snippet printer). Replace with: - 'cua remote accept': starts a temporary NWListener-based pairing server, generates a short code (e.g. a3f1-9c2b), prints the pair command to send to the human, waits for POST /pair, writes remote_targets config and exits. - 'cua remote pair <host> <code>': sends the code to the accept server, receives a 32-byte shared HMAC secret, writes remote server config to ~/.cua/config.json (merging without clobbering), prompts 'cua daemon restart'. Both machines' configs are written automatically — no JSON copy-paste. Update skills/computer-use/SKILL.md and add docs/REMOTE.md. All 344 tests pass.
…iles - Add StreamConfig to CUAConfig (enabled, push_to, secret, flush_interval, app_levels, blocked_apps with wildcard "*" default) - Add EventStreamFilter (CUACore): maps CUAEvent → StreamEvent with level-based privacy rules; blocks apps; scrubs AXSecureTextField values from snapshots - Add EventShipper (CUADaemonLib): subscribes to EventBus, batches StreamEvents, authenticates to agent's RemoteServer via HMAC challenge-response, POSTs NDJSON - Add /stream/push endpoint to RemoteServer: validates Bearer token, parses NDJSON, appends events to ~/.cua/streams/<name>/YYYY-MM-DD.jsonl - Wire EventShipper startup in cuad/main.swift when stream.enabled - Add `cua stream read <target> [--date] [--app] [--tail] [--json]` CLI command - Update pairing ceremony: cua remote accept writes remote.secret + remote_targets; cua remote pair writes stream config with default app_levels; both print stream URL - 21 new tests in StreamTests.swift (365 total)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements a remote access layer so an agent on one machine (Mac Mini) can drive cuad on another (laptop) — no SSH, just Tailscale + HMAC challenge-response over HTTP.
New files
RemoteServer.swift(CUADaemonLib) — NWListener HTTP proxy:GET /handshake(nonce, 30s TTL),POST /auth(HMAC-SHA256 verify → session token),POST /rpc(Bearer auth, blocked-app check, method allowlist, proxies to local UDS)RemoteClient.swift(CUACore) — challenge-response client, disk-cached session tokens at~/.cua/remote-sessions/<name>.jsonRemoteTests.swift— 20 new tests: HMAC verification, single-use challenges, ±30s replay protection, session TTL, blocked apps, disallowed methods, config decoding. All 344 tests pass.Modified files
CUAConfig.swift—RemoteServerConfig+RemoteTargettypesCUA.swift—cua remote setup(generates secret, prints config snippets + Tailscale IP);--remote <target>flag +CUA_REMOTEenv var onstatus,list,snapshot,act,pipe,screenshotmain.swift— starts RemoteServer on boot whenremote.enabled = trueTest plan
swift build -c releasepassesswift test— all 344 tests pass"remote"block to~/.cua/config.json,cua daemon restart, verify log shows[remote-server] Listening on port 4567cua remote setupto generate secret + print config snippets"remote_targets", runcua --remote james-laptop status