Code
Run interpreter-style code snippets, keep state in Code Contexts, stream Code Run events, and promote rich outputs with the TypeScript SDK.
client.code runs Python, JavaScript, or TypeScript snippets inside a live
Sandbox. A SandboxHandle exposes the same helpers as
sandbox.code.*, so most code can stay sandbox-scoped instead of passing
the Sandbox id repeatedly.
Use Commands for top-level process records and shell commands. Use Code Runs for notebook-style snippets, stateful interpreter work, rich outputs, and streamed execution events. Code Runs are not durable resources; export files or promote outputs to Artifacts when you need persistence.
Default language
The TypeScript SDK defaults Code Contexts and Code Runs to python when you omit
language. Pass javascript or typescript when you want those interpreters.
run
Run a snippet and wait for the result.
run(
sandboxId: `sbx_${string}`,
input: RunCodeInput,
): Promise<RunCodeResult>RunCodeInput:
| Field | Type | Default | Description |
|---|---|---|---|
code | string | required | Source to execute, capped at 256 KiB. |
language | "python" | "javascript" | "typescript" | "python" | Interpreter language. |
contextId | `cctx_${string}` | SDK-created | Existing Code Context to reuse. |
cwd | string | /workspace | Working directory inside the Workspace. |
timeoutMs | number | 60000 | Code Run timeout in milliseconds, maximum 600000. |
artifactPolicy | "inline_only" | "promote" | inline_only | Whether artifact-capable rich outputs should be promoted to Artifacts. |
idempotencyKey | string | SDK-generated | Idempotency key with a 24-hour retry window for the completed Code Run. |
const result = await sandbox.code.run({
code: `
total = sum([10, 20, 12])
print(f"total={total}")
total
`,
});
for (const chunk of result.stdout) process.stdout.write(chunk);
console.log(result.outputs);RunCodeResult includes sandboxId, contextId, language,
executionCount, stdout, stderr, outputs, optional truncation flags,
optional error, and durationMs.
Code Contexts
A Code Context keeps language state inside one Sandbox. Use it when values, imports, or loaded data should persist across runs.
createContext(
sandboxId: `sbx_${string}`,
input?: CreateCodeContextInput,
): Promise<CodeContextRef>
listContexts(sandboxId: `sbx_${string}`): Promise<readonly CodeContextRef[]>
getContext(
sandboxId: `sbx_${string}`,
contextId: `cctx_${string}`,
): Promise<CodeContextRef>const context = await sandbox.code.createContext({ language: "python" });
const contexts = await sandbox.code.listContexts();
const sameContext = await sandbox.code.getContext(context.id);
await sandbox.code.run({
contextId: context.id,
code: "import math\nradius = 4",
});
const result = await sandbox.code.run({
contextId: context.id,
code: "print(math.pi * radius ** 2)",
});
console.log(result.stdout.join(""));
await sandbox.code.deleteContext(context.id);CreateCodeContextInput accepts language, cwd, timeoutMs, and
idempotencyKey. Context creation defaults to /workspace and a 30000 ms
context timeout, with a maximum of 600000 ms. Deleting a context is
best-effort against the provider, but CrowNest metadata is authoritative.
If you omit contextId from run, CrowNest lazily creates or reuses one
default Code Context for the Sandbox and language. The result always returns
the contextId that was used.
Rich outputs
Code Runs return outputs rather than forcing everything through stdout.
Each output is one of:
| Kind | Description |
|---|---|
inline | Small text, markdown, JSON, data, chart, or LaTeX value in the response. |
artifact | Promoted output stored as an Artifact, with artifactId and content type. |
rejected | Output CrowNest could not inline or promote, with a stable rejection reason. |
Use artifactPolicy: "promote" when code may produce images, HTML, SVG,
or larger structured results that should survive after the Sandbox is gone.
Promotion requires the artifact:create scope.
import { writeFile } from "node:fs/promises";
const result = await sandbox.code.run({
artifactPolicy: "promote",
code: `
import matplotlib.pyplot as plt
plt.figure()
plt.plot([1, 2, 3], [2, 5, 4])
plt.title("Weekly score")
plt.show()
`,
});
const image = result.outputs.find(
(output) => output.kind === "artifact" && output.format === "png",
);
if (image?.kind === "artifact") {
const bytes = await client.artifacts.download(image.artifactId);
await writeFile("weekly-score.png", bytes);
}Inline output is capped, and total inline output is capped across one Code
Run. Large or unsafe outputs may be rejected with reasons such as
output_too_large, requires_artifact_promotion, or
unsafe_active_content.
runStream
Stream interpreter events as the Code Run executes.
runStream(
sandboxId: `sbx_${string}`,
input: RunCodeInput,
): AsyncIterable<CodeRunEvent>CodeRunEvent:
| Event | Shape |
|---|---|
stdout | { type: "stdout", data: string } |
stderr | { type: "stderr", data: string } |
output | { type: "output", data: CodeOutput } |
error | { type: "error", data: CodeExecutionError } |
complete | { type: "complete", data: RunCodeResult } |
let finalResult;
for await (const event of sandbox.code.runStream({
code: `
import time
for idx in range(3):
print(f"step {idx}")
time.sleep(0.2)
`,
})) {
if (event.type === "stdout") process.stdout.write(event.data);
if (event.type === "stderr") process.stderr.write(event.data);
if (event.type === "error") {
console.error(event.data.message);
}
if (event.type === "complete") {
finalResult = event.data;
}
}
console.log(finalResult?.executionCount);Stream replay is result-only in v1. Reusing a completed idempotency key
emits a single complete event with the stored result.
Execution errors
Interpreter failures are part of the Code Run result, not SDK transport
errors. A Python exception resolves normally with result.error, and may
also appear as a streaming error event.
const result = await sandbox.code.run({ code: "1 / 0" });
if (result.error) {
console.error(result.error.name);
console.error(result.error.message);
console.error(result.error.traceback?.join("\n"));
}API-level failures still throw CrowNestApiError, for example
forbidden, not_found, sandbox_destroyed, code_source_too_large,
unsupported_code_language, or quota_exceeded.
JavaScript and TypeScript
Pass language when you do not want Python.
const js = await sandbox.code.run({
language: "javascript",
code: "console.log(JSON.stringify({ ok: true }))",
});
const ts = await sandbox.code.run({
language: "typescript",
code: "const answer: number = 42; console.log(answer)",
});Code Contexts are language-specific. Keep separate contexts if you switch between Python, JavaScript, and TypeScript in the same Sandbox.
Next steps
- Code concept - how Code Contexts and Code Runs fit the resource model.
- Commands - run top-level processes and stream logs.
- Artifacts - persist rich outputs.
- Code API reference