> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.recursiv.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.recursiv.io/_mcp/server.

# Projects & Deploy

## Overview

Projects are the top-level container for your applications. Each project can have sandboxes for development, databases, storage buckets, and production deployments.

All project methods are available on `r.projects`.

## Methods

| Method                                             | Description                                                          |
| -------------------------------------------------- | -------------------------------------------------------------------- |
| `list(params?)`                                    | List projects accessible to the authenticated user.                  |
| `get(id)`                                          | Get a project by ID with full details (sandbox, databases, storage). |
| `create(input)`                                    | Create a new project in an organization.                             |
| `delete(id)`                                       | Delete a project permanently.                                        |
| `deploy(id, input?)`                               | Trigger a deployment (production or preview).                        |
| `deployments(id, params?)`                         | List all deployments for a project.                                  |
| `deployment(projectId, deploymentId)`              | Get a specific deployment by ID.                                     |
| `deploymentLogs(projectId, deploymentId, params?)` | Get build/runtime logs for a deployment.                             |
| `executeCode(id, input)`                           | Execute code in the project's sandbox.                               |
| `sandbox(id)`                                      | Get the current sandbox status.                                      |
| `createSandbox(id)`                                | Start a new sandbox for the project.                                 |
| `stopSandbox(id)`                                  | Stop and clean up the project's sandbox.                             |

## List projects

```typescript
const { data: projects, meta } = await r.projects.list();

for (const project of projects) {
  console.log(`${project.name} (${project.slug})`);
}

// Filter by organization
const { data: orgProjects } = await r.projects.list({
  organization_id: 'org_123',
});
```

**Parameters:**

| Parameter         | Type      | Description               |
| ----------------- | --------- | ------------------------- |
| `organization_id` | `string?` | Filter by organization.   |
| `limit`           | `number?` | Max results (default 20). |
| `offset`          | `number?` | Pagination offset.        |

## Get a project

```typescript
const { data: project } = await r.projects.get('proj_123');

console.log(project.name);
console.log(project.slug);
console.log(project.repo_url);
console.log(project.sandbox?.status);       // 'running' | 'stopped' | ...
console.log(project.databases);              // [{ id, name, status }]
console.log(project.storage_buckets);        // [{ id, name }]
```

The detailed response includes sandbox status, provisioned databases, and storage buckets.

## Create a project

```typescript
const { data: project } = await r.projects.create({
  organization_id: 'org_123',
  name: 'My New App',
});

console.log(project.id);   // 'proj_abc...'
console.log(project.slug); // 'my-new-app' (auto-generated if not provided)
```

**Input fields:**

| Field                 | Type                     | Required | Description                                    |
| --------------------- | ------------------------ | -------- | ---------------------------------------------- |
| `organization_id`     | `string`                 | Yes      | The organization to create the project in.     |
| `name`                | `string`                 | Yes      | Project name.                                  |
| `slug`                | `string?`                | No       | URL slug. Auto-generated from name if omitted. |
| `repo_url`            | `string?`                | No       | GitHub repository URL to link.                 |
| `template_source`     | `'default' \| 'custom'?` | No       | Template type.                                 |
| `custom_template_url` | `string?`                | No       | URL to a custom project template.              |

## Delete a project

```typescript
const result = await r.projects.delete('proj_123');
console.log(result.data.deleted); // true
```

> **Warning**
>
> Deleting a project is permanent. All associated sandboxes, databases, storage buckets, and deployments will be destroyed.

## Sandbox management

Sandboxes are isolated development environments powered by E2B. Each project can have one active sandbox.

### Start a sandbox

```typescript
const { data: sandbox } = await r.projects.createSandbox('proj_123');

console.log(sandbox.id);
console.log(sandbox.status);  // 'starting' | 'running'
console.log(sandbox.message); // 'Sandbox started successfully'
```

### Check sandbox status

```typescript
const { data: status } = await r.projects.sandbox('proj_123');

console.log(status.status);    // 'running' | 'stopped' | 'error'
console.log(status.e2b_id);    // E2B sandbox ID
console.log(status.error);     // Error message if status === 'error'
```

### Stop a sandbox

```typescript
await r.projects.stopSandbox('proj_123');
```

### Execute code

Run code inside the project's sandbox. The sandbox must be running.

```typescript
const { data: result } = await r.projects.executeCode('proj_123', {
  code: `
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(JSON.stringify(data, null, 2));
  `,
  language: 'typescript',
});

console.log(result.output);        // stdout output
console.log(result.exitCode);      // 0 on success
console.log(result.executionTime); // milliseconds
```

