Documentation
¶
Overview ¶
Package wrenn is the official Go client for the Wrenn API.
Wrenn runs AI coding agents inside persistent, isolated microVMs called capsules. This SDK covers the endpoints reachable with a team API key (the "wrn_" key created from the dashboard): capsule lifecycle, command execution, filesystem access, process management, metrics, snapshots, and external storage volumes (Client.CreateVolume, attached to a capsule via CreateCapsuleParams.VolumeIDs). It also opens interactive terminals (Capsule.Pty), wraps the git binary inside a capsule (Capsule.Git), and builds proxied URLs for services running inside a capsule (Capsule.URL). Stateful code execution in a persistent Jupyter kernel lives in the coderunner subpackage.
Getting started ¶
client, err := wrenn.New(wrenn.WithAPIKey("wrn_..."))
if err != nil {
log.Fatal(err)
}
cap, err := client.CreateCapsule(ctx, wrenn.CreateCapsuleParams{
Template: "minimal-ubuntu",
})
if err != nil {
log.Fatal(err)
}
if err := cap.WaitForStatus(ctx, wrenn.StatusRunning); err != nil {
log.Fatal(err)
}
res, err := cap.Exec(ctx, wrenn.ExecParams{Cmd: "echo", Args: []string{"hi"}})
fmt.Println(string(res.Stdout))
Authentication ¶
Every request carries the team API key in the X-API-Key header. The key is read from WithAPIKey or the WRENN_API_KEY environment variable; the base URL and proxy domain fall back to WRENN_BASE_URL and WRENN_PROXY_DOMAIN. Keys are scoped to a single team; all capsules and snapshots you create or read are that team's. Capsule.ExecStream is receive-only; for a bidirectional terminal (keystrokes, resize, byte-faithful output) use Capsule.Pty.
Errors ¶
Failed API calls return an *APIError carrying the server error code, message, and request ID. Use IsNotFound, IsConflict, and friends, or inspect APIError.Code directly, to branch on specific failures.
Example ¶
package main
import (
"context"
"fmt"
"log"
wrenn "github.com/wrennhq/go-sdk"
)
func main() {
client, err := wrenn.New(wrenn.WithAPIKey("wrn_your_team_key"))
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Create a capsule and wait for it to boot.
cap, err := client.CreateCapsule(ctx, wrenn.CreateCapsuleParams{
Template: "minimal-ubuntu",
})
if err != nil {
log.Fatal(err)
}
defer func() { _ = cap.Destroy(ctx) }()
if err := cap.WaitForStatus(ctx, wrenn.StatusRunning); err != nil {
log.Fatal(err)
}
// Run a command.
res, err := cap.Exec(ctx, wrenn.ExecParams{Cmd: "echo", Args: []string{"hello"}})
if err != nil {
log.Fatal(err)
}
fmt.Printf("exit=%d out=%s", res.ExitCode, res.Stdout)
}
Output:
Index ¶
- Constants
- func IsConflict(err error) bool
- func IsGitAuthError(err error) bool
- func IsNotFound(err error) bool
- func IsNotRunning(err error) bool
- func IsUnauthorized(err error) bool
- func IsVolumeInUse(err error) bool
- type APIError
- type BackgroundProcess
- type Capsule
- func (cap *Capsule) AttachProcess(ctx context.Context, selector string) (<-chan StreamEvent, error)
- func (cap *Capsule) Destroy(ctx context.Context) error
- func (cap *Capsule) Exec(ctx context.Context, params ExecParams) (*ExecResult, error)
- func (cap *Capsule) ExecStream(ctx context.Context, params ExecStreamParams) (<-chan StreamEvent, error)
- func (cap *Capsule) Exists(ctx context.Context, p string) (bool, error)
- func (cap *Capsule) Git() *Git
- func (cap *Capsule) KillProcess(ctx context.Context, selector string, sig Signal) error
- func (cap *Capsule) ListDir(ctx context.Context, path string, depth uint32) ([]FileEntry, error)
- func (cap *Capsule) ListProcesses(ctx context.Context) ([]Process, error)
- func (cap *Capsule) MakeDir(ctx context.Context, path string) (*FileEntry, error)
- func (cap *Capsule) Metrics(ctx context.Context, rangeTier string) (*Metrics, error)
- func (cap *Capsule) Pause(ctx context.Context) error
- func (cap *Capsule) Ping(ctx context.Context) error
- func (cap *Capsule) Pty(ctx context.Context, params PtyParams) (*PtySession, error)
- func (cap *Capsule) PtyConnect(ctx context.Context, tag string) (*PtySession, error)
- func (cap *Capsule) ReadFile(ctx context.Context, path string) ([]byte, error)
- func (cap *Capsule) ReadFileStream(ctx context.Context, path string) (io.ReadCloser, error)
- func (cap *Capsule) Refresh(ctx context.Context) error
- func (cap *Capsule) Remove(ctx context.Context, path string) error
- func (cap *Capsule) Resume(ctx context.Context) error
- func (cap *Capsule) StartBackground(ctx context.Context, params StartBackgroundParams) (*BackgroundProcess, error)
- func (cap *Capsule) URL(port int) string
- func (cap *Capsule) WaitForStatus(ctx context.Context, target string) error
- func (cap *Capsule) WriteFile(ctx context.Context, path string, content []byte) error
- func (cap *Capsule) WriteFileFrom(ctx context.Context, path string, r io.Reader) error
- type Client
- func (c *Client) AuthorizedRequest(ctx context.Context, method, absURL string, body io.Reader) (*http.Request, error)
- func (c *Client) Capsule(id string) *Capsule
- func (c *Client) CreateCapsule(ctx context.Context, params CreateCapsuleParams) (*Capsule, error)
- func (c *Client) CreateSnapshot(ctx context.Context, capsuleID, name string) (*Capsule, error)
- func (c *Client) CreateVolume(ctx context.Context, params CreateVolumeParams) (*Volume, error)
- func (c *Client) DeleteSnapshot(ctx context.Context, name string) error
- func (c *Client) DeleteVolume(ctx context.Context, ref string) error
- func (c *Client) DialProxyWS(ctx context.Context, absURL string) (*websocket.Conn, error)
- func (c *Client) DialWS(ctx context.Context, absURL string) (*websocket.Conn, error)
- func (c *Client) GetCapsule(ctx context.Context, id string) (*Capsule, error)
- func (c *Client) GetVolume(ctx context.Context, ref string) (*Volume, error)
- func (c *Client) HTTPClient() *http.Client
- func (c *Client) ListCapsules(ctx context.Context) ([]*Capsule, error)
- func (c *Client) ListSnapshots(ctx context.Context, params ListSnapshotsParams) (*SnapshotList, error)
- func (c *Client) ListVolumes(ctx context.Context) ([]*Volume, error)
- func (c *Client) ProxyRequest(ctx context.Context, method, absURL string, body io.Reader) (*http.Request, error)
- func (c *Client) ProxyURL(capsuleID string, port int, websocket bool) string
- func (c *Client) RenameSnapshot(ctx context.Context, name, newName string) error
- func (c *Client) SetSnapshotVisibility(ctx context.Context, name string, public bool) error
- func (c *Client) Stats(ctx context.Context, rangeParam string) (*Stats, error)
- func (c *Client) Usage(ctx context.Context, from, to string) (*Usage, error)
- type CreateCapsuleParams
- type CreateVolumeParams
- type ExecParams
- type ExecResult
- type ExecStreamParams
- type FileEntry
- type FileStatus
- type Git
- func (g *Git) Add(ctx context.Context, p GitAddParams) (*ExecResult, error)
- func (g *Git) Branches(ctx context.Context, opts GitOptions) ([]GitBranch, error)
- func (g *Git) CheckoutBranch(ctx context.Context, name string, opts GitOptions) (*ExecResult, error)
- func (g *Git) Clone(ctx context.Context, p GitCloneParams) (*ExecResult, error)
- func (g *Git) Commit(ctx context.Context, message string, p GitCommitParams) (*ExecResult, error)
- func (g *Git) ConfigureUser(ctx context.Context, name, email string, p GitConfigParams) error
- func (g *Git) CreateBranch(ctx context.Context, name string, p GitCreateBranchParams) (*ExecResult, error)
- func (g *Git) CreateTag(ctx context.Context, name string, p GitTagParams) (*ExecResult, error)
- func (g *Git) CurrentBranch(ctx context.Context, opts GitOptions) (string, error)
- func (g *Git) DangerouslyAuthenticate(ctx context.Context, p GitAuthenticateParams) error
- func (g *Git) DeleteBranch(ctx context.Context, name string, p GitDeleteBranchParams) (*ExecResult, error)
- func (g *Git) DeleteTag(ctx context.Context, name string, opts GitOptions) (*ExecResult, error)
- func (g *Git) Diff(ctx context.Context, p GitDiffParams) (string, error)
- func (g *Git) Fetch(ctx context.Context, p GitFetchParams) (*ExecResult, error)
- func (g *Git) GetConfig(ctx context.Context, key string, p GitConfigParams) (string, error)
- func (g *Git) Init(ctx context.Context, p GitInitParams) (*ExecResult, error)
- func (g *Git) Log(ctx context.Context, p GitLogParams) ([]GitCommit, error)
- func (g *Git) Merge(ctx context.Context, p GitMergeParams) (*ExecResult, error)
- func (g *Git) Pull(ctx context.Context, p GitPullParams) (*ExecResult, error)
- func (g *Git) Push(ctx context.Context, p GitPushParams) (*ExecResult, error)
- func (g *Git) RemoteAdd(ctx context.Context, name, remoteURL string, p GitRemoteAddParams) (*ExecResult, error)
- func (g *Git) RemoteGet(ctx context.Context, name string, opts GitOptions) (string, error)
- func (g *Git) Reset(ctx context.Context, p GitResetParams) (*ExecResult, error)
- func (g *Git) Restore(ctx context.Context, paths []string, p GitRestoreParams) (*ExecResult, error)
- func (g *Git) SetConfig(ctx context.Context, key, value string, p GitConfigParams) (*ExecResult, error)
- func (g *Git) Show(ctx context.Context, object string, p GitShowParams) (string, error)
- func (g *Git) StashList(ctx context.Context, opts GitOptions) ([]GitStashEntry, error)
- func (g *Git) StashPop(ctx context.Context, p GitStashPopParams) (*ExecResult, error)
- func (g *Git) StashSave(ctx context.Context, p GitStashSaveParams) (*ExecResult, error)
- func (g *Git) Status(ctx context.Context, opts GitOptions) (*GitStatus, error)
- func (g *Git) Tags(ctx context.Context, opts GitOptions) ([]string, error)
- type GitAddParams
- type GitAuthenticateParams
- type GitBranch
- type GitCloneParams
- type GitCommit
- type GitCommitParams
- type GitConfigParams
- type GitCreateBranchParams
- type GitDeleteBranchParams
- type GitDiffParams
- type GitError
- type GitFetchParams
- type GitInitParams
- type GitLogParams
- type GitMergeParams
- type GitOptions
- type GitPullParams
- type GitPushParams
- type GitRemoteAddParams
- type GitResetParams
- type GitRestoreParams
- type GitShowParams
- type GitStashEntry
- type GitStashPopParams
- type GitStashSaveParams
- type GitStatus
- type GitTagParams
- type ListSnapshotsParams
- type MetricPoint
- type Metrics
- type Option
- type Process
- type PtyEvent
- type PtyEventType
- type PtyParams
- type PtySession
- type Signal
- type Snapshot
- type SnapshotList
- type StartBackgroundParams
- type Stats
- type StatsCurrent
- type StatsPeaks
- type StatsSeries
- type StreamEvent
- type StreamEventType
- type Usage
- type UsagePoint
- type Volume
Examples ¶
Constants ¶
const ( StatusPending = "pending" StatusStarting = "starting" StatusRunning = "running" StatusPausing = "pausing" StatusPaused = "paused" StatusSnapshotting = "snapshotting" StatusResuming = "resuming" StatusStopping = "stopping" StatusHibernated = "hibernated" StatusStopped = "stopped" StatusMissing = "missing" StatusError = "error" )
Capsule status values. The set mirrors the server's status enum, including the transient states (pausing, snapshotting, resuming, stopping) a capsule reports mid-transition and the terminal "missing" state. Status is a plain string, so unknown future values still decode.
const ( CodeInvalidRequest = "invalid_request" CodeValidationFailed = "validation_failed" CodeAuthSessionRequired = "auth_session_required" CodeForbidden = "forbidden" CodeNotFound = "not_found" CodeSandboxNotFound = "sandbox_not_found" CodeSandboxNotRunning = "sandbox_not_running" CodeTemplateNotFound = "template_not_found" CodeTemplateProtected = "template_protected" CodeConflict = "conflict" CodePayloadTooLarge = "payload_too_large" CodeHostUnreachable = "host_unreachable" CodeInternal = "internal_error" // Storage volume codes. All but CodeVolumeNotFound are 409 conflicts, so // [IsConflict] reports true for them. CodeVolumeNotFound = "volume_not_found" CodeVolumeInUse = "volume_in_use" CodeVolumeHostMismatch = "volume_host_mismatch" CodeVolumeNameTaken = "volume_name_taken" CodeVolumesAttached = "volumes_attached" )
Well-known error codes returned by the Wrenn API in APIError.Code. The list is not exhaustive — always be prepared to handle codes not enumerated here.
const ( VolumeStatusDetached = "detached" VolumeStatusAttaching = "attaching" VolumeStatusAttached = "attached" VolumeStatusDeleting = "deleting" )
Volume status values. A volume is "detached" (free to attach or delete), "attaching" (reserved by a booting capsule), "attached" (in use), or "deleting" (a delete is in flight; reverts to detached if it fails). Status is a plain string, so unknown future values still decode.
const DefaultBaseURL = "https://app.wrenn.dev/api"
DefaultBaseURL is used when no base URL is supplied via WithBaseURL or the WRENN_BASE_URL environment variable.
const DefaultProxyDomain = "wrenn.dev"
DefaultProxyDomain is the host used to build capsule proxy URLs (see Capsule.URL) when the client talks to the default hosted deployment.
const Version = "0.2.0"
Version is the semantic version of this SDK. It is reported in the User-Agent header on every request (see WithUserAgent to override).
Keep this in sync with the git tag used to publish the module: tagging a release as vX.Y.Z is what `go get` resolves, and this constant should match.
Variables ¶
This section is empty.
Functions ¶
func IsConflict ¶
IsConflict reports whether err is a conflict: the generic "conflict" code (e.g. a snapshot that could not be removed from every host) or one of the volume conflicts — still attached, name already taken, volumes pinned to different hosts, or volumes attached when snapshotting.
func IsGitAuthError ¶
IsGitAuthError reports whether err is a *GitError caused by an authentication failure against a remote.
func IsNotFound ¶
IsNotFound reports whether err is a not-found error (capsule, template, volume, or generic 404). It unwraps wrapped errors.
func IsNotRunning ¶
IsNotRunning reports whether err indicates the capsule was not in the running state required by the operation.
func IsUnauthorized ¶
IsUnauthorized reports whether err indicates a missing or invalid API key. It unwraps wrapped errors.
func IsVolumeInUse ¶ added in v0.2.0
IsVolumeInUse reports whether err indicates the volume is still attached to a capsule. Destroy the capsule before deleting the volume.
Types ¶
type APIError ¶
type APIError struct {
// StatusCode is the HTTP status of the response.
StatusCode int
// Code is the stable, machine-readable error code (see the Code* constants).
Code string
// Message is a human-readable description safe to show to users.
Message string
// RequestID identifies the request in server logs; quote it in bug reports.
RequestID string
// Retryable is true when the same request may succeed if retried later.
Retryable bool
// Details carries optional structured context (e.g. the offending field).
Details map[string]any
}
APIError is a structured error returned by the Wrenn API. It mirrors the server error envelope: {"error": {"code", "message", "request_id", ...}}.
type BackgroundProcess ¶
type BackgroundProcess struct {
// PID is the process ID inside the guest.
PID uint32 `json:"pid"`
// Tag is a stable handle for the process, usable as a selector in
// [Capsule.KillProcess] and [Capsule.AttachProcess].
Tag string `json:"tag"`
// Cmd is the command that was started.
Cmd string `json:"cmd"`
}
BackgroundProcess identifies a process started with Capsule.StartBackground.
type Capsule ¶
type Capsule struct {
ID string `json:"id"`
Status string `json:"status"`
Template string `json:"template"`
VCPUs int32 `json:"vcpus"`
MemoryMB int32 `json:"memory_mb"`
TimeoutSec int32 `json:"timeout_sec"`
DiskSizeMB int32 `json:"disk_size_mb"`
DiskUsedMB *int64 `json:"disk_used_mb,omitempty"`
CreatedAt string `json:"created_at"`
StartedAt *string `json:"started_at,omitempty"`
LastActiveAt *string `json:"last_active_at,omitempty"`
LastUpdated string `json:"last_updated"`
Metadata map[string]string `json:"metadata,omitempty"`
// contains filtered or unexported fields
}
Capsule is a handle to a Wrenn capsule (an isolated microVM). Fields describe the capsule as of the last create/get/refresh; per-capsule operations are methods. A Capsule is bound to the Client that produced it.
func (*Capsule) AttachProcess ¶
AttachProcess streams the output of an already-running process (identified by PID or tag) as a receive-only channel of StreamEvent. This is the background-process counterpart to Capsule.ExecStream: attach to a process started with Capsule.StartBackground and follow its output.
Cancel ctx to detach. The channel closes when the process exits. The capsule must be running.
func (*Capsule) Destroy ¶
Destroy permanently deletes the capsule. The call is accepted asynchronously.
func (*Capsule) Exec ¶
func (cap *Capsule) Exec(ctx context.Context, params ExecParams) (*ExecResult, error)
Exec runs a command to completion inside the capsule and returns its output. The capsule must be running.
func (*Capsule) ExecStream ¶
func (cap *Capsule) ExecStream(ctx context.Context, params ExecStreamParams) (<-chan StreamEvent, error)
ExecStream runs a command and streams its output back as a receive-only channel of StreamEvent. The stream is receive-only: there is no interactive input. Events arrive in order — a single EventStart, any number of EventStdout/EventStderr, then a terminating EventExit (or EventError). The channel is closed when the process ends.
Cancel ctx to stop the stream early. The capsule must be running.
events, err := cap.ExecStream(ctx, wrenn.ExecStreamParams{Cmd: "npm", Args: []string{"test"}})
if err != nil {
return err
}
for ev := range events {
switch ev.Type {
case wrenn.EventStdout:
fmt.Print(ev.Data)
case wrenn.EventExit:
fmt.Println("exit", ev.ExitCode)
}
}
Example ¶
package main
import (
"context"
"fmt"
"log"
wrenn "github.com/wrennhq/go-sdk"
)
func main() {
client, _ := wrenn.New(wrenn.WithAPIKey("wrn_your_team_key"))
cap := client.Capsule("cl-...")
ctx := context.Background()
events, err := cap.ExecStream(ctx, wrenn.ExecStreamParams{
Cmd: "sh",
Args: []string{"-c", "for i in 1 2 3; do echo $i; sleep 1; done"},
})
if err != nil {
log.Fatal(err)
}
for ev := range events {
switch ev.Type {
case wrenn.EventStdout:
fmt.Print(ev.Data)
case wrenn.EventExit:
fmt.Println("exited with", ev.ExitCode)
}
}
}
Output:
func (*Capsule) Exists ¶
Exists reports whether path exists inside the capsule. It lists the parent directory and checks for a matching entry, so a missing parent (or a missing path) returns false without an error. The capsule must be running.
func (*Capsule) KillProcess ¶
KillProcess sends sig to the process identified by selector, which may be a numeric PID or a tag. An empty sig defaults to SIGKILL. The capsule must be running.
func (*Capsule) ListDir ¶
ListDir lists directory entries at path. Depth controls recursion (0 or 1 for a single level). The capsule must be running.
func (*Capsule) ListProcesses ¶
ListProcesses returns the processes tracked inside the capsule. The capsule must be running.
func (*Capsule) MakeDir ¶
MakeDir creates the directory at path, creating parent directories as needed, and returns its entry. It is not idempotent: if the path already exists it returns a conflict error (see IsConflict). The capsule must be running.
func (*Capsule) Metrics ¶
Metrics returns resource-usage samples for the capsule. rangeTier is one of "5m", "10m", "1h", "2h", "6h", "12h", "24h"; an empty value defaults to "10m". Available while the capsule is running or paused.
func (*Capsule) Pause ¶
Pause snapshots and suspends the capsule, freeing host resources. The updated capsule state is applied in place.
func (*Capsule) Ping ¶
Ping refreshes the capsule's activity timer, deferring the inactivity timeout. Returns an error unless the capsule is running.
func (*Capsule) Pty ¶
Pty opens an interactive pseudo-terminal in the capsule and returns a live PtySession. The capsule must be running. Cancel ctx or call PtySession.Close to end the session.
func (*Capsule) PtyConnect ¶
PtyConnect reattaches to an existing terminal identified by tag (the Tag from a prior PtyEventStarted). Output resumes from the live terminal; there is no fresh PtyEventStarted on reconnect. The capsule must be running.
func (*Capsule) ReadFile ¶
ReadFile reads the file at path and returns its full contents. For large files, use Capsule.ReadFileStream to avoid buffering. The capsule must be running.
func (*Capsule) ReadFileStream ¶
ReadFileStream opens the file at path for streaming reads. The caller must close the returned reader. The capsule must be running.
func (*Capsule) Resume ¶
Resume restores a paused or hibernated capsule back to running. The updated capsule state is applied in place.
func (*Capsule) StartBackground ¶
func (cap *Capsule) StartBackground(ctx context.Context, params StartBackgroundParams) (*BackgroundProcess, error)
StartBackground launches a long-running process and returns immediately. Its output can be streamed later with Capsule.AttachProcess using the returned PID or tag. The capsule must be running.
func (*Capsule) URL ¶
URL returns the HTTP(S) URL that reaches a port exposed inside this capsule. For a WebSocket endpoint, use Client.ProxyURL with websocket set to true.
The URL points into the untrusted guest; reach it with Client.ProxyRequest (see the security note on Client.ProxyURL), never with the team API key.
func (*Capsule) WaitForStatus ¶
WaitForStatus polls the capsule until its status equals target, then returns. It returns early with an error if the capsule enters the "error" state (when that is not the target) or if ctx is cancelled. The capsule's fields are kept up to date as it polls.
func (*Capsule) WriteFile ¶
WriteFile writes content to path inside the capsule, buffering the whole payload in memory. For large or streamed inputs use Capsule.WriteFileFrom. The capsule must be running.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a Wrenn API client scoped to a single team API key. It is safe for concurrent use by multiple goroutines.
func New ¶
New constructs a Client. An API key is required, supplied via WithAPIKey or the WRENN_API_KEY environment variable. The base URL and proxy domain fall back to WRENN_BASE_URL and WRENN_PROXY_DOMAIN when their options are omitted. Explicit options always take precedence over environment variables.
func (*Client) AuthorizedRequest ¶
func (c *Client) AuthorizedRequest(ctx context.Context, method, absURL string, body io.Reader) (*http.Request, error)
AuthorizedRequest builds an HTTP request to an absolute URL with the client's team API key and User-Agent headers set. Use it to call the Wrenn API itself or a trusted self-hosted endpoint.
Security: never point this at a capsule proxy URL (Capsule.URL / Client.ProxyURL). Those URLs terminate inside the untrusted guest VM, so the X-API-Key header would be delivered there in clear text and readable by any process in the capsule. The proxy needs no authentication — use Client.ProxyRequest, which sends no key, for in-capsule services.
func (*Client) Capsule ¶
Capsule returns a handle to an existing capsule by ID without making a request. Use it to run operations against a capsule you already know. Call Capsule.Refresh to populate its metadata.
func (*Client) CreateCapsule ¶
CreateCapsule provisions a new capsule. Creation is asynchronous: the returned Capsule typically starts in a pending/starting state. Use Capsule.WaitForStatus to block until it is running.
func (*Client) CreateSnapshot ¶
CreateSnapshot captures a running or paused capsule as a new template. The call is asynchronous: the capsule briefly pauses and resumes while the snapshot is registered in the background. The returned Capsule reflects the capsule's transitional state.
func (*Client) CreateVolume ¶ added in v0.2.0
CreateVolume provisions a new detached storage volume. Attach it to a capsule with CreateCapsuleParams.VolumeIDs.
It fails with a conflict (see IsConflict) if the team already has a volume with this name.
func (*Client) DeleteSnapshot ¶
DeleteSnapshot removes a snapshot the team owns. It fails with a conflict (see IsConflict) if any host holding the files is offline. Platform and protected templates cannot be deleted.
func (*Client) DeleteVolume ¶ added in v0.2.0
DeleteVolume permanently deletes a volume and its data. The volume must be detached: destroy any capsule using it first, or the call fails with IsVolumeInUse. Accepts an ID or a name.
func (*Client) DialProxyWS ¶
DialProxyWS opens a WebSocket connection to an absolute ws:// or wss:// URL WITHOUT the team API key (only the User-Agent is set). Combine it with Client.ProxyURL to reach a WebSocket service running inside a capsule; the proxy is authenticated by the unguessable capsule hostname, not the key.
func (*Client) DialWS ¶
DialWS opens a WebSocket connection to an absolute ws:// or wss:// URL with the client's team API key and User-Agent headers set. Use it for the Wrenn API or a trusted self-hosted endpoint.
Security: never point this at a capsule proxy URL (Client.ProxyURL with websocket true). The connection terminates inside the untrusted guest VM, so the X-API-Key header would be readable by any process in the capsule. Use Client.DialProxyWS, which sends no key, for in-capsule WebSocket services.
func (*Client) GetCapsule ¶
GetCapsule fetches a capsule by ID.
func (*Client) GetVolume ¶ added in v0.2.0
GetVolume looks up a volume by ID ("vol-…") or by name ("vl-cache", or plain "cache" — the "vl-" prefix is optional). The two namespaces cannot collide, since an ID always carries the "vol-" prefix.
func (*Client) HTTPClient ¶
HTTPClient returns the underlying *http.Client used for API requests. Pair it with Client.ProxyRequest to call an HTTP service running inside a capsule (see Capsule.URL), or with Client.AuthorizedRequest to call the Wrenn API or a trusted self-hosted endpoint.
func (*Client) ListCapsules ¶
ListCapsules returns all capsules owned by the team.
func (*Client) ListSnapshots ¶
func (c *Client) ListSnapshots(ctx context.Context, params ListSnapshotsParams) (*SnapshotList, error)
ListSnapshots returns one page of templates the team may launch.
func (*Client) ListVolumes ¶ added in v0.2.0
ListVolumes returns all storage volumes owned by the team, newest first.
func (*Client) ProxyRequest ¶
func (c *Client) ProxyRequest(ctx context.Context, method, absURL string, body io.Reader) (*http.Request, error)
ProxyRequest builds an HTTP request to an absolute URL WITHOUT the team API key; only the User-Agent header is set. Combine it with Client.HTTPClient and Capsule.URL to reach an HTTP service running inside a capsule. The proxy is authenticated by the unguessable capsule hostname, not the key, so the key must never enter the guest.
func (*Client) ProxyURL ¶
ProxyURL returns the URL that reaches a port exposed inside the capsule with the given ID. Wrenn publishes in-capsule ports at {port}-{capsuleID}.{proxyDomain}; the control plane reverse-proxies requests whose Host header matches that pattern through to the guest. When websocket is true the ws:// or wss:// scheme is used, otherwise http:// or https://.
The proxied endpoint needs no separate authentication — the capsule-scoped hostname is unguessable — so the returned URL can be handed to any HTTP or WebSocket client.
Security: this URL terminates inside the untrusted guest VM. Never attach the team API key to it (do not use Client.AuthorizedRequest or Client.DialWS) — the X-API-Key header would be delivered into the capsule and readable by any process there, and the proxy ignores it anyway. Use Client.ProxyRequest or Client.DialProxyWS, which send no key.
func (*Client) RenameSnapshot ¶
RenameSnapshot renames a snapshot the team owns. Renaming unpublishes it. Platform and protected templates cannot be renamed.
func (*Client) SetSnapshotVisibility ¶
SetSnapshotVisibility publishes or unpublishes a snapshot the team owns. Published snapshots are launchable by other teams as "<team-slug>/<name>".
type CreateCapsuleParams ¶
type CreateCapsuleParams struct {
// Template is the base image or snapshot name to launch (e.g.
// "minimal-ubuntu"). Foreign public templates use "<team-slug>/<name>".
Template string `json:"template,omitempty"`
// VCPUs is the number of virtual CPUs.
VCPUs int32 `json:"vcpus,omitempty"`
// MemoryMB is the guest memory in megabytes.
MemoryMB int32 `json:"memory_mb,omitempty"`
// TimeoutSec is the inactivity timeout after which the capsule is
// auto-destroyed. Zero uses the server default.
TimeoutSec int32 `json:"timeout_sec,omitempty"`
// Metadata is arbitrary key/value data stored with the capsule.
Metadata map[string]string `json:"metadata,omitempty"`
// VolumeIDs are external storage volumes to attach at boot, each given as a
// volume ID ("vol-…") or a name ("vl-cache"). Each is mounted at
// /mnt/<volume-id> inside the guest; read the exact path from
// [Volume.MountPath] once the capsule is running. At most four per capsule,
// and each volume must be detached and owned by the team.
//
// Volumes can only be attached at create time. If a volume is already pinned
// to a host the capsule is scheduled onto that host, so attaching volumes
// pinned to different hosts fails (see [IsConflict]). Not supported for
// capsules created from a snapshot template.
VolumeIDs []string `json:"volume_ids,omitempty"`
}
CreateCapsuleParams are the options for Client.CreateCapsule. Zero-valued resource fields fall back to server defaults.
type CreateVolumeParams ¶ added in v0.2.0
type CreateVolumeParams struct {
// Name is optional and unique within the team. Lowercase letters, numbers,
// and dashes only (no leading, trailing, or repeated dashes), at most 40
// characters including the "vl-" prefix. The prefix is added if omitted, so
// "cache" and "vl-cache" name the same volume. Leave it empty and the volume
// is named after its own ID.
Name string `json:"name,omitempty"`
// Size is the human-readable size with a G/Gi/M/Mi suffix ("20Gi", "500M");
// a bare number is read as megabytes. Fixed at creation.
Size string `json:"size,omitempty"`
// SizeMB is the size in megabytes, as an alternative to Size. The minimum is
// 100; the maximum is set per deployment (20Gi by default).
SizeMB int32 `json:"size_mb,omitempty"`
}
CreateVolumeParams are the options for Client.CreateVolume. Supply the size as either Size or SizeMB; Size wins if both are set.
type ExecParams ¶
type ExecParams struct {
// Cmd is the executable to run. Required.
Cmd string `json:"cmd"`
// Args are the command arguments.
Args []string `json:"args,omitempty"`
// TimeoutSec bounds the command's run time. Zero uses the server default.
TimeoutSec int32 `json:"timeout_sec,omitempty"`
// Envs are additional environment variables for the command.
Envs map[string]string `json:"envs,omitempty"`
// Cwd is the working directory to run the command in.
Cwd string `json:"cwd,omitempty"`
}
ExecParams configures a synchronous command execution via Capsule.Exec.
type ExecResult ¶
ExecResult is the outcome of a synchronous Capsule.Exec. Stdout and Stderr are returned as raw bytes; the SDK transparently decodes the server's base64 encoding when the output is not valid UTF-8.
type ExecStreamParams ¶
type ExecStreamParams struct {
// Cmd is the executable to run. Required.
Cmd string
// Args are the command arguments.
Args []string
}
ExecStreamParams configures a streaming command execution.
type FileEntry ¶
type FileEntry struct {
Name string `json:"name"`
Path string `json:"path"`
Type string `json:"type"` // "file", "directory", "symlink", ...
Size int64 `json:"size"`
Mode uint32 `json:"mode"`
Permissions string `json:"permissions"`
Owner string `json:"owner"`
Group string `json:"group"`
ModifiedAt int64 `json:"modified_at"` // unix seconds
SymlinkTarget *string `json:"symlink_target,omitempty"`
}
FileEntry describes a filesystem entry returned by Capsule.ListDir and Capsule.MakeDir.
type FileStatus ¶
type FileStatus struct {
// Path is the file path relative to the repository root.
Path string
// IndexStatus is the staged (index) status character.
IndexStatus string
// WorkTreeStatus is the working-tree status character.
WorkTreeStatus string
// RenamedFrom is the original path when the change is a rename.
RenamedFrom string
}
FileStatus is one entry from git status --porcelain=v1.
func (FileStatus) Staged ¶
func (f FileStatus) Staged() bool
Staged reports whether the change is staged in the index.
func (FileStatus) Status ¶
func (f FileStatus) Status() string
Status is a normalized label: conflict, renamed, copied, deleted, added, modified, typechange, untracked, or unknown.
type Git ¶
type Git struct {
// contains filtered or unexported fields
}
Git is a handle to git operations inside a capsule, obtained from Capsule.Git. Every method runs the real git binary in the guest through Capsule.Exec, so git must be installed in the capsule's image. Commands that exit non-zero return a *GitError; use IsGitAuthError to detect authentication failures.
func (*Git) Add ¶
func (g *Git) Add(ctx context.Context, p GitAddParams) (*ExecResult, error)
Add stages files for commit.
func (*Git) CheckoutBranch ¶
func (g *Git) CheckoutBranch(ctx context.Context, name string, opts GitOptions) (*ExecResult, error)
CheckoutBranch checks out an existing branch.
func (*Git) Clone ¶
func (g *Git) Clone(ctx context.Context, p GitCloneParams) (*ExecResult, error)
Clone clones a remote repository into the capsule. When Username and Password are set they are embedded for the clone and then stripped from the origin remote unless DangerouslyStoreCredentials is true.
func (*Git) Commit ¶
func (g *Git) Commit(ctx context.Context, message string, p GitCommitParams) (*ExecResult, error)
Commit creates a commit with the given message.
func (*Git) ConfigureUser ¶
ConfigureUser sets the git user.name and user.email. Scope defaults to "global".
func (*Git) CreateBranch ¶
func (g *Git) CreateBranch(ctx context.Context, name string, p GitCreateBranchParams) (*ExecResult, error)
CreateBranch creates and checks out a new branch.
func (*Git) CreateTag ¶
func (g *Git) CreateTag(ctx context.Context, name string, p GitTagParams) (*ExecResult, error)
CreateTag creates a tag. With a Message it is annotated, otherwise lightweight.
func (*Git) CurrentBranch ¶
CurrentBranch returns the checked-out branch name, or "" when HEAD is detached (rather than an error).
func (*Git) DangerouslyAuthenticate ¶
func (g *Git) DangerouslyAuthenticate(ctx context.Context, p GitAuthenticateParams) error
DangerouslyAuthenticate persists git credentials via the credential store.
The credentials are written in plain text to the capsule filesystem and are readable by any process in the capsule. Prefer the per-operation Username and Password fields on Git.Clone, Git.Push, and Git.Pull instead.
func (*Git) DeleteBranch ¶
func (g *Git) DeleteBranch(ctx context.Context, name string, p GitDeleteBranchParams) (*ExecResult, error)
DeleteBranch deletes a branch.
func (*Git) DeleteTag ¶
func (g *Git) DeleteTag(ctx context.Context, name string, opts GitOptions) (*ExecResult, error)
DeleteTag deletes a tag.
func (*Git) Fetch ¶
func (g *Git) Fetch(ctx context.Context, p GitFetchParams) (*ExecResult, error)
Fetch downloads objects and refs from a remote without merging them.
func (*Git) GetConfig ¶
GetConfig returns a git config value, or "" if the key is not set (rather than an error).
func (*Git) Init ¶
func (g *Git) Init(ctx context.Context, p GitInitParams) (*ExecResult, error)
Init initializes a new git repository.
func (*Git) Merge ¶
func (g *Git) Merge(ctx context.Context, p GitMergeParams) (*ExecResult, error)
Merge merges Ref into the current branch, or aborts an in-progress merge.
func (*Git) Pull ¶
func (g *Git) Pull(ctx context.Context, p GitPullParams) (*ExecResult, error)
Pull pulls changes from a remote.
func (*Git) Push ¶
func (g *Git) Push(ctx context.Context, p GitPushParams) (*ExecResult, error)
Push pushes commits to a remote.
func (*Git) RemoteAdd ¶
func (g *Git) RemoteAdd(ctx context.Context, name, remoteURL string, p GitRemoteAddParams) (*ExecResult, error)
RemoteAdd adds a remote.
func (*Git) RemoteGet ¶
RemoteGet returns the URL of a remote, or "" if the remote does not exist (rather than an error). An empty name defaults to "origin".
func (*Git) Reset ¶
func (g *Git) Reset(ctx context.Context, p GitResetParams) (*ExecResult, error)
Reset resets the current HEAD.
func (*Git) Restore ¶
func (g *Git) Restore(ctx context.Context, paths []string, p GitRestoreParams) (*ExecResult, error)
Restore restores working-tree files or unstages changes.
func (*Git) SetConfig ¶
func (g *Git) SetConfig(ctx context.Context, key, value string, p GitConfigParams) (*ExecResult, error)
SetConfig sets a git config value. For local scope, Cwd should be the repository root.
func (*Git) Show ¶
Show returns `git show` output for an object (commit, tag, blob). An empty object shows HEAD.
func (*Git) StashList ¶
func (g *Git) StashList(ctx context.Context, opts GitOptions) ([]GitStashEntry, error)
StashList lists the stash entries, newest first.
func (*Git) StashPop ¶
func (g *Git) StashPop(ctx context.Context, p GitStashPopParams) (*ExecResult, error)
StashPop applies and removes a stash entry.
func (*Git) StashSave ¶
func (g *Git) StashSave(ctx context.Context, p GitStashSaveParams) (*ExecResult, error)
StashSave pushes the working-tree changes onto the stash.
type GitAddParams ¶
type GitAddParams struct {
// Paths are specific files to stage; empty stages the current directory
// (or everything with All).
Paths []string
// All stages all changes including untracked files.
All bool
GitOptions
}
GitAddParams configures Git.Add.
type GitAuthenticateParams ¶
type GitAuthenticateParams struct {
// Username and Password are the git credentials. Required.
Username string
Password string
// Host defaults to "github.com".
Host string
// Protocol defaults to "https".
Protocol string
GitOptions
}
GitAuthenticateParams configures Git.DangerouslyAuthenticate.
type GitBranch ¶
type GitBranch struct {
// Name is the short branch name.
Name string
// IsCurrent reports whether this is the checked-out branch.
IsCurrent bool
}
GitBranch is a single local branch entry.
type GitCloneParams ¶
type GitCloneParams struct {
// URL is the remote repository URL. Required.
URL string
// Dest is the destination path; defaults to the repo name from the URL.
Dest string
// Branch checks out a specific branch or tag after cloning.
Branch string
// SingleBranch restricts the clone to just Branch (or the remote's default
// when Branch is empty). Off by default; a shallow Depth clone already
// narrows to one branch as git normally does.
SingleBranch bool
// Depth creates a shallow clone with this many commits.
Depth int
// Username and Password authenticate HTTP(S) clones. Password requires
// Username.
Username string
Password string
// DangerouslyStoreCredentials leaves credentials embedded in the origin
// remote URL after cloning. Off by default: credentials are stripped.
DangerouslyStoreCredentials bool
GitOptions
}
GitCloneParams configures Git.Clone.
type GitCommit ¶
type GitCommit struct {
// Hash is the full commit SHA.
Hash string
// ShortHash is the abbreviated SHA.
ShortHash string
// AuthorName and AuthorEmail identify the author.
AuthorName string
AuthorEmail string
// Date is the author date in strict ISO 8601 (e.g. 2026-07-19T12:00:00+00:00).
Date string
// Subject is the first line of the commit message.
Subject string
// Body is the remainder of the commit message (may be empty).
Body string
}
GitCommit is one entry from Git.Log.
type GitCommitParams ¶
type GitCommitParams struct {
// AllowEmpty allows creating a commit with no changes.
AllowEmpty bool
// AuthorName and AuthorEmail override the commit author.
AuthorName string
AuthorEmail string
GitOptions
}
GitCommitParams configures Git.Commit.
type GitConfigParams ¶
type GitConfigParams struct {
// Scope is one of "local", "global", or "system". [Git.SetConfig] and
// [Git.GetConfig] default to "local"; [Git.ConfigureUser] to "global".
Scope string
GitOptions
}
GitConfigParams configures the git config methods.
type GitCreateBranchParams ¶
type GitCreateBranchParams struct {
// StartPoint is the commit or ref to branch from.
StartPoint string
GitOptions
}
GitCreateBranchParams configures Git.CreateBranch.
type GitDeleteBranchParams ¶
type GitDeleteBranchParams struct {
// Force force-deletes with -D.
Force bool
GitOptions
}
GitDeleteBranchParams configures Git.DeleteBranch.
type GitDiffParams ¶
type GitDiffParams struct {
// Staged diffs the index against HEAD (git diff --cached).
Staged bool
// Refs are up to two commits/branches to diff. One ref diffs it against the
// working tree; two refs diff the pair.
Refs []string
// Paths restricts the diff to these paths.
Paths []string
// NameOnly lists only the changed file names.
NameOnly bool
// Stat produces a diffstat summary instead of the full patch.
Stat bool
GitOptions
}
GitDiffParams configures Git.Diff.
type GitError ¶
type GitError struct {
// Op is the short operation name (e.g. "clone", "push").
Op string
// Message is the failure detail, usually git's stderr.
Message string
// Stderr is the raw stderr output from git.
Stderr string
// ExitCode is git's process exit code.
ExitCode int32
// Auth is true when the failure looks like an authentication error.
Auth bool
}
GitError is returned when a git command exits non-zero. It is distinct from APIError: a GitError means the SDK reached the capsule and ran git, but git itself failed.
type GitFetchParams ¶
type GitFetchParams struct {
// Remote is the remote name; defaults to "origin" unless All is set.
Remote string
// Refspec optionally restricts what is fetched (e.g. a branch name).
Refspec string
// All fetches from every configured remote.
All bool
// Prune deletes remote-tracking refs that no longer exist on the remote.
Prune bool
// Tags fetches all tags in addition to the refspec.
Tags bool
// Depth deepens (or shortens) a shallow clone to this many commits.
Depth int
// Username and Password authenticate HTTP(S) fetches. They are embedded in
// the remote URL for the fetch and then restored. Ignored when All is set.
Username string
Password string
GitOptions
}
GitFetchParams configures Git.Fetch.
type GitInitParams ¶
type GitInitParams struct {
// Path is the destination path; defaults to ".".
Path string
// Bare creates a bare repository.
Bare bool
// InitialBranch names the initial branch (e.g. "main").
InitialBranch string
GitOptions
}
GitInitParams configures Git.Init.
type GitLogParams ¶
type GitLogParams struct {
// MaxCount limits the number of commits (0 = git default, all).
MaxCount int
// Skip skips this many commits from the top.
Skip int
// Ref is the starting commit, branch, or range (default HEAD).
Ref string
// Author filters by author (regex, as git --author).
Author string
// Since and Until bound the commit date range (any git date string).
Since string
Until string
// Paths restricts history to commits touching these paths.
Paths []string
GitOptions
}
GitLogParams configures Git.Log.
type GitMergeParams ¶
type GitMergeParams struct {
// Ref is the branch or commit to merge into the current branch. Required
// unless Abort is set.
Ref string
// NoFF forces a merge commit even when a fast-forward is possible.
NoFF bool
// FFOnly refuses the merge unless a fast-forward is possible.
FFOnly bool
// Squash stages the merge result without committing or recording the merge.
Squash bool
// Message overrides the merge commit message.
Message string
// Abort aborts an in-progress merge and restores the pre-merge state.
Abort bool
GitOptions
}
GitMergeParams configures Git.Merge.
type GitOptions ¶
type GitOptions struct {
// Cwd is the working directory (usually the repository root).
Cwd string
// Envs are extra environment variables merged over the git defaults.
Envs map[string]string
// TimeoutSec bounds the command; zero uses the per-operation default.
TimeoutSec int32
}
GitOptions carries the execution options common to every git command.
type GitPullParams ¶
type GitPullParams struct {
// Remote is the remote name; defaults to "origin".
Remote string
// Branch is the branch to pull.
Branch string
// Rebase rebases instead of merging.
Rebase bool
// FFOnly only allows fast-forward merges.
FFOnly bool
// Username and Password authenticate HTTP(S) pulls. They are embedded in
// the remote URL for the pull and then restored.
Username string
Password string
GitOptions
}
GitPullParams configures Git.Pull.
type GitPushParams ¶
type GitPushParams struct {
// Remote is the remote name; defaults to "origin".
Remote string
// Branch is the branch to push; defaults to the current branch.
Branch string
// Force force-pushes.
Force bool
// SetUpstream sets the upstream tracking reference.
SetUpstream bool
// Username and Password authenticate HTTP(S) pushes. They are embedded in
// the remote URL for the push and then restored.
Username string
Password string
GitOptions
}
GitPushParams configures Git.Push.
type GitRemoteAddParams ¶
type GitRemoteAddParams struct {
// Fetch fetches immediately after adding.
Fetch bool
GitOptions
}
GitRemoteAddParams configures Git.RemoteAdd.
type GitResetParams ¶
type GitResetParams struct {
// Mode is one of soft, mixed, hard, merge, keep.
Mode string
// Ref is the commit, branch, or ref to reset to.
Ref string
// Paths are specific paths to reset.
Paths []string
GitOptions
}
GitResetParams configures Git.Reset.
type GitRestoreParams ¶
type GitRestoreParams struct {
// Staged restores the index (unstages).
Staged bool
// Worktree restores working-tree files. When neither Staged nor Worktree is
// set, Worktree is assumed.
Worktree bool
// Source is the commit or ref to restore from.
Source string
GitOptions
}
GitRestoreParams configures Git.Restore.
type GitShowParams ¶
type GitShowParams struct {
// NameOnly lists only the changed file names.
NameOnly bool
// Stat produces a diffstat summary.
Stat bool
GitOptions
}
GitShowParams configures Git.Show.
type GitStashEntry ¶
type GitStashEntry struct {
// Ref is the stash reference (e.g. "stash@{0}").
Ref string
// Description is the stash message.
Description string
}
GitStashEntry is one entry from Git.StashList.
type GitStashPopParams ¶
type GitStashPopParams struct {
// Ref selects a specific stash entry (e.g. "stash@{1}"); empty pops the
// most recent.
Ref string
GitOptions
}
GitStashPopParams configures Git.StashPop.
type GitStashSaveParams ¶
type GitStashSaveParams struct {
// Message is an optional stash label.
Message string
// IncludeUntracked also stashes untracked files (git stash -u).
IncludeUntracked bool
// KeepIndex leaves staged changes in the index after stashing.
KeepIndex bool
GitOptions
}
GitStashSaveParams configures Git.StashSave.
type GitStatus ¶
type GitStatus struct {
// Branch is the current branch name, empty when detached.
Branch string
// Upstream is the upstream tracking branch, if any.
Upstream string
// Ahead is the number of commits ahead of upstream.
Ahead int
// Behind is the number of commits behind upstream.
Behind int
// Detached reports whether HEAD is detached.
Detached bool
// Files holds the per-file status entries.
Files []FileStatus
}
GitStatus is the parsed output of git status --porcelain=v1 --branch.
func (GitStatus) HasConflicts ¶
HasConflicts reports whether at least one file has merge conflicts.
func (GitStatus) HasUntracked ¶
HasUntracked reports whether at least one file is untracked.
type GitTagParams ¶
type GitTagParams struct {
// Message, when set, creates an annotated tag carrying this message;
// otherwise a lightweight tag is created.
Message string
// Ref is the commit or ref to tag; defaults to HEAD.
Ref string
// Force overwrites an existing tag of the same name.
Force bool
GitOptions
}
GitTagParams configures Git.CreateTag.
type ListSnapshotsParams ¶
type ListSnapshotsParams struct {
// Type filters by "base" or "snapshot"; empty returns both.
Type string
// Query searches over name and team slug.
Query string
// Page is the 1-based page number (default 1).
Page int
// PerPage is the page size (default 50, max 200).
PerPage int
}
ListSnapshotsParams filters and paginates Client.ListSnapshots.
type MetricPoint ¶
type MetricPoint struct {
TimestampUnix int64 `json:"timestamp_unix"`
CPUPct float64 `json:"cpu_pct"`
MemBytes int64 `json:"mem_bytes"`
DiskBytes int64 `json:"disk_bytes"`
}
MetricPoint is a single time-series sample of capsule resource usage.
type Metrics ¶
type Metrics struct {
CapsuleID string `json:"sandbox_id"`
Range string `json:"range"`
Points []MetricPoint `json:"points"`
}
Metrics is a range of resource-usage samples for a capsule.
type Option ¶
type Option func(*Client)
Option configures a Client.
func WithAPIKey ¶
WithAPIKey sets the team API key (the "wrn_..." value). Required.
func WithBaseURL ¶
WithBaseURL overrides the API base URL (default DefaultBaseURL). Useful for self-hosted deployments. The path prefix is preserved, so pass the full API root, e.g. "https://wrenn.internal/api".
func WithHTTPClient ¶
WithHTTPClient supplies a custom *http.Client (for proxies or instrumentation). Prefer per-call context deadlines over a client-wide Timeout: a fixed timeout would abort legitimately long operations such as a synchronous Capsule.Exec of a slow command or a large Capsule.ReadFileStream.
func WithProxyDomain ¶
WithProxyDomain overrides the host used to build capsule proxy URLs ({port}-{capsuleID}.<domain>, see Capsule.URL). Falls back to the WRENN_PROXY_DOMAIN environment variable, then to a value derived from the base URL. Useful for self-hosted deployments with a custom proxy host.
func WithUserAgent ¶
WithUserAgent overrides the User-Agent header sent on every request.
type Process ¶
type Process struct {
PID uint32 `json:"pid"`
Tag string `json:"tag,omitempty"`
Cmd string `json:"cmd"`
Args []string `json:"args,omitempty"`
}
Process describes a running process listed by Capsule.ListProcesses.
type PtyEvent ¶
type PtyEvent struct {
// Type is the event kind.
Type PtyEventType
// Data holds raw terminal output (PtyEventOutput) or an error message
// (PtyEventError). Unlike [Capsule.ExecStream], output travels as binary
// WebSocket frames, so it is byte-faithful — no UTF-8 mangling.
Data []byte
// PID is the shell's process ID, set on PtyEventStarted.
PID uint32
// Tag is the session handle, set on PtyEventStarted. Pass it to
// [Capsule.PtyConnect] to reattach to the same terminal later.
Tag string
// ExitCode is set on PtyEventExit.
ExitCode int32
// Fatal reports whether a PtyEventError ended the session.
Fatal bool
}
PtyEvent is a single event from an interactive PtySession.
type PtyEventType ¶
type PtyEventType string
PtyEventType identifies the kind of a PtyEvent.
const ( // PtyEventStarted is emitted once when the terminal is ready; Tag and PID // are set. It does not appear when reconnecting with [Capsule.PtyConnect]. PtyEventStarted PtyEventType = "started" // PtyEventOutput carries a chunk of raw terminal output in Data. PtyEventOutput PtyEventType = "output" // PtyEventExit is emitted once when the shell process ends; ExitCode is set. PtyEventExit PtyEventType = "exit" // PtyEventError carries a stream-level error message in Data. When Fatal is // true the session has ended and the event channel closes. PtyEventError PtyEventType = "error" )
type PtyParams ¶
type PtyParams struct {
// Cmd is the program to run in the terminal. Empty launches the guest
// user's default login shell (resolved from /etc/passwd).
Cmd string
// Args are the command arguments.
Args []string
// Cols is the terminal width in columns. Zero defaults to 80.
Cols uint32
// Rows is the terminal height in rows. Zero defaults to 24.
Rows uint32
// Envs are additional environment variables for the shell.
Envs map[string]string
// Cwd is the working directory to start the shell in.
Cwd string
// User is the guest user to run as. Empty uses the image's default user.
User string
}
PtyParams configures Capsule.Pty.
type PtySession ¶
type PtySession struct {
// contains filtered or unexported fields
}
PtySession is a live, bidirectional pseudo-terminal inside a capsule. Unlike the receive-only Capsule.ExecStream, a PtySession accepts keystrokes (PtySession.Write), terminal resizes (PtySession.Resize), and delivers byte-faithful output. Consume PtySession.Events; write with the input methods; call PtySession.Close (or cancel the context) when done.
term, err := cap.Pty(ctx, wrenn.PtyParams{Cmd: "/bin/bash"})
if err != nil {
return err
}
defer term.Close()
_ = term.Write([]byte("echo hello\n"))
for ev := range term.Events() {
switch ev.Type {
case wrenn.PtyEventOutput:
os.Stdout.Write(ev.Data)
case wrenn.PtyEventExit:
return nil
}
}
A PtySession is safe for concurrent use: one goroutine may range over Events() while another calls Write/Resize/Kill.
func (*PtySession) Close ¶
func (s *PtySession) Close() error
Close ends the session and releases the WebSocket connection. It is safe to call more than once. Unlike relying on context cancellation, Close reliably ends a session even if the consumer has stopped reading Events().
func (*PtySession) Events ¶
func (s *PtySession) Events() <-chan PtyEvent
Events returns the receive-only channel of terminal events. It is closed when the shell exits, a fatal error occurs, or the context is cancelled.
func (*PtySession) Kill ¶
func (s *PtySession) Kill() error
Kill sends SIGKILL to the terminal's process, ending the session.
func (*PtySession) PID ¶
func (s *PtySession) PID() uint32
PID returns the shell's process ID once known (after PtyEventStarted). Zero until then.
func (*PtySession) Resize ¶
func (s *PtySession) Resize(cols, rows uint32) error
Resize changes the terminal dimensions. Both cols and rows must be positive.
func (*PtySession) Tag ¶
func (s *PtySession) Tag() string
Tag returns the session handle once known (after PtyEventStarted, or the tag passed to Capsule.PtyConnect). Empty until then.
func (*PtySession) Write ¶
func (s *PtySession) Write(p []byte) error
Write sends raw bytes to the terminal's stdin (keystrokes, pasted text). The bytes are delivered verbatim as a binary frame — no JSON wrapping, no base64.
type Signal ¶
type Signal string
Signal is a process termination signal accepted by Capsule.KillProcess.
type Snapshot ¶
type Snapshot struct {
Name string `json:"name"`
Type string `json:"type"` // "base" or "snapshot"
VCPUs *int32 `json:"vcpus,omitempty"`
MemoryMB *int32 `json:"memory_mb,omitempty"`
SizeBytes int64 `json:"size_bytes"`
CreatedAt string `json:"created_at"`
Platform bool `json:"platform"` // platform-owned base image
Protected bool `json:"protected"` // cannot be renamed/deleted
Public bool `json:"public"` // published to other teams
Owned bool `json:"owned"` // owned by the caller's team
TeamSlug string `json:"team_slug"`
Metadata map[string]string `json:"metadata,omitempty"`
}
Snapshot describes a template the team may launch: its own snapshots and base images, platform images, and public templates published by other teams.
type SnapshotList ¶
type SnapshotList struct {
Templates []Snapshot `json:"templates"`
Total int `json:"total"`
Page int `json:"page"`
PerPage int `json:"per_page"`
TotalPages int `json:"total_pages"`
}
SnapshotList is a page of snapshots with pagination metadata.
type StartBackgroundParams ¶
type StartBackgroundParams struct {
// Cmd is the executable to run. Required.
Cmd string `json:"cmd"`
// Args are the command arguments.
Args []string `json:"args,omitempty"`
// Tag is an optional stable handle for the process; the server assigns one
// if empty.
Tag string `json:"tag,omitempty"`
// Envs are additional environment variables for the command.
Envs map[string]string `json:"envs,omitempty"`
// Cwd is the working directory to run the command in.
Cwd string `json:"cwd,omitempty"`
}
StartBackgroundParams configures Capsule.StartBackground.
type Stats ¶
type Stats struct {
Range string `json:"range"`
Current StatsCurrent `json:"current"`
Peaks StatsPeaks `json:"peaks"`
Series StatsSeries `json:"series"`
}
Stats is aggregate capsule usage for the team.
type StatsCurrent ¶
type StatsCurrent struct {
RunningCount int32 `json:"running_count"`
VCPUsReserved int32 `json:"vcpus_reserved"`
MemoryMBReserved int32 `json:"memory_mb_reserved"`
}
StatsCurrent is the team's live capsule reservation.
type StatsPeaks ¶
type StatsPeaks struct {
RunningCount int32 `json:"running_count"`
VCPUs int32 `json:"vcpus"`
MemoryMB int32 `json:"memory_mb"`
}
StatsPeaks are peak values over the requested range.
type StatsSeries ¶
type StatsSeries struct {
Labels []string `json:"labels"`
Running []int32 `json:"running"`
VCPUs []int32 `json:"vcpus"`
MemoryMB []int32 `json:"memory_mb"`
}
StatsSeries is the per-bucket time series over the requested range. All slices share the same length and index as Labels.
type StreamEvent ¶
type StreamEvent struct {
// Type is the event kind.
Type StreamEventType
// PID is set on EventStart.
PID uint32
// Data holds output (EventStdout/EventStderr) or a message (EventError).
//
// The server transmits output as text over JSON, so bytes that are not
// valid UTF-8 may be altered in transit. For binary-faithful output, run
// the command with [Capsule.Exec] instead.
Data string
// ExitCode is set on EventExit.
ExitCode int32
}
StreamEvent is a single event from a receive-only process stream (Capsule.ExecStream or Capsule.AttachProcess).
type StreamEventType ¶
type StreamEventType string
StreamEventType identifies the kind of a StreamEvent.
const ( // EventStart is emitted once when the process begins; PID is set. EventStart StreamEventType = "start" // EventStdout carries a chunk of standard output in Data. EventStdout StreamEventType = "stdout" // EventStderr carries a chunk of standard error in Data. EventStderr StreamEventType = "stderr" // EventExit is emitted once when the process ends; ExitCode is set. EventExit StreamEventType = "exit" // EventError carries a stream-level error message in Data. EventError StreamEventType = "error" )
type Usage ¶
type Usage struct {
From string `json:"from"`
To string `json:"to"`
Points []UsagePoint `json:"points"`
}
Usage is billed resource usage over a date range.
type UsagePoint ¶
type UsagePoint struct {
Date string `json:"date"` // YYYY-MM-DD
CPUMinutes float64 `json:"cpu_minutes"`
RAMMBMinutes float64 `json:"ram_mb_minutes"`
}
UsagePoint is one day of billed resource usage.
type Volume ¶ added in v0.2.0
type Volume struct {
// ID is the volume ID ("vol-…").
ID string `json:"id"`
// TeamID is the owning team.
TeamID string `json:"team_id"`
// Name is the "vl-"-prefixed name, unique within the team. It is accepted
// anywhere a volume ID is (see [Client.GetVolume], CreateCapsuleParams.VolumeIDs).
Name string `json:"name"`
// SizeMB is the volume's size ceiling in megabytes, fixed at creation. The
// backing storage is sparse, so it is not allocated upfront.
SizeMB int32 `json:"size_mb"`
// Status is one of the VolumeStatus* constants.
Status string `json:"status"`
// HostID is the host the volume is pinned to; nil until first attached.
HostID *string `json:"host_id,omitempty"`
// CapsuleID is the capsule the volume is currently attached to, if any.
CapsuleID *string `json:"sandbox_id,omitempty"`
// MountPath is the guest path the volume is mounted at while attached
// (e.g. "/mnt/vol-…"). Empty while detached.
MountPath string `json:"mount_path"`
// CreatedAt is an RFC 3339 timestamp.
CreatedAt string `json:"created_at"`
// LastAttachedAt is an RFC 3339 timestamp, nil if never attached.
LastAttachedAt *string `json:"last_attached_at,omitempty"`
}
Volume is an external storage volume: a persistent disk that outlives the capsules it is attached to. A volume is created detached and is placed on a host only when it is first attached to a capsule, at which point it is pinned to that host for the rest of its life. Volumes are never auto-deleted.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package coderunner runs code in a persistent Jupyter kernel inside a Wrenn capsule.
|
Package coderunner runs code in a persistent Jupyter kernel inside a Wrenn capsule. |