Setting Up Grass with a Daytona Remote Server
A complete technical walkthrough for running Claude Code on a Daytona remote workspace and monitoring it from your phone with Grass — including Tailscale setup and troubleshooting.
This guide walks through the full technical setup for running Claude Code on a Daytona remote workspace and connecting to it from your phone using Grass. By the end, you will have a remote coding session running entirely in the cloud — your laptop can stay off — with live agent output and approval gates surfacing on your phone.
TL;DR
- Install Grass CLI and Claude Code on the Daytona workspace, not your laptop
- Use
grass start --network tailscalefor private access, orgrass start --network remote-ipfor public IP access - Scan the QR code with the Grass app to connect — everything else works identically to local
- Daytona workspaces persist between stops; add Grass to your
devcontainer.jsoninit script to avoid reinstalling - If the workspace auto-stops mid-session, Claude Code transcripts are preserved on disk and sessions are resumable
Prerequisites
- A Daytona account with at least one workspace configured. See the Daytona workspaces documentation for workspace creation.
- Node.js 18+ on the Daytona workspace — most Daytona base images include Node.js. Run
node --versioninside the workspace terminal to confirm. - Claude Code installable on the workspace — requires an Anthropic API key or Claude account. Authentication must be completed inside the workspace terminal.
- Grass mobile app — iOS App Store (native) or Android PWA.
- Tailscale (recommended) — installed on both the Daytona workspace and your phone. See Tailscale's setup guide for installation on both platforms.
How do the pieces fit together?
In a local Grass setup, the CLI server and the agent run on your laptop, and your phone connects over WiFi. In a Daytona setup, the CLI server and the agent both run on the Daytona workspace — your laptop is removed from the picture entirely:
Your phone (Grass app)
|
| HTTP REST + SSE
| (over Tailscale or public internet)
|
Daytona workspace
├── grass start (CLI server, port 32100–32199)
├── Claude Code process
└── ~/.claude/projects/ (session transcripts)
|
| Anthropic API
|
Claude (model)
The Daytona workspace handles all compute and storage. Grass on your phone is the interface layer. Your laptop is not in this diagram at all — you can close it after starting the workspace and kicking off the task.
The key difference from local setup is the network path. Your phone cannot reach the Daytona workspace over local WiFi — it needs either Tailscale (a private overlay network) or a public IP with the Grass port exposed. Tailscale is strongly recommended.
Step 1: Open a terminal in your Daytona workspace
Access your Daytona workspace terminal via the Daytona dashboard, VS Code Remote SSH, or direct SSH. Confirm you are inside the workspace:
pwd
node --version
If node is not available, install it:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
Step 2: Install Grass CLI and Claude Code on the workspace
npm install -g @grass-ai/ide
npm install -g @anthropic-ai/claude-code
Verify both are installed:
grass --version
claude --version
Then authenticate Claude Code. This requires completing the authentication flow inside the workspace terminal — it cannot be done from the Grass mobile app:
claude
Follow the prompts to authenticate with your Anthropic account or API key. Once authenticated, exit with Ctrl+C.
Common issue: npm install -g fails with a permissions error.
Fix: Run with sudo, or configure npm to use a user-writable global directory: mkdir ~/.npm-global && npm config set prefix ~/.npm-global and add ~/.npm-global/bin to your PATH.
Step 3: Install and configure Tailscale on the workspace
Tailscale is the recommended way to connect your phone to the Daytona workspace privately. Install it on the workspace:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Authenticate Tailscale — this opens a URL you visit in a browser to authorise the workspace device on your Tailscale account. Once authenticated, get the workspace's Tailscale IP:
tailscale ip -4
Note this IP — it is what Grass will encode in the QR code when you use --network tailscale.
Also ensure Tailscale is installed and running on your phone. The iOS Tailscale app is available from the App Store; Android from the Play Store.
Common issue: tailscale up hangs or fails with a kernel module error.
Fix: Some Daytona base images do not include the TUN kernel module required by Tailscale. Try sudo tailscale up --tun=userspace-networking which runs Tailscale in userspace mode without requiring the kernel module.
Step 4: Start the Grass server
Navigate to your project directory on the workspace and start Grass:
cd ~/projects/my-repo
grass start --network tailscale
Grass detects your Tailscale IP and encodes it in the QR code. The output should show a Tailscale IP address (typically in the 100.x.x.x range) rather than a local 192.168.x.x address:
Starting grass server...
workspace: /home/user/projects/my-repo
port: 32100
available agents: claude-code
Tailscale http://100.94.x.x:32100
[QR code]
Scan to open on your phone
If you are not using Tailscale, use --network remote-ip instead:
grass start --network remote-ip
This fetches your workspace's public IP from api.ipify.org. Note that Grass has no authentication — if you use a public IP, ensure the Grass port is protected by a firewall rule restricting access to your phone's IP address.
Common issue: --network tailscale prints a local IP instead of a Tailscale IP.
Fix: Tailscale may not be running. Run tailscale status to check. If it shows Tailscale is stopped, run sudo tailscale up again.
Step 5: Scan the QR code and connect
Open the Grass app on your phone. Tap Scan QR Code and scan the code from the workspace terminal. The connection is added to your server list.
Tap the server, select your repository, choose Claude Code, and start a new session. Send a prompt — output should begin streaming to your phone within a few seconds.
Common issue: Connection fails after scanning — app shows a connection error.
Fix: Confirm both the workspace and your phone are connected to Tailscale. Run tailscale ping <phone-tailscale-ip> from the workspace terminal to verify connectivity. If ping fails, check that both devices show as connected in your Tailscale admin console.
Step 6: Keep Grass running when the terminal closes
By default, grass start runs in the foreground. If the terminal session closes — because you disconnect from SSH or close your laptop — Grass stops and the agent session ends.
Run Grass inside tmux to keep it alive:
# Start a new tmux session running grass
tmux new-session -d -s grass 'cd ~/projects/my-repo && grass start --network tailscale'
# Attach to the session to see output
tmux attach -t grass
# Detach without stopping it: Ctrl+B, then D
With this setup, closing your laptop or SSH connection does not affect the Grass server or the Claude Code session running inside it. The Daytona workspace and tmux session keep everything alive independently.
How do I know the Daytona setup is working correctly?
A correctly configured remote setup looks like this:
- The Grass app shows the server with a green status indicator
- The server URL shown in the app uses a Tailscale IP (
100.x.x.x) or a public IP — not a local192.168.x.xaddress - Starting a Claude Code session and sending a prompt produces streaming output on your phone
- Closing your laptop and reopening the Grass app reconnects to the same session
- Asking the agent to write a file triggers a permission modal on your phone with a diff preview
To verify the workspace is truly independent of your laptop: start a session, close your laptop completely, wait 5 minutes, then reopen the Grass app. If the session is still running and the output has continued, the setup is correct.
Troubleshooting
Problem: tailscale ip -4 returns nothing or an error.
Fix: Tailscale is not authenticated or not running. Run sudo tailscale up and complete the browser-based authentication flow. If the workspace does not have a browser, copy the authentication URL and open it on another device.
Problem: Grass connects but Claude Code does not appear in the agent picker.
Fix: Claude Code was not found in PATH when grass start ran. Run which claude on the workspace to confirm it is installed. If the path is non-standard (e.g. ~/.npm-global/bin/claude), ensure that directory is in PATH before running grass start.
Problem: The Daytona workspace auto-stopped mid-session and the Grass connection dropped.
Fix: Restart the workspace from the Daytona dashboard. Once running, re-run tmux attach -t grass to resume the Grass server (or start a new one). Claude Code session transcripts are stored at ~/.claude/projects/<cwd>/<session-id>.jsonl on the workspace filesystem — if the workspace persists disk state between stops, resume with claude --continue.
Problem: grass start --network remote-ip generates a QR code but the phone cannot connect.
Fix: The Grass port (32100 by default) may be blocked by the Daytona workspace's firewall. Check your Daytona workspace network settings and open the relevant port for inbound connections. Alternatively, switch to Tailscale which avoids firewall issues entirely.
Problem: Tailscale connects but the Grass SSE stream is very slow or keeps dropping.
Fix: The Daytona workspace may be in a different geographic region from your phone, adding latency to the SSE connection. Try switching to a Daytona workspace region closer to your location. SSE reconnects automatically using Last-Event-ID — output is never lost, but high-latency connections may feel sluggish.
Next steps
Connect Grass to Daytona — The use case companion to this guide: a scenario-focused walkthrough of the same Daytona integration, with more detail on when to use it and what the day-to-day workflow looks like.
Monitor a long-running coding agent overnight — Once your remote setup is running, this covers the overnight monitoring workflow: staying connected from your phone, handling approval gates, and recovering from disconnects.
Manage multiple agents from one mobile dashboard — Running multiple Claude Code sessions across Daytona workspaces simultaneously, all monitored from the Grass app.
Frequently asked questions
Does the Daytona workspace need to stay running for Grass to work?
Yes. Grass connects to the Grass CLI server running on the Daytona workspace. If the workspace stops, the CLI server stops and the Grass connection drops. Restart the workspace from the Daytona dashboard to re-establish the connection. Claude Code session history is preserved in transcript files on the workspace filesystem as long as the workspace disk is not wiped.
Can I automate the Grass and Claude Code installation on every new Daytona workspace?
Yes. Add the installation commands to your workspace devcontainer.json or init script:
{
"postCreateCommand": "npm install -g @grass-ai/ide @anthropic-ai/claude-code"
}
This runs automatically when the workspace is created. Note that Claude Code authentication still needs to be completed manually inside the workspace terminal the first time.
Is there a way to use Grass with Daytona without Tailscale?
Yes — use grass start --network remote-ip. This generates a QR code with the workspace's public IP. You will need to open the Grass port (default 32100) in your Daytona workspace's firewall or network settings. Grass has no authentication, so restrict the open port to your phone's IP address if possible. Tailscale is simpler and safer for most setups.
What happens to Claude Code session data if the Daytona workspace is destroyed?
All session data — transcript files, project files, authentication state — is lost when a Daytona workspace is destroyed (as opposed to stopped). Before destroying a workspace, ensure the agent has committed and pushed all changes to your remote repository. Claude Code transcripts at ~/.claude/projects/ are not backed up automatically.
Can I connect to the same Daytona workspace from multiple phones?
Yes. The Grass server accepts connections from any client that can reach the port. Multiple phones can connect simultaneously and see the same session output. Only one device should send prompts or handle approval gates at a time to avoid conflicting instructions.
How do I run multiple Claude Code sessions on one Daytona workspace?
Run grass start from different project directories in separate tmux windows. Grass auto-selects different ports for each instance. Each instance appears as a separate server connection in the Grass app. This is mobile coding agent orchestration on remote infrastructure — multiple agents running on one workspace, all manageable from your phone.