**Supported languages:**

| Language   | Value                    |
| ---------- | ------------------------ |
| TypeScript | `'typescript'` (default) |
| JavaScript | `'javascript'`           |
| Python     | `'python'`               |

## Deployments

Deploys build from the project's **linked GitHub repository**. A project with no `repo_url` fails with `"Project has no linked repository. Push code to GitHub first."` Link a repo by passing `repo_url` to `projects.create` or `projects.update` — or scaffold one server-side with no GitHub account required:

```typescript
// Creates a repo from a Recursiv starter template ('nextjs' | 'expo')
// under the platform's GitHub owner. Requires the projects:write scope.
const { data: repo } = await r.github.createFromTemplate({
  template: 'nextjs',
  name: 'my-app',
});

const { data: project } = await r.projects.create({
  name: 'my-app',
  repo_url: repo.repo_url,
});
```

### Deploy to production

```typescript
const { data: deployment } = await r.projects.deploy('proj_123', {
  branch: 'main',
  type: 'production',
});

console.log(deployment.id);
console.log(deployment.status);         // 'queued' | 'building' | 'deploying' | 'live' | 'failed'
console.log(deployment.deployment_url); // Live URL once deployed
```

**Deploy input fields:**

| Field            | Type                        | Default        | Description                                |
| ---------------- | --------------------------- | -------------- | ------------------------------------------ |
| `type`           | `'production' \| 'preview'` | `'production'` | Deployment type.                           |
| `branch`         | `string?`                   | —              | Git branch to deploy.                      |
| `commit_hash`    | `string?`                   | —              | Specific commit to deploy.                 |
| `commit_message` | `string?`                   | —              | Commit message for the deployment record.  |
| `webhook_url`    | `string?`                   | —              | URL to receive deployment status webhooks. |

### Create a preview deployment

```typescript
const { data: preview } = await r.projects.deploy('proj_123', {
  branch: 'feature/new-ui',
  type: 'preview',
});

console.log(preview.deployment_url); // Unique preview URL
```

### List deployments

```typescript
const { data: deployments, meta } = await r.projects.deployments('proj_123');

for (const d of deployments) {
  console.log(`${d.id} — ${d.status} — ${d.deployment_url ?? 'pending'}`);
}
```

### Get a specific deployment

```typescript
const { data: deployment } = await r.projects.deployment('proj_123', 'deploy_456');

console.log(deployment.status);
console.log(deployment.branch);
console.log(deployment.commit_hash);
console.log(deployment.created_by?.name);
console.log(deployment.started_at);
console.log(deployment.completed_at);
```

### Get deployment logs

```typescript
const { data: logs } = await r.projects.deploymentLogs('proj_123', 'deploy_456');

console.log(logs.logs); // Build and runtime log output

// Limit log lines
const { data: recentLogs } = await r.projects.deploymentLogs('proj_123', 'deploy_456', {
  lines: 50,
});
```

## Complete workflow

Here is a full example: create a project, start a sandbox, execute code, deploy, and check logs.

```typescript
import { Recursiv } from '@recursiv/sdk';

const r = new Recursiv();

// 1. Create the project
const { data: project } = await r.projects.create({
  organization_id: 'org_123',
  name: 'Hello World App',
});
console.log('Created project:', project.id);

// 2. Start a sandbox
const { data: sandbox } = await r.projects.createSandbox(project.id);
console.log('Sandbox status:', sandbox.status);

// 3. Execute code in the sandbox
const { data: result } = await r.projects.executeCode(project.id, {
  code: 'console.log("Hello from Recursiv!")',
  language: 'typescript',
});
console.log('Output:', result.output); // "Hello from Recursiv!\n"

// 4. Deploy to production
const { data: deployment } = await r.projects.deploy(project.id, {
  type: 'production',
  commit_message: 'Initial deployment',
});
console.log('Deployment:', deployment.id, deployment.status);

// 5. Poll for deployment completion
let status = deployment.status;
while (status !== 'live' && status !== 'failed') {
  await new Promise((resolve) => setTimeout(resolve, 5000));
  const { data: updated } = await r.projects.deployment(project.id, deployment.id);
  status = updated.status;
  console.log('Status:', status);
}

// 6. Check deployment logs
const { data: logs } = await r.projects.deploymentLogs(project.id, deployment.id);
console.log('Logs:', logs.logs);

// 7. Clean up sandbox when done developing
await r.projects.stopSandbox(project.id);
```