Antigravity 2.0 remote ssh solution

Continuing the discussion from Antigravity 2.0 where's remote dev / wsl support? editor view? terminal?:

Hi @manavbhullar,

First off: hats off on the event-driven socket reconciler. Replacing the typical battery-draining while true; sleep 5 polling script with a tiny C socket listener (mac-listener on :4455) triggered by Linux systemd network state events and macOS launchd is clean, thoughtful systems engineering. It solves the classic frozen-mount recovery problem without burning idle CPU cycles.

The friction you are solving is very real. Because Antigravity 2.0’s desktop Agent Manager is bound to local workspace boundaries, developers on lightweight client machines need a viable way to offload heavy builds, Docker daemons, and test suites to headless Linux servers.

After running extensive long-horizon agentic benchmarks, I wanted to share a constructive architectural observation about the single operational vulnerability in this setup: the Prompt-Level Execution Trap.


1. The Vulnerability: Prompt Discipline vs Long-Horizon Drift

In your AGENTS.md, you instruct the model:

“NEVER run terminal commands on the local Mac. Always run commands over SSH using ssh my-server 'cd ~/Codes/<project> && <command>'.”

While this works smoothly during short, 5-turn interactions, it inevitably breaks down in long, complex trajectories:

  1. Conversational Attention Degradation (Lost in the Middle): As context expands (turn 25+), LLMs experience recency decay. During deep reasoning turns or when recovering from tool errors, the agent’s attention prioritises immediate syntax resolution over top-level negative constraints. It will eventually drop the ssh wrapper and execute npm run build, pytest, or git directly in the local Mac shell.
  2. Double-Quoting & Shell Escaping Hell: Forcing the model to wrap bash commands inside single-quoted SSH strings (ssh my-server 'cd path && command') creates acute friction with nested quotes, heredocs, pipes, and awk variables ($1). Agents frequently trip over string interpolation, resulting in syntax errors and hallucinated retry loops.

2. The Architectural Evolution: The Deterministic MCP Remote Gateway

To make this rock-solid, the remote boundary should not be negotiated via prompt instructions. It should be enforced deterministically at the Model Context Protocol (MCP) tool layer:

[Antigravity Agent]
       |
       +--> MCP Tool: remote_run_command({ cmd: "npm", args: ["run", "build"] })
                 |
                 +--> [Local MCP Server] --(SSH ControlMaster / Tailscale)--> [Remote Ubuntu Host]

By introducing a lightweight, dedicated Remote Runner MCP:

  • Zero Local Execution Leaks: The agent’s native local command runner is restricted or omitted from the toolset. The agent physically cannot touch the local host because its execution tool only speaks to the remote server.
  • Zero Quoting Bugs: Commands and flags are passed as clean, unescaped JSON string arrays (["cargo", "test", "--all"]), bypassing shell escaping issues entirely.
  • Persistent Multiplexing: The MCP server maintains an active SSH ControlMaster socket over the Tailscale tunnel, eliminating the per-command SSH handshake overhead.
  • True Cross-Platform Support: The client side becomes platform-agnostic, running identically on macOS, Linux, or Windows workstations.

3. A Question on SMB Directory Walk Throughput

How are you finding Antigravity’s indexing and file-search performance over SMB on repositories with tens of thousands of files?

In our testing with network-mounted shares, high-frequency stat calls, AST tree parsing, and ripgrep searches across deep directory trees often introduce noticeable latency over network round-trips compared to local NVMe storage. Have you considered pairing your SSH execution gateway with a bidirectional delta-sync engine (like Mutagen) so file reads remain instantaneous on local disk while mutations sync to Linux in sub-10ms?

Really impressive proof-of-concept. Closing the loop with a deterministic MCP execution tool would make this a bulletproof enterprise pattern.

Hi @dllhell, thank you for the detailed feedback. You were right on both points, so I built it.

1. Prompt drift → now enforced at the tool layer. I added a remote-runner MCP server. The interesting part is that the MCP server itself runs on the Linux box: Antigravity starts it with ssh -T my-server ~/.local/share/remote-runner/run.sh, so nothing new runs on the Mac. Tools: run_on_server, start_background, read_background, stop_background, list_background. Mac paths like /Volumes/Codes/project are mapped to the server path automatically.

Since I can’t fully remove Antigravity’s built-in terminal, I added a second, deterministic layer on the Mac: a small zsh safety net loaded from ~/.zshenv. Inside the shared folder, npm, node, python, pip, git, cargo, docker and others are forwarded to the server over SSH. So even if the agent drifts at turn 40 and types npm run build locally, it still runs on the server. I tested it: python3 typed on the Mac printed the server’s hostname.

2. Quoting hell → gone. run_on_server takes either an argv list (["npm", "run", "build"]) or a bash script sent on stdin, so there’s no ssh '...' layer. I tested nested quotes, pipes, a heredoc and awk '{print $1}', and all worked as written. The safety net single-quotes every argument, so python3 -c 'print("it'\''s ok")' arrives unchanged.

Two small corrections for anyone reading: the listener is Swift, not C, and the server side is triggered by ip monitor(kernel network events), with systemd only keeping it alive.

3. SMB throughput: I chose a single copy on the server over Mutagen on purpose: the agent’s edits land on the server instantly and there’s no second copy that can conflict. But I agree it’s a trade-off for very large repos, and Mutagen is a good option there.

One question back: do you know if Antigravity 2.0 lets you disable the built-in terminal tool per workspace? If so, the MCP tool would be the only way to run commands, and the safety net would just be a backup.

Repo (with the new mcp/ folder and a changelog): GitHub - manav-bhullar/agent-remote-workspace: Let local-only AI agents (Antigravity 2.0, Gemini, Claude, Codex) work on a remote Linux server: files mount on your Mac over SMB, commands run over SSH, and the connection heals itself. · GitHub

Thanks again, this made the setup much more solid.

Hi @manavbhullar,

Launching the MCP server directly on the Linux host via ssh -T my-server ~/.local/share/remote-runner/run.sh is brilliant. Using SSH as the transport layer for JSON-RPC stdio completely sidesteps opening network ports on the client, and mapping /Volumes/Codes/... to remote paths transparently makes the developer experience seamless.

Regarding your question on disabling Antigravity 2.0’s built-in terminal per workspace:

Currently in the Antigravity 2.0 desktop IDE, there is no official per-workspace configuration flag (e.g. in .antigravity/settings.json) to completely omit run_command from the root agent’s declared tool schema. While you can configure terminal auto-execution policies (forcing the UI to prompt for user approval before commands run) or strip execution tools when spawning custom subagents (enable_write_tools: false), the primary session agent always inherits the core terminal tool by default.

This is precisely why your ~/.zshenv shell interceptor (rw-guard.zsh) is the single smartest solution available today:

  • Even if the LLM experiences attention drift at turn 40 and invokes run_command, the spawned subshell on macOS intercepts npm, cargo, docker, and python inside /Volumes/Codes and redirects them over SSH.
  • It turns what would be an uncontrolled local leak into a harmless, transparent remote redirection.

This would make a fantastic concrete feature request for the Google DevRel and Antigravity teams: allowing workspaces to define an explicit tool denylist (e.g. antigravity.tools.exclude: ["run_command"] in .gemini/settings.json) so developers can delegate all execution strictly to custom MCP servers like remote-runner.

Kudos on shipping the update and documenting it so cleanly in the changelog. This is by far the most solid remote-development pattern for Antigravity 2.0 circulating right now.