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

# Commands

## Overview

The Commands resource provides two capabilities:

1. **Execute** -- Run AI-powered commands with context (current screen, organization, locale, attachments).
2. **Gate Prompt** -- Evaluate a conversation to determine if it should be allowed or blocked.

All command methods are available on `r.commands`.

## Methods

| Method              | Description                                                  |
| ------------------- | ------------------------------------------------------------ |
| `execute(input)`    | Execute an AI command with context and optional attachments. |
| `gatePrompt(input)` | Evaluate a conversation for access gating.                   |

## Execute a command

Send a natural language prompt to the AI with optional context about the current screen, organization, locale, and file attachments.

```typescript
const { data: result } = await r.commands.execute({
  prompt: 'Create a new project called "analytics-dashboard" and set up a database.',
  current_screen: '/dashboard/projects',
  org_slug: 'my-org',
  model: 'anthropic/claude-sonnet-4.6',
  locale: 'en',
});

console.log(result.text);    // Natural language response
console.log(result.actions); // Structured actions the AI wants to perform
```

**Input fields:**

| Field            | Type              | Required | Description                                                        |
| ---------------- | ----------------- | -------- | ------------------------------------------------------------------ |
| `prompt`         | `string`          | Yes      | The command or instruction to execute.                             |
| `current_screen` | `string?`         | No       | The current screen/route in the application (provides UI context). |
| `org_slug`       | `string \| null?` | No       | Organization slug for scoping the command.                         |
| `model`          | `string?`         | No       | AI model to use.                                                   |
| `locale`         | `string?`         | No       | Locale for the response (e.g., `'en'`, `'es'`, `'ja'`).            |
| `attachments`    | `Attachment[]?`   | No       | Files to include with the command.                                 |

**Attachment format:**

```typescript
interface Attachment {
  url: string;       // URL to the file
  mime?: string;     // MIME type (e.g., 'image/png')
  filename?: string; // Original filename
}
```

**Returns:** `SingleResponse<ExecutePromptResult>`

```typescript
interface ExecutePromptResult {
  text: string;                       // AI's natural language response
  actions: Record<string, unknown>[]; // Structured actions to perform
}
```

### Example with attachments

```typescript
const { data: result } = await r.commands.execute({
  prompt: 'Analyze this screenshot and suggest UI improvements.',
  attachments: [
    {
      url: 'https://storage.example.com/screenshot.png',
      mime: 'image/png',
      filename: 'dashboard-screenshot.png',
    },
  ],
});

console.log(result.text);
```

### Example with context

```typescript
const { data: result } = await r.commands.execute({
  prompt: 'What can I do from this screen?',
  current_screen: '/projects/proj_123/deployments',
  org_slug: 'acme-corp',
  locale: 'en',
});

console.log(result.text);
// "From the deployments screen, you can: 1. Trigger a new deployment..."
```

## Gate a prompt

The prompt gating endpoint evaluates a conversation to determine whether it should proceed. This is useful for implementing content moderation, access control, or guardrails for AI-powered features.

```typescript
const { data: result } = await r.commands.gatePrompt({
  messages: [
    { role: 'user', content: 'Help me write a Python script to analyze CSV data.' },
  ],
  model: 'anthropic/claude-sonnet-4.6',
});

console.log(result.approved); // true or false
console.log(result.reply);    // AI's explanation of the decision
```

**Input fields:**

| Field      | Type                  | Required | Description                     |
| ---------- | --------------------- | -------- | ------------------------------- |
| `messages` | `GatePromptMessage[]` | Yes      | The conversation to evaluate.   |
| `model`    | `string?`             | No       | AI model to use for evaluation. |

**Message format:**

```typescript
interface GatePromptMessage {
  role: 'user' | 'assistant';
  content: string;
}
```

**Returns:** `SingleResponse<GatePromptResult>`

```typescript
interface GatePromptResult {
  reply: string;     // The AI's response/explanation
  approved: boolean; // Whether the prompt is approved
}
```

### Example: content moderation

```typescript
async function moderateMessage(userMessage: string): Promise<boolean> {
  const { data: gate } = await r.commands.gatePrompt({
    messages: [
      { role: 'user', content: userMessage },
    ],
  });

  if (!gate.approved) {
    console.log('Message blocked:', gate.reply);
    return false;
  }

  return true;
}

// Usage
const allowed = await moderateMessage('Help me build a REST API');
if (allowed) {
  // Proceed with the command
  const { data: result } = await r.commands.execute({
    prompt: 'Help me build a REST API',
  });
  console.log(result.text);
}
```

### Example: multi-turn gating

```typescript
const conversation = [
  { role: 'user' as const, content: 'I want to deploy my app.' },
  { role: 'assistant' as const, content: 'Sure! Which project would you like to deploy?' },
  { role: 'user' as const, content: 'The analytics dashboard, to production.' },
];

const { data: gate } = await r.commands.gatePrompt({
  messages: conversation,
});

if (gate.approved) {
  const { data: result } = await r.commands.execute({
    prompt: conversation[conversation.length - 1].content,
    current_screen: '/projects/analytics-dashboard',
  });
  console.log(result.text);
  console.log(result.actions);
}
```