# How to Connect Grass to Claude Code

> *Originally published at* [*codeongrass.com*](https://codeongrass.com/blog/connect-grass-to-claude-code/)

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](https://docs.anthropic.com/en/docs/claude-code/getting-started).
    
*   Grass CLI installed — `npm 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:

```plaintext
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

```bash
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:

```plaintext
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. Run `claude` in the terminal to check authentication status. If your Anthropic API key has expired, complete re-authentication 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 indicators** — `thinking`, `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:

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

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

```plaintext
~/.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.

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:

```bash
# 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. The transcript file may have been moved or deleted. Check `~/.claude/projects/<cwd>/` for the `.jsonl` file.

## 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](https://codeongrass.com/blog/what-is-an-agent-approval-gate/).

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.

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.

**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. 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. 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.

**Problem:** Long-running sessions stop receiving output on the phone after the screen locks. **Fix:** This is expected — Grass closes SSE streams when the app backgrounds for battery safety. When you unlock your phone and return to Grass, 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](https://codeongrass.com/blog/monitor-coding-agent-overnight/) — staying connected from your phone, handling approval gates, and recovery from disconnects.
    
*   [Approve or deny a coding agent action from your phone](https://codeongrass.com/blog/approve-deny-coding-agent-action-mobile/) — a deeper look at the permission modal and how to handle a backlog of pending approvals.
    
*   [Setting up Grass with a Daytona remote server](https://codeongrass.com/blog/setting-up-grass-daytona-remote-server/) — run Claude Code on a cloud workspace instead of your laptop.
    

## 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. 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. 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.

### 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. Cost is not shown mid-session — Claude Code does not emit running cost totals until completion.
