How to Connect Grass to Claude Code

A deep dive into the Grass and Claude Code integration: how sessions are created and resumed, how the permission system works, and how to get the most out of both tools together.

This guide covers everything about connecting Grass to Claude Code: how the integration works under the hood, how to start and resume sessions, how the permission system operates, and how to handle the edge cases that come up in long-running agent workflows. If you have already run through the getting started guide, this goes deeper on the Claude Code side specifically.

TL;DR

  • Grass connects to Claude Code via the @anthropic-ai/claude-agent-sdk — no manual configuration required
  • Sessions are stored as .jsonl transcript files at ~/.claude/projects/<cwd>/<session-id>.jsonl
  • Claude Code runs in default permission mode: it pauses at agent approval gates and waits for sign-off via the Grass permission modal
  • Use claude --continue to resume the last session or claude --resume <session-id> for a specific one
  • The Grass app streams all Claude Code output over SSE with sequence-numbered frames — no output is lost on reconnect

Prerequisites

  • Claude Code installed and authenticated — run npm install -g @anthropic-ai/claude-code, then claude to complete authentication. See the Claude Code getting started guide.
  • Grass CLI installednpm install -g @grass-ai/ide (Node.js 18+ required)
  • Grass mobile app — iOS App Store (native) or Android PWA
  • A project directory with at least one git repository or folder
  • Network access — same WiFi as your machine, or Tailscale for remote connections

How does Grass connect to a running Claude Code session?

Grass and Claude Code communicate through the Grass CLI server, which sits between the agent SDK and your phone:

Grass mobile app
       |
       | HTTP REST + SSE
       |
Grass CLI server (grass start)
       |
       | @anthropic-ai/claude-agent-sdk
       |
Claude Code process
       |
       | Anthropic API
       |
Claude (model)

When you run grass start, the CLI initialises a session manager that uses the @anthropic-ai/claude-agent-sdk query() function to run Claude Code in default permission mode. The Grass server manages the lifecycle of each session — creating it, streaming its events, buffering output for replay, and forwarding permission requests to the mobile app.

Your phone never talks directly to the Claude Code process or the Anthropic API. It talks to the Grass server, which handles the agent SDK integration. This means the Claude Code session keeps running regardless of your phone's connection state.

Step 1: Start the Grass server in your project

cd ~/projects/my-repo
grass start

Grass auto-selects a port from 32100-32199 and starts the server. The output confirms which agents are available:

Starting grass server...
  workspace: /Users/you/projects/my-repo
  port: 32100
  available agents: claude-code, opencode

If claude-code does not appear in the agents list, Claude Code is not installed or not in your PATH. Run which claude to check. If it returns nothing, re-run npm install -g @anthropic-ai/claude-code.

Common issue: Claude Code appears in the list but sessions fail to start. Fix: Run claude in the terminal to check authentication status. If your Anthropic API key has expired or the authentication flow needs to be re-run, complete it in the terminal before trying again in Grass.

Step 2: Connect the Grass app and start a session

Scan the QR code with the Grass app (or tap a saved server connection). Navigate to your repository, select Claude Code from the agent picker, and tap + to start a new session.

Type a prompt and send it. The Grass server creates a new Claude Code session via the agent SDK and begins streaming events to your phone. You will see:

  • Status indicatorsthinking, tool, tool_summary — showing what the agent is currently doing
  • Tool use events — the name and input of each tool the agent invokes (file reads, bash commands, etc.)
  • Assistant messages — the agent's text responses, streamed chunk by chunk with full markdown rendering
  • Result events — on completion, a summary showing cost, duration in milliseconds, and turn count

Step 3: Understand how Claude Code session transcripts work

Every Claude Code session creates a .jsonl transcript file at:

~/.claude/projects/<url-encoded-cwd>/<session-id>.jsonl

For example, a session in /Users/you/projects/my-repo would be stored at:

~/.claude/projects/-Users-you-projects-my-repo/<session-id>.jsonl

This file is the source of truth for session history. When you resume a session in Grass, the app fetches the session list via GET /sessions?agent=claude-code&repoPath=<path>, which reads the transcript files on disk. Opening a past session loads its full message history from the .jsonl file.

This means session history persists across Grass restarts, machine restarts, and reconnects. As long as the transcript file exists on disk, the session is resumable.

Step 4: Resume a Claude Code session

To resume a session from the Grass app: tap the server, select the repository, choose Claude Code, and tap an existing session from the list. Grass loads the full history from the transcript file and reconnects to the session.

To resume from the terminal:

# Resume the most recent session
claude --continue

# Resume a specific session by ID
claude --resume <session-id>

The session ID is visible in the Grass session list and in the transcript filename. You can resume a session that was started in Grass from the terminal, or vice versa — the transcript file is the shared state.

Common issue: A session appears in the Grass list but shows no history when opened. Fix: The transcript file may have been moved or deleted. Check ~/.claude/projects/<cwd>/ for the .jsonl file. If it is missing, the session history cannot be recovered, but you can start a new session from the same repository.

Step 5: Handle permission requests from your phone

Claude Code runs in default permission mode when started via Grass. In this mode, it pauses before taking any action that modifies your system — writing files, running bash commands, fetching URLs. These pauses are agent approval gates.

