SDK Reference
Programmatic reference for Tenki Sandbox covering installation, authentication, client options, identity discovery, OpenCode integration, and error types.
Tenki Sandbox provides two official SDKs:
- Go SDK:
github.com/TenkiCloud/tenki-sdk-go/sandbox - TypeScript SDK: published as
@tenki/sandbox
Both SDKs wrap the same public service contract (tenki.sandbox.v1), so you get identical functionality regardless of which language you choose.
Install
Go
go get github.com/TenkiCloud/tenki-sdk-go/sandboxTypeScript
npm install @tenki/sandboxAuthenticate
Token forms
The service accepts three token forms:
- API key: sent as
Authorization: Bearer <token>when the token starts withtk_ - Ory session token: sent as
X-Session-Tokenwhen the token starts withory_st_ - browser session token: sent as
Cookie: ory_kratos_session=<token>otherwise
For most external integrations, use an API key.
Resolution order
Go SDK: WithAuthToken() > TENKI_API_KEY env var > error.
TypeScript SDK: options.authToken > TENKI_AUTH_TOKEN env var > TENKI_API_KEY env var.
Base URL: WithBaseURL() / options.baseUrl > TENKI_API_URL env var > https://api.tenki.cloud.
Create a client
Go
import tenkisandbox "github.com/TenkiCloud/tenki-sdk-go/sandbox"
// Zero-config: reads TENKI_API_KEY and TENKI_API_URL.
client, err := tenkisandbox.New()
// Explicit:
client, err := tenkisandbox.New(
tenkisandbox.WithAuthToken("tk_your_api_key"),
tenkisandbox.WithBaseURL("https://api.example.com"),
)
defer client.Close()Useful client options:
| Option | Description | Default |
|---|---|---|
WithAuthToken(token) | API authentication token | TENKI_API_KEY env |
WithBaseURL(url) | Sandbox service endpoint | https://api.tenki.cloud |
WithHTTPTimeout(d) | HTTP timeout | 30s |
WithHTTPClient(c) | Custom *http.Client | auto-created |
WithConnectClientOptions(...) | Additional Connect client options | none |
TypeScript
import { TenkiSandbox } from "@tenki/sandbox";
const sandbox = new TenkiSandbox(); // env-driven
// Or explicit:
const sandbox = new TenkiSandbox({
authToken: "tk_...",
baseUrl: "https://api.tenki.cloud",
});Defaults
Defaults applied by Create when you do not override them:
inbound:falseoutbound:truecpu:2memory:4096 MB
Validation: cpu_cores 1..16, memory_mb 512..65536, volume size 1 MiB to 100 GiB.
Identity and workspaces
Use WhoAmI to discover the authenticated owner and visible workspaces. Many APIs (volumes, templates) require a workspace ID.
identity, err := client.WhoAmI(ctx)
fmt.Printf("owner: %s/%s\n", identity.OwnerType, identity.OwnerID)
for _, ws := range identity.Workspaces {
fmt.Printf("workspace: %s (%s)\n", ws.Name, ws.ID)
}OpenCode integration
Sessions can run OpenCode inside the VM for AI-driven workflows. Enable it with WithOpenCode(true) at create time, or pass WithOpenCodeProvider(...) to wire in your provider keys.
Single run
result, err := session.OpenCode.Run(
ctx,
"Review this repository and summarize risks.",
tenkisandbox.WithModel("anthropic/claude-sonnet-4-5"),
tenkisandbox.WithTimeout(5*time.Minute),
tenkisandbox.WithOnEvent(func(ev tenkisandbox.Event) {
log.Printf("[%s] %s", ev.Type, ev.Data)
}),
)const run = await session.openCode.run("Fix the failing tests", {
model: "claude-sonnet-4-20250514",
onEvent: (e) => console.log(`[${e.type}] ${e.data}`),
});
console.log(`Cost: $${run.totalCost}`);Long-lived instance
Start an OpenCode instance once and run many prompts against it:
instance, err := session.OpenCode.StartInstance(
ctx,
tenkisandbox.WithInstanceWorkDir("/workspace/repo"),
tenkisandbox.WithInstanceModel("anthropic/claude-sonnet-4-5"),
)
result, err := instance.Run(ctx, "Fix the failing tests")const instance = await session.openCode.startInstance({
workDir: "/workspace",
model: "claude-sonnet-4-20250514",
});
const result = await instance.run("Add unit tests");Abort the active OpenCode session:
err = session.OpenCode.Abort(ctx)Git helpers
The SDK exposes structured Git operations on a session.
out, err := session.Git.Clone(ctx, "https://github.com/octocat/Hello-World.git", tenkisandbox.GitCloneParams{
Directory: "/workspace/repo",
Depth: 1,
})
out, err = session.Git.Checkout(ctx, "main", tenkisandbox.GitCheckoutParams{})
out, err = session.Git.FetchPR(ctx, 123, tenkisandbox.GitFetchPRParams{
Directory: "/workspace/repo",
})await session.git.clone("https://github.com/org/repo", { depth: 1 });
await session.git.checkout({ branch: "feature" });
const diff = await session.git.diff({});
const log = await session.git.log({ maxCount: 10 });
await session.git.fetchPR({ remote: "origin", prNumber: 42 });You can also inject a GitHub token at session create time with WithGitHubToken(token) so private clones work without provisioning credentials inside the guest.
Timeout constants (Go)
DefaultSessionCreateTimeoutDefaultSnapshotCreateTimeoutDefaultRestoreTimeoutDefaultExecTimeout
Size constants (TypeScript)
import { GB, GiB, KB, KiB, MB, MiB, TB, TiB } from "@tenki/sandbox";
const tenGiB = 10 * GiB;The Go SDK exposes the same scale factors (tenkisandbox.GB, MiB, etc.).
Errors
The Go SDK maps service errors to typed values. Common ones:
| Error | Meaning |
|---|---|
ErrSessionNotFound | session ID is unknown |
ErrSessionExpired | session passed its MaxDuration |
ErrSessionTerminated | session is TERMINATED |
ErrInvalidState | operation invalid for current state |
ErrCommandTimeout | exec exceeded its timeout |
ErrUnauthorized | bad/missing auth token |
ErrPermissionDenied | authorized but lacks permission |
ErrQuotaExceeded | workspace hit a resource quota |
ErrPortLimitExceeded | too many exposed ports on this session |
ErrInboundDisabled | inbound network not enabled |
ErrSSHUnavailable | SSH endpoint not ready |
ErrRateLimited | back off and retry |
ErrVolumeNotFound | volume ID is unknown |
ErrVolumeInUse | volume already attached |
ErrVolumeLimitExceeded | workspace volume quota |
ErrSnapshotNotFound | snapshot ID is unknown |
ErrSnapshotFailed | snapshot creation failed |
ErrTemplateNotFound | template ID is unknown |
ErrTemplateExists | template name conflict |
ErrTemplateBuildNotFound | build ID is unknown |
ErrTemplateBuildFailed | build failed; see error/log_tail |
ErrTemplateBuildInProgress | build still running |
if errors.Is(err, tenkisandbox.ErrTemplateBuildInProgress) {
// retry later
}The TypeScript SDK exposes equivalent typed errors that all extend SandboxError:
import { CommandTimeoutError, QuotaExceededError, SessionNotFoundError } from "@tenki/sandbox";
try {
await session.exec("sleep", { args: ["999"], timeoutMs: 1000 });
} catch (err) {
if (err instanceof CommandTimeoutError) {
console.log("Command timed out");
}
}Advanced API surface
The public service contract also exposes lower-level RPCs that the convenience SDKs don't wrap:
GetArtifactUploadUrl,GetArtifactDownloadUrl: used for full template build log artifactsListWorkspaceSandboxesPauseSession,ResumeSession: present in the protobuf, not always wrapped, may not be available in every deployment
If you need them, integrate directly with the protocol:
proto/tenki/sandbox/v1/sandbox.proto