upstash-box-js
bởi upstash
Làm việc với SDK TypeScript/JavaScript @upstash/box cho các container đám mây trong môi trường sandbox với AI agent, shell, hệ thống tệp và git. Sử dụng khi xây dựng với Upstash…
npx skills add https://github.com/upstash/skills --skill upstash-box-js@upstash/box SDK
Sandboxed cloud containers with built-in AI agents, shell, filesystem, and git.
Install & Setup
npm install @upstash/box
Set UPSTASH_BOX_API_KEY env var or pass apiKey to constructors.
Box Lifecycle
import { Box, Agent, ClaudeCode, BoxApiKey } from "@upstash/box"
// Create with agent + git + env vars
const box = await Box.create({
runtime: "node", // "node" | "python" | "golang" | "ruby" | "rust"
agent: {
harness: Agent.ClaudeCode, // Agent.Codex | Agent.OpenCode
model: ClaudeCode.Sonnet_4_5,
// apiKey options:
// omit → server decides which key to use
// BoxApiKey.UpstashKey → use Upstash-provided LLM key
// BoxApiKey.StoredKey → use key previously stored via Upstash Console
// "sk-..." → direct API key string
apiKey: BoxApiKey.UpstashKey,
},
git: { // all fields optional
token: process.env.GITHUB_TOKEN, // alternatively link your GitHub account via Upstash Console
userName: "Bot",
userEmail: "[email protected]",
},
env: { DATABASE_URL: "..." },
skills: ["upstash/qstash-js"], // GitHub repos as agent skills
})
// Reconnect, list, delete, pause/resume
const same = await Box.get(box.id)
const all = await Box.list()
await box.pause()
await box.resume()
await box.delete() // irreversible
const { status } = await box.getStatus()
Agent Runs
import { z } from "zod"
// Structured output with Zod schema
const run = await box.agent.run({
prompt: "Review the code for security issues",
responseSchema: z.object({
verdict: z.enum(["approved", "changes_requested"]),
findings: z.array(z.object({
severity: z.enum(["high", "medium", "low"]),
file: z.string(),
issue: z.string(),
})),
}),
timeout: 120_000,
maxRetries: 2,
onToolUse: (tool) => console.log(tool.name, tool.input),
})
run.status // "running" | "completed" | "failed" | "cancelled" | "detached"
run.result // typed from schema
run.cost // { inputTokens, outputTokens, computeMs, totalUsd }
// Streaming
const stream = await box.agent.stream({
prompt: "Build a REST API",
})
for await (const chunk of stream) { console.log(chunk) }
// Fire-and-forget with webhook
await box.agent.run({
prompt: "Run tests",
webhook: { url: "https://example.com/hook", headers: { Authorization: "Bearer ..." } },
})
Run Fields
Every run (agent, command, or code) returns a Run<T>:
const run = await box.exec.command("npm test")
run.id // run ID
run.status // "completed" | "failed" | ...
run.result // string output (or typed T with responseSchema)
run.exitCode // number | null (null for agent runs)
run.cost // { inputTokens, outputTokens, computeMs, totalUsd }
await run.cancel() // cancel a running run
const logs = await run.logs() // [{ timestamp, level, message }]
Shell Execution
// Run commands
const run = await box.exec.command("echo hello && ls -la")
// Run code snippets — lang: "js" | "ts" | "python"
const run2 = await box.exec.code({ code: "console.log(1+1)", lang: "js", timeout: 10_000 })
// Streaming shell
const stream = await box.exec.stream("npm run build")
for await (const chunk of stream) {
// chunk: { type: "output", data } | { type: "exit", exitCode, cpuNs }
}
Filesystem
await box.files.write({ path: "/workspace/home/app.js", content: "console.log('hi')" })
const content = await box.files.read("/workspace/home/app.js")
const entries = await box.files.list("/workspace/home") // [{ name, path, size, is_dir, mod_time }]
// Binary files — use encoding: "base64" for read and write
await box.files.write({ path: "/workspace/home/image.png", content: base64String, encoding: "base64" })
const b64 = await box.files.read("/workspace/home/image.png", { encoding: "base64" })
// Upload local files, download box files
await box.files.upload([{ path: "./local/file.txt", destination: "/workspace/home/file.txt" }])
await box.files.download({ folder: "./output" })
cd / Working Directory
The SDK tracks cwd client-side. All operations (exec, files, git, agent) run relative to it.
box.cwd // current working directory (starts at /workspace/home)
await box.cd("my-repo") // relative to current cwd
await box.cd("/workspace/home/other") // absolute path
Git
await box.git.clone({ repo: "github.com/org/repo", branch: "main" })
await box.cd("repo") // cd into cloned repo
const status = await box.git.status()
const diff = await box.git.diff()
const { sha } = await box.git.commit({ message: "fix: resolve bug" })
await box.git.push({ branch: "feature/fix" })
await box.git.checkout({ branch: "release/v2" })
const pr = await box.git.createPR({ title: "Fix bug", body: "...", base: "main" })
// pr: { url, number, title, base }
// Arbitrary git commands
const { output } = await box.git.exec({ args: ["log", "--oneline", "-5"] })
Snapshots & Fork
// Snapshot — checkpoint workspace state
const snap = await box.snapshot({ name: "after-setup" })
// snap: { id, name, box_id, size_bytes, status, created_at }
const restored = await Box.fromSnapshot(snap.id)
const snaps = await box.listSnapshots()
await box.deleteSnapshot(snap.id)
// Fork — clone live state into a new box
const forked = await box.fork()
EphemeralBox
Lightweight, short-lived boxes (max 3 days). No agent, git, snapshot, or fork. Supports exec, files, cd, and snapshots only.
import { EphemeralBox } from "@upstash/box"
const ebox = await EphemeralBox.create({
runtime: "python",
ttl: 3600, // seconds, max 259200 (3 days)
env: { API_KEY: "..." },
})
ebox.expiresAt // unix timestamp when auto-deleted
await ebox.exec.command("python -c 'print(1+1)'")
await ebox.exec.code({ code: "print('hi')", lang: "python" })
await ebox.files.write({ path: "/workspace/home/data.json", content: "{}" })
await ebox.cd("subdir")
await ebox.delete()
// Restore from snapshot
const ebox2 = await EphemeralBox.fromSnapshot(snap.id, { ttl: 7200 })
Public URLs
Expose box ports as public URLs with optional auth.
const publicURL = await box.getPublicURL(3000)
// publicURL: { url: "https://{id}-3000.preview.box.upstash.com", port }
const authed = await box.getPublicURL(3000, { bearerToken: true })
// authed: { url, port, token }
const basic = await box.getPublicURL(3000, { basicAuth: true })
// basic: { url, port, username, password }
const { publicURLs } = await box.listPublicURLs()
await box.deletePublicURL(3000)
MCP Servers
Attach MCP servers to the box agent.
const box = await Box.create({
agent: { harness: Agent.ClaudeCode, model: ClaudeCode.Sonnet_4_5 },
mcpServers: [
{ name: "fs", package: "@modelcontextprotocol/server-filesystem" },
{ name: "custom", url: "https://mcp.example.com/sse", headers: { Authorization: "..." } },
],
})
Gotchas
- Default working directory is
/workspace/home, not/homeor/ box.cd()is client-side tracking — it validates the path exists but doesn't change the box's shell cwd. All SDK methods use it automatically.EphemeralBoxdoes NOT supportagent,git,fork, or public URLs — use fullBoxfor thoserun.exitCodeisnullfor agent runs, only available for exec commandsbox.delete()is irreversible — snapshot first if you need the state- Git operations require
git.tokeninBoxConfigfor private repos and PRs Box.fromSnapshot()creates a new box — it does not modify the original
Thêm skills từ upstash
context7-cli
upstash
Sử dụng CLI ctx7 để tải tài liệu thư viện, quản lý kỹ năng lập trình AI và cấu hình Context7 MCP. Kích hoạt khi người dùng nhắc đến "ctx7" hoặc "context7",…
official
context7-mcp
upstash
Kỹ năng này nên được sử dụng khi người dùng hỏi về thư viện, framework, tài liệu tham khảo API hoặc cần ví dụ mã. Kích hoạt cho các câu hỏi về thiết lập, mã…
official
documentation-lookup
upstash
Kỹ năng này nên được sử dụng khi người dùng hỏi về thư viện, framework, tài liệu tham khảo API hoặc cần ví dụ mã. Kích hoạt cho các câu hỏi về thiết lập, mã…
official
find-docs
upstash
Truy xuất tài liệu hiện tại và ví dụ mã cho bất kỳ thư viện nào bằng CLI Context7.
official
context7-cli
upstash
Sử dụng CLI ctx7 để tải tài liệu thư viện, quản lý kỹ năng lập trình AI và cấu hình Context7 MCP. Kích hoạt khi người dùng đề cập đến "ctx7" hoặc "context7",…
official
context7-docs-lookup
upstash
Sử dụng Context7 để lấy tài liệu thư viện cập nhật. Kích hoạt khi người dùng hỏi về thư viện, framework, tham chiếu API, hoặc cần ví dụ mã —…
official
context7-mcp
upstash
Kỹ năng này nên được sử dụng khi người dùng hỏi về thư viện, framework, tài liệu tham khảo API hoặc cần ví dụ mã. Kích hoạt cho các câu hỏi thiết lập, mã…
official
ctx7-cli
upstash
Sử dụng CLI ctx7 để tải tài liệu thư viện, quản lý kỹ năng lập trình AI và cấu hình Context7 MCP. Kích hoạt khi người dùng đề cập đến "ctx7" hoặc "context7",…
official