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

# Build a Code Playground

Set up a sandbox, AI coding assistant, and deploy pipeline using the SDK.

## Prerequisites

* Node.js >= 18
* A Recursiv API key with scopes: `projects:read`, `projects:write`, `agents:read`, `agents:write`
* Your Organization ID

## Install

```bash
npm install @recursiv/sdk
```

## Set up environment

```bash
export RECURSIV_API_KEY=sk_live_xxx
export RECURSIV_ORG_ID=your-org-id
```

## The code

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

const r = new Recursiv()
const ORG_ID = process.env.RECURSIV_ORG_ID!

async function main() {
  // 1. Create a project
  const { data: project } = await r.projects.create({
    name: 'code-playground',
    organization_id: ORG_ID,
  })
  console.log('Project:', project.id)

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

  // 3. Create an AI coding assistant
  const { data: agent } = await r.agents.create({
    name: 'Code Assistant',
    username: 'coder_' + Date.now(),
    model: 'anthropic/claude-sonnet-4.6',
    system_prompt: `You are a coding assistant. When the user asks you to write code,
respond with working TypeScript code. Be concise.`,
    tool_mode: 'autonomous',
    organization_id: ORG_ID,
  })

  // 4. Ask the agent to write code
  process.stdout.write('Agent: ')
  let generatedCode = ''
  for await (const chunk of r.agents.chatStream(agent.id, {
    message: 'Write a function that checks if a string is a palindrome',
  })) {
    const text = chunk.delta ?? ''
    process.stdout.write(text)
    generatedCode += text
  }
  console.log('\n')

  // 5. Execute code in the sandbox
  const { data: result } = await r.projects.executeCode(project.id, {
    code: `
      function isPalindrome(s: string): boolean {
        const cleaned = s.toLowerCase().replace(/[^a-z0-9]/g, '');
        return cleaned === cleaned.split('').reverse().join('');
      }
      console.log(isPalindrome('racecar'));  // true
      console.log(isPalindrome('hello'));    // false
      console.log(isPalindrome('A man a plan a canal Panama')); // true
    `,
    language: 'typescript',
  })
  console.log('Output:', result.output)

  // 6. Deploy to production
  const { data: deployment } = await r.projects.deploy(project.id, {
    branch: 'main',
    type: 'production',
  })
  console.log('Deployed:', deployment.id)

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

  // 8. Clean up sandbox when done
  await r.projects.stopSandbox(project.id)
}

main()
```

## What just happened

You built the core flow of a code playground:

* A project with an isolated sandbox environment
* An AI assistant that generates code on demand
* Code execution with output capture
* One-call deploy to production
* Log monitoring

## Anonymous sandbox

For public-facing playgrounds where users don't need an account:

```typescript
const r = new Recursiv({ anonymous: true })

const { data } = await r.sandbox.execute({
  code: 'console.log("Hello from the sandbox!")',
  language: 'typescript',
})
console.log(data.output)
// Rate-limited: 10 executions/day per IP
```

## Next steps

* Add a database with `r.databases.ensure()` for persisting user projects
* Give the agent project access with `r.agents.grantProjectAccess()`
* Add file storage with `r.storage.ensureBucket()` for saving code files
* Track project tasks with `r.projectBrain.tasks()`