# @react-grab/opencode

OpenCode agent provider for React Grab. Requires running a local server that interfaces with the OpenCode CLI.

## Installation

```bash
npm install @react-grab/opencode
# or
pnpm add @react-grab/opencode
# or
bun add @react-grab/opencode
# or
yarn add @react-grab/opencode
```

## Server Setup

The server runs on port `6567` by default.

### Quick Start (CLI)

Start the server in the background before running your dev server:

```bash
npx @react-grab/opencode@latest && pnpm run dev
```

The server will run as a detached background process. **Note:** Stopping your dev server (Ctrl+C) won't stop the React Grab server. To stop it:

```bash
pkill -f "react-grab.*server"
```

### Recommended: Config File (Automatic Lifecycle)

For better lifecycle management, start the server from your config file. This ensures the server stops when your dev server stops:

### Vite

```ts
// vite.config.ts
import { startServer } from "@react-grab/opencode/server";

if (process.env.NODE_ENV === "development") {
  startServer();
}
```

### Next.js

```ts
// next.config.ts
import { startServer } from "@react-grab/opencode/server";

if (process.env.NODE_ENV === "development") {
  startServer();
}
```

> **Note:** You must have [OpenCode](https://opencode.ai) installed (`npm i -g opencode-ai@latest`).

## Client Usage

### Script Tag

```html
<script src="//unpkg.com/react-grab/dist/index.global.js"></script>
<script src="//unpkg.com/@react-grab/opencode/dist/client.global.js"></script>
```

### Next.js

Using the `Script` component in your `app/layout.tsx`:

```jsx
import Script from "next/script";

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        {process.env.NODE_ENV === "development" && (
          <>
            <Script
              src="//unpkg.com/react-grab/dist/index.global.js"
              strategy="beforeInteractive"
            />
            <Script
              src="//unpkg.com/@react-grab/opencode/dist/client.global.js"
              strategy="lazyOnload"
            />
          </>
        )}
      </head>
      <body>{children}</body>
    </html>
  );
}
```

### ES Module

```tsx
import { attachAgent } from "@react-grab/opencode/client";

attachAgent();
```

## Options

You can configure the OpenCode agent provider:

```typescript
import { createOpenCodeAgentProvider } from "@react-grab/opencode/client";

const provider = createOpenCodeAgentProvider({
  serverUrl: "http://localhost:6567", // Custom server URL
  getOptions: () => ({
    model: "claude-sonnet-4-20250514", // AI model to use
    agent: "build", // Agent type: "build" or "plan"
    directory: "/path/to/project", // Project directory
  }),
});
```

## How It Works

```
┌─────────────────┐      HTTP       ┌─────────────────┐     stdin      ┌─────────────────┐
│                 │  localhost:6567 │                 │                │                 │
│   React Grab    │ ──────────────► │     Server      │ ─────────────► │    opencode     │
│    (Browser)    │ ◄────────────── │   (Node.js)     │ ◄───────────── │      (CLI)      │
│                 │       SSE       │                 │     stdout     │                 │
└─────────────────┘                 └─────────────────┘                └─────────────────┘
      Client                              Server                            Agent
```

1. **React Grab** sends the selected element context to the server via HTTP POST
2. **Server** receives the request and spawns the `opencode` CLI process
3. **OpenCode** processes the request and streams JSON responses to stdout
4. **Server** relays status updates to the client via Server-Sent Events (SSE)