When the agent hits a gate, Grass forwards the permission request to your phone via the /permissions/events SSE stream. A native modal appears with:

  • The action type (file write, bash command, URL fetch)
  • Full details — file path and diff preview for writes; exact command string for bash; target URL for fetches
  • Approve and Deny buttons

Tapping Approve sends a POST /sessions/:id/permission with approved: true. The agent proceeds. Tapping Deny sends approved: false — the agent skips the action and handles the denial gracefully, either continuing with the rest of the task or reporting it could not complete the step.

The global permission manager in the Grass app queues requests from all connected servers. If multiple sessions hit approval gates simultaneously, they surface one at a time in the order received.

How do I know the Claude Code integration is working correctly?

A correctly configured Grass and Claude Code setup looks like this:

  • The Grass server logs show available agents: claude-code on startup
  • Starting a new session and sending a prompt produces streaming output within a few seconds
  • The session appears in the Grass session list with a preview of the first messages
  • Asking the agent to write a file triggers a permission modal on your phone with a diff preview
  • After the session ends, the transcript file exists at ~/.claude/projects/<cwd>/<session-id>.jsonl

To explicitly test the permission flow: send the prompt create a file called test.txt with the contents hello world. Claude Code will request approval to write the file. The modal should appear on your phone with the file path and content preview.

Troubleshooting

Problem: Claude Code sessions start but output stops streaming after a few seconds. Fix: Check your network connection — the SSE stream between the Grass app and server may have dropped. Pull down to refresh in the Grass chat view to re-attach the stream. If the issue persists, check that no firewall or VPN is interfering with the SSE connection on the port Grass is using.

Problem: Permission modals show the action but the Approve button does not respond. Fix: The POST /sessions/:id/permission request may be failing. Check that the Grass server is still running in the terminal (it should show request logs). If the server has stopped, restart it with grass start — the session transcript is still on disk and can be resumed.

Problem: Session history is not loading — the session list shows sessions but opening one shows an empty chat. Fix: The Grass server is not finding the transcript files. Confirm the repoPath the Grass app is using matches the directory where Claude Code was run. The transcript path is derived from the working directory at the time the session was created — if you moved the project directory, the path will not match.

Problem: Claude Code is available in the terminal but not showing in the Grass agent picker. Fix: The Grass server checks for the claude binary at startup. If Claude Code was installed after grass start was run, restart the Grass server. Run grass start again in the terminal.

Problem: Long-running sessions stop receiving output on the phone after the screen locks. Fix: This is expected behaviour — Grass closes SSE streams when the app backgrounds for battery safety. When you unlock your phone and return to the Grass app, the stream re-attaches automatically and replays any missed output using the Last-Event-ID header and SSE sequence numbers.

Next steps

Monitor a long-running coding agent overnight — How to keep a Claude Code session running for hours and stay connected from your phone: live output, permission modals, and recovery from disconnects.

Approve or deny a coding agent action from your phone — A deeper look at the permission modal: what triggers it, what information it shows, and how to handle a backlog of pending approvals.

Setting up Grass with a Daytona remote server — Run Claude Code on a cloud workspace instead of your laptop. This guide covers the Daytona-specific configuration for remote Claude Code sessions.

Frequently asked questions

Does Grass work with all Claude Code versions?

Grass uses the @anthropic-ai/claude-agent-sdk to run Claude Code sessions. As long as the claude CLI is installed and authenticated on your machine, Grass will use whatever version is currently installed. There is no minimum version requirement beyond what the agent SDK itself requires. Run claude --version to check your installed version.

Can I run Claude Code with a custom model via Grass?

Grass runs Claude Code using the agent SDK defaults — it does not currently expose model selection in the app. Claude Code uses the model configured in your Claude Code settings or via environment variables. If you need a specific model, set the ANTHROPIC_MODEL environment variable before running grass start.

What happens to the Claude Code session if I force-quit the Grass app?

The Claude Code session keeps running on your machine. The Grass server process is independent of the mobile app — closing the app only drops the SSE connection. The agent continues working, the transcript file continues being written, and approval gates queue on the server side. When you reopen the app and reconnect, everything replays from where you left off.

How does Grass handle Claude Code's context window limits?

Grass does not manage Claude Code's context window — that is handled by the agent SDK and Claude Code itself. For very long sessions, Claude Code may summarise prior context automatically. If a session approaches context limits, you will see this reflected in the agent's behaviour (it may reference fewer earlier messages). Starting a new session with --continue gives Claude Code a fresh context while keeping the session history on disk.

Can multiple people connect to the same Grass server and Claude Code session?

Yes — the Grass server has no authentication and will accept connections from any client that can reach the port. Multiple phones can connect to the same server and see the same session output. However, only one person should be sending prompts and handling approval gates at a time to avoid conflicting instructions to the agent.

Is there a way to see how much an overnight Claude Code session cost?

Yes. When a Claude Code session completes, Grass receives a result event from the agent SDK that includes cost, duration in milliseconds, and turn count. This is displayed at the end of the session in the Grass chat view. For sessions still in progress, cost is not shown until completion — Claude Code does not emit running cost totals mid-session.