> ## Documentation Index
> Fetch the complete documentation index at: https://agent.minimax.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript SDK

> Drive local MiniMax Code from Node.js with @minimax-ai/code-sdk.

If you already use MiniMax Code through the CLI, an editor integration, or headless `mcode exec`, you can also control it from application code with the TypeScript SDK.

Use the SDK when you need to:

* Automate fixes, reviews, or code generation in CI/CD;
* Embed MiniMax Code in internal tools or your own agents;
* Orchestrate multi-turn Sessions from code instead of hand-written `mcode exec` pipelines.

The SDK drives the local CLI with `mcode exec --output-format stream-json`: one `run()` / `runStreamed()` call is one CLI process and one Turn. Phase 1 (`0.x`) may change APIs between minor versions until `1.0`.

Related pages: [Headless and CI](https://agent.minimax.io/docs/cli/automation.md), [Python SDK](https://agent.minimax.io/docs/cli/sdk-python.md). Package: [npm `@minimax-ai/code-sdk`](https://www.npmjs.com/package/@minimax-ai/code-sdk).

## Requirements

| Component | Requirement |
| - | - |
| Node.js | `>=22.19 <23` or `>=24.2 <27` |
| MiniMax Code CLI (`mcode`) | `>=0.6.3` (`MIN_CLI_VERSION`) |
| Event `schemaVersion` | `1` |

The SDK and CLI ship separately. Upgrading the SDK does not require a CLI upgrade as long as the CLI meets `MIN_CLI_VERSION`. Sign in or configure a working API-key provider in the data directory before the first run.

## Installation

```bash theme={null}
npm install @minimax-ai/code-sdk
npm install @minimax-ai/code   # optional; a globally installed mcode works too
```

`@minimax-ai/code` is an optional peer dependency and runs install scripts for native modules. npm 11 rejects `--allow-scripts` for project-scoped installs (`EALLOWSCRIPTS`), so approve them in the project's `package.json` first:

```json theme={null}
{
  "allowScripts": {
    "@minimax-ai/code": true,
    "better-sqlite3": true
  }
}
```

## Quick start

Create a client, start a Thread, and run a prompt:

```ts theme={null}
import { MCode } from "@minimax-ai/code-sdk";

const mcode = new MCode({ dataDir: "/srv/mcode-data" });
const thread = mcode.startThread({
  cwd: "/path/to/repo",
  model: "minimax/MiniMax-M3",
  permission: "smart",
});

const turn = await thread.run("Diagnose and fix the failing CI job", {
  files: ["./ci.log"],
  timeoutMs: 10 * 60_000,
});
console.log(thread.id, turn.finalResponse, turn.usage);

// Continue on the same Thread
await thread.run("Add unit tests for the fix");

// Resume an earlier Session
const resumed = mcode.resumeThread("mvs_xxx", { cwd: "/path/to/repo" });
await resumed.run("Continue where you left off");
```

Stream events:

```ts theme={null}
const { events } = await thread.runStreamed("Implement the plan");
for await (const event of events) {
  switch (event.type) {
    case "item.completed":
      console.log(event.item);
      break;
    case "turn.failed":
      console.error(event.status, event.error);
      break;
    default:
      // Newer CLIs may add event types; the SDK passes them through unchanged.
      break;
  }
}
```

## CLI resolution

The SDK does not hard-depend on the CLI. Lookup order:

1. The `bin` constructor option (executable, JS entry, or command name on `PATH`);
2. An installed `@minimax-ai/code` next to the SDK (optional peer);
3. `mcode` on `PATH`.

`resolveFromCwd` defaults to `false`. Set it to `true` to also search the host working directory after the SDK-local package and before `PATH`. Leave it off for untrusted checkouts (for example CI pull-request jobs); pass `bin`, or install the CLI next to the SDK or on `PATH`.

Before the first run, each `MCode` instance runs `mcode --version` once and caches the result. A CLI older than `0.6.3` fails with `MCodeVersionError`. Only `major.minor.patch` is compared, so `0.6.3-preview.N` satisfies the minimum.

## `new MCode(options?)`

| Option | Description |
| - | - |
| `bin` | Explicit `mcode` path or command name; skips package and `PATH` lookup |
| `resolveFromCwd` | Also search `process.cwd()` for the CLI; default `false` |
| `dataDir` | Data directory, passed to the CLI as `MINIMAX_DATA_DIR` |
| `env` | Child process environment. **Replaces** `process.env` when set; defaults to `process.env` |
| `configPath` | Runtime config file, passed as `--config` |

`env` replaces the environment entirely. Passing only custom variables drops `PATH`, `HOME`, and similar values. To add variables, spread `process.env`:

```ts theme={null}
const mcode = new MCode({ env: { ...process.env, FOO: "bar" } });
```

## Threads: `startThread` / `resumeThread`

Thread options are passed to the CLI on every Turn of that Thread:

| Option | CLI flag |
| - | - |
| `cwd` | `--cwd` (defaults to the host process working directory) |
| `model` / `effort` | `--model` / `--effort` |
| `permission` | `--permission`: `smart` / `full` / `off` |
| `mode` | `--mode`: `standard` / `lightweight`; only on the Turn that creates the Session |
| `promptMode` | `--prompt-mode`: `tui` / `coding` / `work` |
| `systemPrompt` | `--system-prompt-file` (the SDK writes a temporary file) |
| `appendSystemPrompt` | `--append-system-prompt-file` (the SDK writes a temporary file) |

Notes:

* `mode: "lightweight"` is only valid for a new Thread; passing it to `resumeThread` throws `MCodeInvocationError` immediately;
* There is no `ask` permission for headless runs. MiniMax Code's `smart` / `full` / `off` policies are not equivalent to Codex OS sandbox modes, and the SDK does not map between them;
* `thread.id` becomes available once the first Turn emits its first event, even if that Turn fails.

## `thread.run` / `thread.runStreamed`

| Option | Description |
| - | - |
| `files` | Attachments (`--file`, repeatable); relative paths resolve against `cwd` |
| `signal` | `AbortSignal` used for cancellation |
| `timeoutMs` | Passed to the CLI as `--timeout <n>ms`; the SDK force-stops at `timeoutMs + 90s` |
| `maxSteps` | `--max-steps` |

Behavior:

* `run()` resolves only when the status is `succeeded`, with a `Turn` (`finalResponse`, normalized `items`, `usage`, `model`, `sessionId`, `turnId`, `durationMs`, and the full `result`). Every other outcome rejects;
* `runStreamed()` yields CLI events unchanged. `turn.failed` is an ordinary event; the iterator throws only for process or protocol failures. Breaking out of the loop cancels the Turn;
* A Thread runs one Turn at a time. A concurrent call throws `ThreadBusyError`; Turns are not queued.

## Events and items

Event types match the CLI: `exec.started`, `session.started` / `session.resumed`, `turn.started`, `item.started` / `item.updated` / `item.completed`, `turn.completed`, `turn.failed`, and `exec.completed`. Every stdout line must be JSON with `schemaVersion === 1`; anything else is a protocol error.

`Turn.items` are SDK-normalized items: `agent_message`, `reasoning`, and `tool_call`. Items merge by `item.id` in first-appearance order. Items without `item.completed` when the Turn ends are marked `incomplete: true`.

`usage.totalTokens = inputTokens + outputTokens` and **excludes** `cacheReadTokens` / `cacheWriteTokens`; `reasoningTokens` may overlap `outputTokens`.

## Errors

Every error extends `MCodeError` and carries `exitCode`, `signal`, and the last 64 KiB of CLI stderr (`stderr`, diagnostics only).

Common classes:

| Error | Typical cause |
| - | - |
| `MCodeInvocationError` | An option the SDK rejects before starting the CLI, or CLI exit code `2` |
| `MCodeRunError` | Task failure / timeout / limit exceeded; may include `status`, `category`, `result`, `retryable`, `sessionId` |
| `MCodeAbortError` | Cancellation (`AbortSignal`, breaking a streamed iterator, or exit code `130`) |
| `MCodeProtocolError` | Non-JSON stdout, missing fields, broken pipe, and similar protocol issues |
| `MCodeNotFoundError` | No CLI found, or a launcher whose JS entry cannot be determined |
| `MCodeVersionError` | CLI older than `MIN_CLI_VERSION`, or an unsupported event `schemaVersion` |
| `ThreadBusyError` | Concurrent Turn on the same Thread |

The SDK never retries automatically, to avoid replaying writes with unknown outcomes. When an error includes `sessionId`, call `resumeThread(error.sessionId)` to continue.

## Cancellation and timeouts

* When `signal` aborts, the SDK sends `SIGTERM`. The CLI cancels and shuts down (up to about 60 seconds); after that budget the SDK sends `SIGKILL`;
* `timeoutMs` is enforced by the CLI after access checks, session resolution, and model selection. The SDK starts its timer at spawn and force-stops at `timeoutMs + 90s`;
* On a normal host exit, the SDK sends `SIGTERM` to any running CLI and deletes temporary system-prompt directories. A host killed by a signal does not emit `exit`, so child processes may remain. Phase 1 has no `close()` / `dispose()`;
* On Windows, Node.js cannot deliver a catchable signal to a child process, so `SIGTERM` is a hard kill.

Abort in-flight Turns from your own signal handlers when you need reliable cleanup:

```ts theme={null}
const controller = new AbortController();
process.once("SIGTERM", () => controller.abort());
await thread
  .run(prompt, { signal: controller.signal })
  .catch(() => undefined);
```

Concurrent `exec` processes that share one data directory have had limited testing. Prefer a separate `dataDir` per SDK instance (or concurrent task), with authentication configured in that directory beforehand.

## Not available in Phase 1

* `outputSchema` (structured-output constraints);
* Approval callbacks, steering a running Turn, continuing after an interrupt, and forking.

For direct CLI usage or structured output, see [Headless and CI](https://agent.minimax.io/docs/cli/automation.md).
