api

package
v0.8.65 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 60 Imported by: 0

Documentation

Overview

Package api defines the Dejima HTTP API: types, server, and client.

The CLI is the first consumer. Third-party apps target this surface directly. See docs/v1-spec.md §6 for the endpoint list and contract.

Index

Constants

View Source
const (
	// DefaultImage is the canonical island image. Built locally from image/Dockerfile.
	DefaultImage = "dejima/island:latest"
	// DefaultAgent is the agent run inside the island when none is specified.
	DefaultAgent = "claude-code"
	// AgentHeadless is the reserved agent type for islands that run a
	// user-provided command directly (no tmux, no interactive attach surface).
	// The command is supplied via CreateIslandRequest.Cmd → Project.Cmd →
	// DEJIMA_AGENT_CMD env var. Useful for API-SDK agents, background
	// workers, and anything that doesn't need an attach surface.
	AgentHeadless = "headless"
)
View Source
const DefaultEphemeralTTL = time.Hour

DefaultEphemeralTTL is a leak backstop: the maximum lifetime applied to an ephemeral sub-agent when its grant sets no TTL (--ttl unset). Without it, a granted sub-agent whose parent stays alive and whose session never reports "exited" (e.g. a lingering tmux shell, or an agent spawned over the API that never started a real process — the d7 case in a3 #62) would live forever, silently holding a max_concurrent slot. An ephemeral is by definition short-lived; an operator who wants longer sets an explicit grant --ttl. This is a ceiling, not a typical lifetime — the parent-removed and exited triggers reap most sub-agents far sooner.

View Source
const DefaultIdleScanInterval = 5 * time.Minute

DefaultIdleScanInterval bounds how often the idle-hibernator samples islands. The actual cadence is min(this, threshold/4) so a short threshold still gets checked a few times within its window.

View Source
const DefaultSpawnReapInterval = time.Minute

DefaultSpawnReapInterval is how often the reaper sweeps for ephemeral sub-agents to clean up. Minute granularity is plenty (TTLs are coarse; the exit/parent cases also resolve on the next sweep).

View Source
const DefaultWakeFlushInterval = 15 * time.Second

DefaultWakeFlushInterval bounds how often queued nudges are retried for delivery (a busy agent's nudge waits here until it next hits a turn boundary). It's the fallback when RunWakeNotifier is given a non-positive interval; the daemon exposes the live value via --wake-flush-interval / DEJIMAD_WAKE_FLUSH_INTERVAL.

View Source
const DefaultWatchdogInterval = 30 * time.Second

DefaultWatchdogInterval is how often the container watchdog samples island health when started without an explicit interval.

View Source
const HeartbeatMonitorInterval = time.Minute

HeartbeatMonitorInterval is how often the daemon checks for silent agents.

View Source
const SchedulerTickInterval = time.Minute

SchedulerTickInterval is how often the daemon checks for due scheduled wakes. Minute granularity is plenty — cadences are hours/days.

Variables

View Source
var ErrSessionGone = errors.New("session gone")

DialSession opens a websocket against the island's primary-agent session. ErrSessionGone tags a websocket-attach failure where the daemon positively reported the session/island is gone (a 404/410 handshake response), as opposed to a transient transport failure (daemon unreachable: laptop sleep, network drop, daemon restart). The reconnect loop uses it to stop retrying promptly — a gone session never comes back — while retrying transport failures for as long as the user keeps the terminal open, since the tmux session survives on the daemon.

Functions

func IdentityFromContext

func IdentityFromContext(ctx context.Context) (authtoken.Identity, bool)

IdentityFromContext returns the authenticated identity for an operator-surface request, and ok=false for requests that did not pass through roleAuth (e.g. the in-island token listener, whose actor is TokenIslandFromContext instead).

func TokenIslandFromContext

func TokenIslandFromContext(ctx context.Context) string

TokenIslandFromContext returns the island a token-authenticated request was scoped to, or "" for requests that did not arrive on the token listener.

func WithAuditIdentity

func WithAuditIdentity(ctx context.Context, id AuditIdentity) context.Context

WithAuditIdentity attaches an authenticated identity to ctx for the audit middleware to record. The auth layer (Lane 2) calls this once it authenticates a request; its middleware must sit OUTSIDE auditMiddleware (authenticate → audit → handle) so the value is present when the record is written. See Server.Handler for the composition order.

func WithIdentity

func WithIdentity(ctx context.Context, id authtoken.Identity) context.Context

WithIdentity returns ctx carrying id. Set by roleAuth on every operator request, so IdentityFromContext is populated for all inner handlers/middleware.

Types

type ActivityFilter

type ActivityFilter struct {
	Actor    string
	Island   string
	Owner    string
	Kind     string // lifecycle | broker | system
	Decision string // allowed | denied
	Since    string // RFC3339
	Until    string // RFC3339
	Limit    int
}

ActivityFilter narrows the team activity feed. All fields are optional.

type ActivityItem

type ActivityItem struct {
	Seq  uint64    `json:"seq"`
	Time time.Time `json:"time"`
	// Actor is who acted: a token label / "operator" / "island:<name>" (an agent).
	Actor string `json:"actor"`
	Role  string `json:"role,omitempty"`
	// Island is the island acted on (or the acting agent's island), when any.
	Island string `json:"island,omitempty"`
	// Owner is that island's owner label, enriched from project config.
	Owner string `json:"owner,omitempty"`
	// Kind buckets the item for filtering/rendering: "lifecycle" (operator island
	// + account ops), "broker" (Port/capability/MCP host access), or "system".
	Kind string `json:"kind"`
	// Summary is the human-readable one-liner ("alice created an island").
	Summary string `json:"summary"`
	// Decision is "allowed" | "denied" (denied attempts are the security-relevant
	// slice — a viewer refused a purge, an agent refused an ungranted MCP server).
	Decision string `json:"decision,omitempty"`
}

ActivityItem is one rendered entry in the team activity feed.

type ActivityResponse

type ActivityResponse struct {
	Items    []ActivityItem `json:"items"`
	Returned int            `json:"returned"`
	// AuditEnabled reflects whether the operational audit log is on. When false,
	// the feed carries only the always-on brokered (agent↔host) records — a hint
	// for clients to suggest enabling --audit for the full who-did-what timeline.
	AuditEnabled bool `json:"audit_enabled"`
}

ActivityResponse is the body of GET /v1/activity.

type AdminUpdateRequest

type AdminUpdateRequest struct {
	Execute bool `json:"execute"`
	// Force applies the update even while terminal sessions are attached. The
	// daemon restart drops every attached client, so by default an Execute with
	// clients attached is deferred (Deferred=true) instead of yanking them.
	Force bool `json:"force,omitempty"`
}

AdminUpdateRequest is the body of POST /v1/admin/update. Execute=false (the default) reports the plan without changing anything.

type AdminUpdateResponse

type AdminUpdateResponse struct {
	Current         string `json:"current"`
	Latest          string `json:"latest"`
	Mode            string `json:"mode"` // source | release
	UpdateAvailable bool   `json:"update_available"`
	Applying        bool   `json:"applying"`
	// Deferred is set when an available update was NOT applied because terminal
	// sessions are attached and Force was not set; AttachedClients is how many.
	// The caller retries with Force (or once the terminals detach) to apply.
	Deferred        bool `json:"deferred,omitempty"`
	AttachedClients int  `json:"attached_clients,omitempty"`
}

AdminUpdateResponse reports the daemon's update status and, when Execute was set and an update is available, that the apply has started (the daemon then restarts, so this response is the client's confirmation it began).

type AgentConfigRequest

type AgentConfigRequest struct {
	Provider *string `json:"provider,omitempty"`
	Model    *string `json:"model,omitempty"`
}

AgentConfigRequest is the body of PATCH /v1/islands/:name/agents/:id/config. Pointer fields distinguish "leave unchanged" (nil) from an explicit value (incl. "" to clear).

type AgentConfigResponse

type AgentConfigResponse struct {
	Provider        string `json:"provider"`
	Model           string `json:"model"`
	RestartRequired bool   `json:"restart_required"`
}

AgentConfigResponse echoes the agent's resulting provider/model and whether the change needs a container recreate to take effect (a Model change rides an immutable env var; a Provider/key change re-materializes on the next restart).

type AgentEventRequest

type AgentEventRequest struct {
	Island  string         `json:"island"`
	Agent   string         `json:"agent,omitempty"`
	Type    events.Type    `json:"type"`
	Payload map[string]any `json:"payload,omitempty"`
}

AgentEventRequest is the body of POST /v1/internal/agent-event.

type AgentInfo

type AgentInfo struct {
	ID         string `json:"id"`
	Type       string `json:"type"`
	Label      string `json:"label,omitempty"`
	Tmux       string `json:"tmux,omitempty"`
	Branch     string `json:"branch,omitempty"`
	Worktree   string `json:"worktree,omitempty"`
	Attachable bool   `json:"attachable"`
	// CreatedAt is when the agent was added to the island — the basis for its
	// displayed uptime/age. Zero for legacy agents persisted before this field.
	CreatedAt time.Time `json:"created_at,omitempty"`
	// State is the agent's session liveness: "running", "stopped" (no tmux
	// session), "exited" (session alive but the agent process died and only a
	// shell prompt remains), or "" (not probed). Detail endpoint only.
	State      string          `json:"state,omitempty"`
	AgentState *AgentStateInfo `json:"agent_state,omitempty"`
	Attached   []PresenceEntry `json:"attached,omitempty"`
	// Restarts is how many times a supervised (Restart) headless agent has
	// crashed and been respawned by its supervisor loop — counted from the
	// per-agent log. A climbing count is how a crash-loop (e.g. OOM) shows up,
	// since a supervised agent's session stays "running". Detail endpoint only.
	Restarts int `json:"restarts,omitempty"`
	// Error is the last orchestration failure for this agent — e.g. its worktree
	// or tmux session couldn't be created. Empty when the agent came up cleanly.
	Error   string    `json:"error,omitempty"`
	ErrorAt time.Time `json:"error_at,omitempty"`
	// Provider/Model echo the agent's configured LLM target (only meaningful for
	// frameworks that reach a model over a provider API key; empty otherwise).
	Provider string `json:"provider,omitempty"`
	Model    string `json:"model,omitempty"`
	// ProviderKeySet reports whether the daemon has a provider credential to
	// inject for this agent's provider.
	ProviderKeySet bool `json:"provider_key_set,omitempty"`
	// AuthState is the proactive LLM-credential readiness, computed from the
	// handler registry + provider store (never from logs): "missing-provider-auth"
	// when a key-requiring agent has no resolvable key (it will fail at first
	// task), else "" (ready, or the agent needs no provider key).
	AuthState string `json:"auth_state,omitempty"`
	// Usage is the agent's adapter-REPORTED token/cost (Claude Code today).
	// OMITTED entirely for adapters that don't report — clients render "n/a"
	// rather than a fake zero. Detail endpoint only.
	Usage *AgentUsage `json:"usage,omitempty"`
	// Ephemeral / SpawnedBy surface an agent-spawned sub-agent and its lineage
	// (the spawning agent's id). Empty/false for operator-created agents.
	// SpawnedByLabel is the spawner's human name, so lineage renders as a name.
	Ephemeral      bool   `json:"ephemeral,omitempty"`
	SpawnedBy      string `json:"spawned_by,omitempty"`
	SpawnedByLabel string `json:"spawned_by_label,omitempty"`
}

AgentInfo is the public view of one agent within an island.

func (AgentInfo) RefID added in v0.6.9

func (a AgentInfo) RefID() string

RefID / RefLabel let an AgentInfo satisfy project.AgentRef, so the CLI can resolve a user-supplied agent ref (id or label) against the island's agent list with the same shared resolver the daemon uses.

func (AgentInfo) RefLabel added in v0.6.9

func (a AgentInfo) RefLabel() string

type AgentSpecRequest

type AgentSpecRequest struct {
	Type  string `json:"type,omitempty"`  // defaults to the island/default agent
	Label string `json:"label,omitempty"` // optional, renamable
	Cmd   string `json:"cmd,omitempty"`   // required only for headless
	// Provider/Model select the LLM target for key-requiring frameworks. Provider
	// names a daemon credential (see /v1/credentials/providers); Model is the
	// "provider/model" string. Both optional; only meaningful when the agent type
	// RequiresProviderKey.
	Provider string `json:"provider,omitempty"`
	Model    string `json:"model,omitempty"`
	// Ephemeral requests an auto-reaped sub-agent. An in-island token (an
	// agent-initiated spawn) MUST set this — a token may only create ephemeral
	// sub-agents within the operator's spawn grant, never persistent agents.
	// SpawnedBy is the spawning agent's id (lineage / depth-cap input).
	Ephemeral bool   `json:"ephemeral,omitempty"`
	SpawnedBy string `json:"spawned_by,omitempty"`
}

AgentSpecRequest describes one agent to create — either as an element of CreateIslandRequest.Agents or the body of POST /v1/islands/{name}/agents.

type AgentStateInfo

type AgentStateInfo struct {
	Latest    string    `json:"latest"` // e.g. "waiting-for-input", "task-complete", "error"
	UpdatedAt time.Time `json:"updated_at"`
}

AgentStateInfo is the most recent operational signal from the agent itself, derived from agent-event hooks (currently emitted by the Claude Code shim). Latest may be empty if the agent hasn't emitted any events.

type AgentTypeCapability

type AgentTypeCapability struct {
	Type                string   `json:"type"`
	Interactive         bool     `json:"interactive"`
	RequiresProviderKey bool     `json:"requires_provider_key"`
	SupportedProviders  []string `json:"supported_providers,omitempty"`
	SuggestedModels     []string `json:"suggested_models,omitempty"`
	GatewayPort         int      `json:"gateway_port,omitempty"` // 0 = no localhost UI to open
	// DashboardTokenCmd, run in the container, prints the framework's gateway auth
	// token; `dejima agent open` appends DashboardTokenSuffix (with "{token}"
	// substituted) to the console URL so the browser auto-authenticates. E.g. suffix
	// "#token={token}" (OpenClaw reads the token from the URL fragment). Both empty =
	// open the gateway root.
	DashboardTokenCmd    string `json:"dashboard_token_cmd,omitempty"`
	DashboardTokenSuffix string `json:"dashboard_token_suffix,omitempty"`
	// Bundled marks a tier-1 agent preinstalled in the image; tier-2 agents
	// (Bundled=false) self-install on first launch. InstallCmd is the informational
	// install command a picker can surface as "installs on first use".
	Bundled    bool     `json:"bundled,omitempty"`
	InstallCmd []string `json:"install_cmd,omitempty"`
}

AgentTypeCapability describes what a built-in agent type supports — drives the provider/model picker and the channels affordance in clients.

type AgentTypesResponse

type AgentTypesResponse struct {
	Types []AgentTypeCapability `json:"types"`
}

AgentTypesResponse is the body of GET /v1/agent-types.

type AgentUsage added in v0.6.7

type AgentUsage struct {
	InputTokens  int       `json:"input_tokens"`
	OutputTokens int       `json:"output_tokens"`
	TotalTokens  int       `json:"total_tokens"`
	CostUSD      *float64  `json:"cost_usd,omitempty"`
	Source       string    `json:"source"` // reporting adapter, e.g. "claude-code"
	AsOf         time.Time `json:"as_of"`
}

AgentUsage is an agent's self-reported token/cost for its session, ingested from the agent's own usage hook over the in-island token path. Dejima can't observe the (opaque, outbound) LLM call, so these numbers come FROM the agent; an adapter that doesn't report leaves AgentInfo.Usage nil → "n/a" (we never fake uniform coverage). InputTokens aggregates fresh + cached input so InputTokens + OutputTokens == TotalTokens. CostUSD is nil when the model isn't in the price table (tokens still show; cost renders n/a).

type AggregateResponse added in v0.8.3

type AggregateResponse struct {
	TotalIslands     int     `json:"total_islands"`
	Running          int     `json:"running"`
	Hibernated       int     `json:"hibernated"`
	MemoryUsageBytes uint64  `json:"memory_usage_bytes"`
	MemoryLimitBytes uint64  `json:"memory_limit_bytes"`
	CPUPercent       float64 `json:"cpu_percent"`
	DiskTotalBytes   int64   `json:"disk_total_bytes"`
}

AggregateResponse is the privacy-preserving host-wide rollup returned by GET /v1/aggregate (multi-tenant design, capRead + any authenticated caller). It carries counts + totals across ALL islands and NEVER any names, repos, owners, or per-island rows — so a teammate can see shared-host utilization without seeing what's running. Field tags are the locked contract between the client (this type, a2) and the server handler (a1's P3). Memory fields are uint64 to match OverviewResponse; disk is int64 to match disk.total_bytes.

type AuditIdentity

type AuditIdentity struct {
	Actor string // who: a token label, user, or service identity
	Role  string // the actor's role, when the auth layer assigns one
}

AuditIdentity is the authenticated caller (who + role) attached to a request by the auth layer. Lane 2 (token auth / roles) populates it via WithAuditIdentity; the audit middleware records it as the entry's Actor/Role. It is optional: the fully-trusted operator listeners (unix socket, tailnet TCP) carry no per-request identity, so until an identity layer fills it the audit middleware attributes those requests to the operator.

func AuditIdentityFromContext

func AuditIdentityFromContext(ctx context.Context) (AuditIdentity, bool)

AuditIdentityFromContext returns the identity attached by WithAuditIdentity.

type AuditOptions

type AuditOptions struct {
	// Reads also records read (GET/HEAD/OPTIONS) requests. Default (false)
	// records state-changing requests + lifecycle only, keeping the log lean and
	// free of high-volume TUI polling noise.
	Reads bool
}

AuditOptions configures the operational audit log.

type AuditQuery

type AuditQuery struct {
	Limit    int    // last N entries after filtering (0 = all)
	Island   string // exact island name
	Type     string // type prefix ("port" matches port.*) or an exact dotted type
	Actor    string // exact actor
	Decision string // "allowed" | "denied"
	Since    string // RFC3339 lower bound (inclusive)
	Until    string // RFC3339 upper bound (inclusive)
}

AuditQuery are the optional filters for reading or exporting the ledger. The zero value reads the whole ledger. Verification always covers the full chain regardless of any filter — these only narrow what is returned.

type AuditResponse

type AuditResponse struct {
	Entries  []ledger.Entry `json:"entries"`
	Total    int            `json:"total"`           // entries in the whole ledger (before filtering)
	Returned int            `json:"returned"`        // entries returned after filter + limit
	Verified bool           `json:"verified"`        // whole-chain hash verification result
	Error    string         `json:"error,omitempty"` // chain-verification failure detail
}

AuditResponse is the body of GET /v1/audit — the Ledger (brokered-operation records plus, when the operational audit log is enabled, api.request and lifecycle records), filtered per the request, plus the result of verifying the hash chain. Verification always runs over the WHOLE chain regardless of any filter or limit: tamper-evidence covers the complete file, not the slice the caller asked to see.

type AuthorizeSSHKeyRequest

type AuthorizeSSHKeyRequest struct {
	PublicKey string `json:"public_key"` // an OpenSSH "ssh-… AAAA… [comment]" line
}

AuthorizeSSHKeyRequest authorizes a public key fleet-wide via the operator API, so any operator device can enroll its own key without copying it to the daemon host (and the daemon — which owns the file — performs the write).

type AuthorizeSSHKeyResponse

type AuthorizeSSHKeyResponse struct {
	Fingerprint string `json:"fingerprint"`
}

AuthorizeSSHKeyResponse returns the enrolled key's fingerprint.

type CapabilityExecuteRequest

type CapabilityExecuteRequest struct {
	Island string            `json:"island,omitempty"`
	Target string            `json:"target"`
	Args   map[string]string `json:"args,omitempty"`
}

CapabilityExecuteRequest is the body of POST /v1/capabilities/execute. Island is supplied by an operator caller; a token-authenticated in-island caller is pinned to its own island by its bearer token and Island is ignored.

type CapabilityExecuteResponse

type CapabilityExecuteResponse struct {
	OK        bool   `json:"ok"`
	Output    string `json:"output,omitempty"`
	ExitCode  int    `json:"exit_code"`
	LedgerSeq uint64 `json:"ledger_seq,omitempty"`
}

CapabilityExecuteResponse is the result of a capability invocation.

type CapabilityGrantRequest

type CapabilityGrantRequest struct {
	Target string `json:"target"`
}

CapabilityGrantRequest is the body of POST /v1/islands/:name/capability/grants — grant the island permission to invoke a named host capability target.

type CapabilityGrantView

type CapabilityGrantView struct {
	Target    string    `json:"target"`
	GrantedAt time.Time `json:"granted_at"`
}

CapabilityGrantView is one capability grant as returned by the API.

type CapabilityGrantsResponse

type CapabilityGrantsResponse struct {
	Grants []CapabilityGrantView `json:"grants"`
}

CapabilityGrantsResponse is the body of GET /v1/islands/:name/capability/grants.

type ClaudeCredentialsStatus

type ClaudeCredentialsStatus struct {
	// SeedPresent reports whether a materialized seed file exists, i.e.
	// whether new islands will start with Claude credentials.
	SeedPresent   bool      `json:"seed_present"`
	SeedUpdatedAt time.Time `json:"seed_updated_at,omitempty"`
	// HostSource is where the daemon host can read credentials right now:
	// "keychain", "file", or "" when the host has no Claude login (the seed
	// then only refreshes via `dejima auth push`).
	HostSource string `json:"host_source,omitempty"`
}

ClaudeCredentialsStatus is the body of GET /v1/credentials/claude. It never carries the secret itself.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a thin HTTP client for the Dejima API.

func NewTCPClient

func NewTCPClient(host string) (*Client, error)

NewTCPClient returns a Client that talks to a remote dejimad over TCP. The host argument may be a bare "host:port" or a full URL.

func NewTCPClientWithToken

func NewTCPClientWithToken(host, token string) (*Client, error)

NewTCPClientWithToken is NewTCPClient with a bearer token attached to every request: the in-island → dejimad autonomy path. host is typically DEJIMA_HOST (host.docker.internal:<port>) and token is DEJIMA_TOKEN, both injected into the container by the daemon when autonomy is enabled.

func NewUnixClient

func NewUnixClient() (*Client, error)

NewUnixClient returns a Client that talks to dejimad over its Unix socket.

func NewWSLClient added in v0.8.64

func NewWSLClient(distro string) (*Client, error)

NewWSLClient returns a Client that talks to a dejimad running inside a WSL2 distro, tunnelling its Unix socket through `wsl.exe … socat`. This is the "local host on Windows" path: Windows itself can't run dejimad, but WSL2 can, and this reaches it without giving the daemon a TCP listener.

No token: the transport inherits the Unix socket's trust (whoever can run commands in the distro as that user could open the socket directly anyway), exactly like NewUnixClient.

func (*Client) Activity

func (c *Client) Activity(ctx context.Context, f ActivityFilter) (*ActivityResponse, error)

Activity returns the curated team activity feed (newest-first), narrowed by the filter. AuditEnabled in the response reflects whether the full who-did-what log is on (vs only the always-on agent↔host broker records).

func (*Client) AddAgent

func (c *Client) AddAgent(ctx context.Context, name string, req AgentSpecRequest) (*AgentInfo, error)

AddAgent adds an agent to an island.

func (*Client) AddPolicy added in v0.6.0

func (c *Client) AddPolicy(ctx context.Context, req PolicyAddRequest) (*policy.Rule, error)

AddPolicy creates (or replaces) an auto-approve rule (operator).

func (*Client) Aggregate added in v0.8.3

func (c *Client) Aggregate(ctx context.Context) (*AggregateResponse, error)

Aggregate returns the privacy-preserving, host-wide utilization rollup: counts and totals across ALL islands, with no names/repos/owners/per-island rows — so a teammate can see shared-host load without seeing what's running (the multi-tenant design's aggregate; readable by any authenticated caller). The GET /v1/aggregate handler is a1's P3; this client type is the shared contract (field tags locked with a1).

func (*Client) ApproveAction

func (c *Client) ApproveAction(ctx context.Context, id string) error

ApproveAction approves and executes a pending action (operator).

func (*Client) Audit

func (c *Client) Audit(ctx context.Context, q AuditQuery) (*AuditResponse, error)

Audit returns the Ledger (filtered per q) plus its whole-chain verification result.

func (*Client) AuditExport

func (c *Client) AuditExport(ctx context.Context, q AuditQuery, format string) (io.ReadCloser, error)

AuditExport streams the filtered ledger in the given format ("jsonl" or "csv"). The caller owns the returned reader and must Close it.

func (*Client) AuthorizeAccountKey

func (c *Client) AuthorizeAccountKey(ctx context.Context, publicKey string) (string, error)

AuthorizeAccountKey enrolls a public key fleet-wide via the daemon (which performs the write). Lets any operator device self-enroll without copying its key to the daemon host. Returns the key's fingerprint.

func (*Client) BuildImage

func (c *Client) BuildImage(ctx context.Context, out io.Writer) error

BuildImage asks the daemon to rebuild the island image from its embedded build context, copying build output to out. Returns nil only when the daemon confirms the build succeeded.

func (*Client) CallMCP

func (c *Client) CallMCP(ctx context.Context, req MCPCallRequest) (*MCPCallResponse, error)

CallMCP brokers one JSON-RPC call to a granted MCP server.

func (*Client) ClaudeCredentialsStatus

func (c *Client) ClaudeCredentialsStatus(ctx context.Context) (*ClaudeCredentialsStatus, error)

ClaudeCredentialsStatus reports whether the daemon can seed islands with Claude credentials, and from where.

func (*Client) ClearIslandIdentity added in v0.6.0

func (c *Client) ClearIslandIdentity(ctx context.Context, name string) (*IslandInfo, error)

ClearIslandIdentity removes an island's visual-identity override and returns the updated island info (Identity then omitted).

func (*Client) ClearPanic

func (c *Client) ClearPanic(ctx context.Context) (*PanicResponse, error)

ClearPanic removes the PANIC flag and restarts islands whose desired state is running.

func (*Client) ClientHistory

func (c *Client) ClientHistory(ctx context.Context) ([]ClientHistoryEntry, error)

ClientHistory returns the daemon's in-memory attach/detach history.

func (*Client) CloneIsland

func (c *Client) CloneIsland(ctx context.Context, name, newName string) (*IslandInfo, error)

CloneIsland duplicates an island under newName, copying its workspace + home volumes (credentials and git history come along).

func (*Client) ConfigureAgent

func (c *Client) ConfigureAgent(ctx context.Context, island, id string, req AgentConfigRequest) (*AgentConfigResponse, error)

ConfigureAgent sets an agent's LLM provider/model.

func (*Client) CreateIsland

func (c *Client) CreateIsland(ctx context.Context, req CreateIslandRequest) (*CreateIslandResponse, error)

CreateIsland provisions a new island. The returned CreateIslandResponse embeds the IslandInfo; on a token-authenticated create by a Home Island it also carries the child's bearer Token (the parent-child spawn model).

func (*Client) CreateSchedule added in v0.8.3

func (c *Client) CreateSchedule(ctx context.Context, name string, req CreateScheduleRequest) (*ScheduleInfo, error)

CreateSchedule adds a durable scheduled wake to an island.

func (*Client) CreateTerminal

func (c *Client) CreateTerminal(ctx context.Context, label string) (*hostterm.Terminal, error)

CreateTerminal creates a host terminal with an optional label.

func (*Client) CreateToken

func (c *Client) CreateToken(ctx context.Context, req CreateTokenRequest) (*CreateTokenResponse, error)

CreateToken issues an operator bearer token with the given role and optional island scope. The returned CreateTokenResponse carries the bearer Secret — shown exactly once; the daemon stores only its hash.

func (*Client) DaemonHost

func (c *Client) DaemonHost() string

DaemonHost returns the hostname this client talks to (no scheme/port), or "" when the daemon is local (the unix-socket sentinel). Callers needing a reachable address for a *daemon-side* service — e.g. the SSH façade, whose bind the daemon may report host-less as ":2222" — use this to point at the daemon's host rather than the local machine's.

func (*Client) DaemonUpdate

func (c *Client) DaemonUpdate(ctx context.Context, execute, force bool) (*AdminUpdateResponse, error)

DaemonUpdate asks the daemon to update itself. execute=false reports the plan; execute=true applies it (the daemon then restarts, so the connection may drop right after this returns — the Applying flag is the confirmation it began). With execute and clients attached, the daemon defers (Deferred=true) unless force is set, which applies anyway and drops those sessions.

func (*Client) DeleteGitHubIdentity

func (c *Client) DeleteGitHubIdentity(ctx context.Context, name string) (affected []string, err error)

DeleteGitHubIdentity removes a GitHub identity from the daemon and returns the names of any islands that still referenced it, so the caller can warn that those islands will lose this auth on their next reseed.

func (*Client) DeleteIsland

func (c *Client) DeleteIsland(ctx context.Context, name string, force bool) error

DeleteIsland tears down an island (purge). When force is false the daemon refuses if the workspace has uncommitted or unpushed git work; force bypasses that guard.

func (*Client) DeleteProviderCredential

func (c *Client) DeleteProviderCredential(ctx context.Context, provider string) (affected []string, err error)

DeleteProviderCredential removes a provider key and returns the names of any islands that still reference it.

func (*Client) DeleteSchedule added in v0.8.3

func (c *Client) DeleteSchedule(ctx context.Context, name, id string) error

DeleteSchedule removes a scheduled wake by id.

func (*Client) DeleteSecret added in v0.8.28

func (c *Client) DeleteSecret(ctx context.Context, island, key string) error

DeleteSecret removes a secret from an island.

func (*Client) DeleteTerminal

func (c *Client) DeleteTerminal(ctx context.Context, id string) error

DeleteTerminal removes a host terminal (and kills its tmux session).

func (*Client) DenyAction

func (c *Client) DenyAction(ctx context.Context, id, reason string) error

DenyAction denies a pending action (operator). An optional reason is recorded in the ledger.

func (*Client) DialAgentSession

func (c *Client) DialAgentSession(ctx context.Context, name, agentID, label string) (*websocket.Conn, error)

DialAgentSession opens a websocket against a specific agent's session. An empty agentID targets the island's primary agent (the legacy route).

func (*Client) DialIslandShell added in v0.6.0

func (c *Client) DialIslandShell(ctx context.Context, name, label string) (*websocket.Conn, error)

DialIslandShell opens a websocket against an island's in-island shell — a contained interactive bash session at /workspace inside the container. Shared and resumable; not tied to an agent.

func (*Client) DialSession

func (c *Client) DialSession(ctx context.Context, name, label string) (*websocket.Conn, error)

func (*Client) DialTerminalSession

func (c *Client) DialTerminalSession(ctx context.Context, id, label string) (*websocket.Conn, error)

DialTerminalSession opens a websocket against a host terminal's session.

func (*Client) ExecInIsland

func (c *Client) ExecInIsland(ctx context.Context, name string, cmd []string) (*ExecResponse, error)

ExecInIsland runs a one-shot command inside an island and returns its output.

func (*Client) ExposeAction

func (c *Client) ExposeAction(ctx context.Context, island, action string) ([]string, error)

ExposeAction adds a named action type to an island's exposed set (operator).

func (*Client) GetEgress added in v0.6.9

func (c *Client) GetEgress(ctx context.Context, island string) (*EgressEventsResponse, error)

GetEgress returns an island's recent observed outbound connections.

func (*Client) GetEgressPolicy added in v0.6.9

func (c *Client) GetEgressPolicy(ctx context.Context, island string) (*egress.IslandPolicy, error)

GetEgressPolicy returns an island's egress policy (effective default = observe).

func (*Client) GetIsland

func (c *Client) GetIsland(ctx context.Context, name string) (*IslandInfo, error)

GetIsland returns one island's info.

func (*Client) GetSpawnGrant added in v0.6.9

func (c *Client) GetSpawnGrant(ctx context.Context, island string) (*SpawnGrantResponse, error)

GetSpawnGrant returns an island's ephemeral-sub-agent spawn grant (or Granted=false).

func (*Client) GitHubDevicePoll added in v0.8.17

GitHubDevicePoll checks a device-flow session and, once authorized, stores the captured token as the identity named req.Name. State is one of authorization_pending | slow_down | expired | access_denied | authorized; on authorized the response's Identity + Login name the stored credential. Honor the response Interval (the server backs off on slow_down) for the next poll.

func (*Client) GitHubDeviceStart added in v0.8.17

func (c *Client) GitHubDeviceStart(ctx context.Context) (GitHubDeviceStartResponse, error)

GitHubDeviceStart begins a guided device-flow GitHub sign-in (no PAT paste). The returned UserCode + VerificationURI are shown to the operator; poll with SessionID. A daemon with no OAuth app configured returns an error whose message points at the `dejima auth push --github` token path instead.

func (*Client) GrantCapability

func (c *Client) GrantCapability(ctx context.Context, name, target string) (*CapabilityGrantView, error)

GrantCapability grants an island permission to invoke a named host capability.

func (c *Client) GrantLink(ctx context.Context, req LinkGrantRequest) (*link.Grant, error)

GrantLink authorizes a directional inter-island info channel (operator-only).

func (*Client) GrantMCP

func (c *Client) GrantMCP(ctx context.Context, name, server string) (*MCPGrantView, error)

GrantMCP grants an island permission to invoke a named host MCP server.

func (*Client) GrantPortScope

func (c *Client) GrantPortScope(ctx context.Context, name, hostPath, mode string) (*PortScopeView, error)

GrantPortScope grants an island brokered access to a host directory.

func (*Client) Health

func (c *Client) Health(ctx context.Context) error

Health returns nil if dejimad is reachable and healthy.

func (*Client) HibernateIsland

func (c *Client) HibernateIsland(ctx context.Context, name string) (*IslandInfo, error)

HibernateIsland stops the container, preserving volumes.

func (*Client) IslandEvents

func (c *Client) IslandEvents(ctx context.Context, name string) ([]events.Event, error)

IslandEvents returns the recent event log for one island.

func (*Client) ListAccountKeys

func (c *Client) ListAccountKeys(ctx context.Context) ([]SSHKeyInfo, error)

ListAccountKeys returns the fleet-wide authorized SSH keys.

func (*Client) ListAgentTypes

func (c *Client) ListAgentTypes(ctx context.Context) ([]AgentTypeCapability, error)

ListAgentTypes returns the capability descriptors for the built-in agent types.

func (*Client) ListAgents

func (c *Client) ListAgents(ctx context.Context, name string) ([]AgentInfo, error)

ListAgents returns the agents in an island.

func (*Client) ListCapabilityGrants

func (c *Client) ListCapabilityGrants(ctx context.Context, name string) (*CapabilityGrantsResponse, error)

ListCapabilityGrants returns the capability targets an island may invoke.

func (*Client) ListExposedActions

func (c *Client) ListExposedActions(ctx context.Context, island string) ([]string, error)

ListExposedActions returns an island's exposed action types.

func (*Client) ListGitHubIdentities

func (c *Client) ListGitHubIdentities(ctx context.Context) ([]githubid.Meta, error)

ListGitHubIdentities returns the daemon's GitHub identities (no tokens).

func (*Client) ListGitHubRepos

func (c *Client) ListGitHubRepos(ctx context.Context, name string) (repos []githubid.Repo, capped bool, err error)

ListGitHubRepos lists repositories the identity can access, fetched daemon-side so a client without its own gh can still browse. capped is true when the identity sees more repos than the single page returned.

func (*Client) ListGrants added in v0.6.0

func (c *Client) ListGrants(ctx context.Context, name string) (*IslandGrantsResponse, error)

ListGrants returns every grant type an island holds (Port scopes, capability targets, MCP servers, and the inter-island link channels touching it) in one call — the unified view the operator surface exposes at GET /v1/islands/{name}/grants.

func (*Client) ListIslands

func (c *Client) ListIslands(ctx context.Context) ([]IslandInfo, error)

ListIslands returns every island known to the daemon.

func (c *Client) ListLinks(ctx context.Context) ([]link.Grant, error)

ListLinks returns every link grant (operator-only).

func (*Client) ListLocalModels added in v0.8.58

func (c *Client) ListLocalModels(ctx context.Context) (*LocalModelsResponse, error)

ListLocalModels returns pulled models plus the host-aware recommendation.

func (*Client) ListMCPGrants

func (c *Client) ListMCPGrants(ctx context.Context, name string) (*MCPGrantsResponse, error)

ListMCPGrants returns the MCP servers an island may invoke.

func (*Client) ListPendingActions

func (c *Client) ListPendingActions(ctx context.Context) ([]link.ActionRequest, error)

ListPendingActions returns the queued cross-island action approvals (operator).

func (*Client) ListPolicy added in v0.6.0

func (c *Client) ListPolicy(ctx context.Context) ([]policy.Rule, error)

ListPolicy returns the active auto-approve rules (operator).

func (*Client) ListPortScopes

func (c *Client) ListPortScopes(ctx context.Context, name string) (*PortScopesResponse, error)

ListPortScopes returns an island's brokered host-file grants.

func (*Client) ListProviderCredentials

func (c *Client) ListProviderCredentials(ctx context.Context) ([]providercreds.Meta, error)

ListProviderCredentials returns the daemon's LLM provider credentials without their keys (masked hint only).

func (*Client) ListSchedules added in v0.8.3

func (c *Client) ListSchedules(ctx context.Context, name string) ([]ScheduleInfo, error)

ListSchedules returns an island's scheduled wakes.

func (*Client) ListSecrets added in v0.8.28

func (c *Client) ListSecrets(ctx context.Context, island string) ([]secrets.Meta, error)

ListSecrets returns an island's secret names + metadata. Values are never included — the response type has no field for one.

func (*Client) ListTerminals

func (c *Client) ListTerminals(ctx context.Context) ([]hostterm.Terminal, error)

ListTerminals returns the daemon's host terminals.

func (*Client) ListTokens

func (c *Client) ListTokens(ctx context.Context) ([]TokenView, error)

ListTokens returns every issued operator token's metadata (never a secret).

func (*Client) ListWebhooks

func (c *Client) ListWebhooks(ctx context.Context) ([]events.Subscription, error)

ListWebhooks returns every webhook subscription.

func (*Client) LocalInstall added in v0.8.58

func (c *Client) LocalInstall(ctx context.Context, out io.Writer) error

LocalInstall streams a best-effort backend install to out.

func (*Client) LocalOff added in v0.8.58

func (c *Client) LocalOff(ctx context.Context) error

LocalOff deregisters the `local` provider; the backend + pulled models stay.

func (*Client) LocalStatus added in v0.8.58

func (c *Client) LocalStatus(ctx context.Context) (*localmodel.Status, error)

LocalStatus fetches the managed local-model backend status (backend, endpoint, pulled models, host RAM + recommendation).

func (*Client) MoveAgent added in v0.6.0

func (c *Client) MoveAgent(ctx context.Context, name, id string, delta int) error

MoveAgent reorders an agent within its island by delta positions (negative = toward the front), clamped to the ends. Order is cosmetic.

func (*Client) Overview

func (c *Client) Overview(ctx context.Context) (*OverviewResponse, error)

Overview returns server-wide aggregates.

func (*Client) Panic

func (c *Client) Panic(ctx context.Context, reason string) (*PanicResponse, error)

Panic engages the daemon-wide panic stop: every island is stopped and a PANIC flag is written so the daemon won't auto-start them on restart.

func (*Client) PanicStatus

func (c *Client) PanicStatus(ctx context.Context) (*PanicResponse, error)

PanicStatus reports whether panic mode is currently engaged.

func (*Client) PatchEgressPolicy added in v0.6.9

func (c *Client) PatchEgressPolicy(ctx context.Context, island string, patch egress.PolicyPatch) (*egress.IslandPolicy, error)

PatchEgressPolicy applies an incremental change to an island's egress policy (set mode, add/remove allow/deny hosts) and returns the resulting policy.

func (*Client) PollMailbox

func (c *Client) PollMailbox(ctx context.Context, island, agent string, since int64) (*MailboxPollResponse, error)

PollMailbox returns the messages in an island's mailbox visible to agent (or just broadcasts when agent is "") with seq > since.

func (*Client) PortExport

func (c *Client) PortExport(ctx context.Context, name, src string) (*PortExportResponse, error)

PortExport copies a file out of the island into host-owned export staging.

func (*Client) PortIntake

func (c *Client) PortIntake(ctx context.Context, name, scope, srcRel, dest string) (*PortIntakeResponse, error)

PortIntake brokers a host file (within a granted scope) into the island.

func (*Client) PortWrite

func (c *Client) PortWrite(ctx context.Context, name, scope, src, destRel string) (*PortWriteResponse, error)

PortWrite copies a file out of the island into a read-write host scope.

func (*Client) PullLocalModel added in v0.8.58

func (c *Client) PullLocalModel(ctx context.Context, name string, out io.Writer) error

PullLocalModel streams a model pull; name may be a curated alias or a raw ref.

func (*Client) PushClaudeCredentials

func (c *Client) PushClaudeCredentials(ctx context.Context, credentialsJSON []byte) error

PushClaudeCredentials stores a Claude credentials blob on the daemon host as the seed for new islands.

func (*Client) PutGitHubIdentity

func (c *Client) PutGitHubIdentity(ctx context.Context, name string, req PutGitHubIdentityRequest) ([]githubid.Meta, error)

PutGitHubIdentity seeds or updates a named GitHub identity on the daemon.

func (*Client) PutProviderCredential

func (c *Client) PutProviderCredential(ctx context.Context, provider string, req PutProviderCredentialRequest) ([]providercreds.Meta, error)

PutProviderCredential stores or updates a provider key on the daemon.

func (*Client) PutSecret added in v0.8.28

func (c *Client) PutSecret(ctx context.Context, island, key, value string) (secrets.Meta, error)

PutSecret sets or rotates a secret and returns its metadata.

func (*Client) ReadFile

func (c *Client) ReadFile(ctx context.Context, name, path string) (io.ReadCloser, error)

ReadFile streams a file out of the island.

func (*Client) RelabelAgent

func (c *Client) RelabelAgent(ctx context.Context, name, id, label string) (*AgentInfo, error)

RelabelAgent sets an agent's cosmetic label (its id and type are immutable).

func (*Client) RelabelTerminal

func (c *Client) RelabelTerminal(ctx context.Context, id, label string) (*hostterm.Terminal, error)

RelabelTerminal renames a host terminal.

func (*Client) RemoveAgent

func (c *Client) RemoveAgent(ctx context.Context, name, id string) error

RemoveAgent removes an agent from an island by id.

func (*Client) RemoveLocalModel added in v0.8.58

func (c *Client) RemoveLocalModel(ctx context.Context, name string) error

RemoveLocalModel deletes a pulled model from the host backend.

func (*Client) RemovePolicy added in v0.6.0

func (c *Client) RemovePolicy(ctx context.Context, from, to, action string) error

RemovePolicy deletes an auto-approve rule by link+action (operator).

func (*Client) RequestLinkAction

func (c *Client) RequestLinkAction(ctx context.Context, island string, req LinkActionRequest) (*LinkActionResponse, error)

RequestLinkAction asks another island to run a named action over a granted channel. The response says whether it executed (pre-authorized) or is pending operator approval.

func (*Client) ResetIsland

func (c *Client) ResetIsland(ctx context.Context, name string) (*IslandInfo, error)

ResetIsland clears agent state, preserves workspace.

func (*Client) RestartAgent added in v0.8.58

func (c *Client) RestartAgent(ctx context.Context, name, id string, resume bool) error

RestartAgent relaunches one agent in place (kill + re-create its tmux session) so it starts in a fresh login shell and picks up a changed environment, e.g. a newly added secret. resume continues the agent's prior conversation when the framework supports it (claude-code).

func (*Client) RevokeAllSessions

func (c *Client) RevokeAllSessions(ctx context.Context) (int, error)

RevokeAllSessions drops every active client websocket. Returns the count.

func (*Client) RevokeCapability

func (c *Client) RevokeCapability(ctx context.Context, name, target string) error

RevokeCapability drops a capability grant by target name.

func (c *Client) RevokeLink(ctx context.Context, from, to, topic string) error

RevokeLink drops a link grant (operator-only).

func (*Client) RevokeMCP

func (c *Client) RevokeMCP(ctx context.Context, name, server string) error

RevokeMCP drops an MCP-server grant by name.

func (*Client) RevokePortScope

func (c *Client) RevokePortScope(ctx context.Context, name, scope string) error

RevokePortScope drops a grant by scope name.

func (*Client) RevokeSpawnGrant added in v0.6.9

func (c *Client) RevokeSpawnGrant(ctx context.Context, island string) error

RevokeSpawnGrant removes an island's spawn grant (operator-only).

func (*Client) RevokeToken

func (c *Client) RevokeToken(ctx context.Context, id string) error

RevokeToken deletes an operator token by id.

func (c *Client) SendLink(ctx context.Context, island string, req LinkSendRequest) (*mailbox.Message, error)

SendLink sends an info message from island to a specific agent in another island over a granted channel; it's delivered into that agent's mailbox.

func (*Client) SendMailbox

func (c *Client) SendMailbox(ctx context.Context, island string, req MailboxSendRequest) (*MailboxSendResponse, error)

SendMailbox posts a message into an island's intra-island mailbox. The response embeds the delivered mailbox.Message (so existing callers read .Seq/.To unchanged) plus the additive UnknownRecipient/Roster signal the CLI uses to warn when a directed `--to` matched no agent in the roster.

func (*Client) SetIslandHibernation added in v0.8.2

func (c *Client) SetIslandHibernation(ctx context.Context, name string, noHibernate bool) (*IslandInfo, error)

SetIslandHibernation pins an island awake (noHibernate=true) or releases it back to idle auto-hibernate (false). Leaves the title untouched.

func (*Client) SetIslandIdentity added in v0.6.0

func (c *Client) SetIslandIdentity(ctx context.Context, name, color, glyph string) (*IslandInfo, error)

SetIslandIdentity sets an island's operator-chosen visual identity (color + glyph) override and returns the updated island info. Color must be a hex string (#rgb or #rrggbb); glyph must be exactly one rune.

func (*Client) SetIslandTitle

func (c *Client) SetIslandTitle(ctx context.Context, name, title string) (*IslandInfo, error)

SetIslandTitle sets an island's cosmetic display title (empty clears it).

func (*Client) SetSpawnGrant added in v0.6.9

func (c *Client) SetSpawnGrant(ctx context.Context, island string, req SpawnGrantRequest) (*SpawnGrantResponse, error)

SetSpawnGrant grants (or updates) an island's spawn budget (operator-only).

func (*Client) StreamLogs

func (c *Client) StreamLogs(ctx context.Context, name, agentID string, follow bool) (io.ReadCloser, error)

StreamLogs returns a reader yielding the container's logs. follow keeps the stream open until ctx is canceled. Uses the timeout-free stream path so a followed stream isn't cut off by the standard 30s client timeout.

func (*Client) SubscribeWebhook

func (c *Client) SubscribeWebhook(ctx context.Context, url, secret string, eventTypes []events.Type) (*events.Subscription, error)

SubscribeWebhook registers a webhook URL with the daemon.

func (*Client) UnexposeAction

func (c *Client) UnexposeAction(ctx context.Context, island, action string) error

UnexposeAction removes an exposed action type (operator).

func (*Client) UnsubscribeWebhook

func (c *Client) UnsubscribeWebhook(ctx context.Context, id string) error

UnsubscribeWebhook removes a webhook subscription by ID.

func (*Client) UpdateIslandResources

func (c *Client) UpdateIslandResources(ctx context.Context, name string, req UpdateResourcesRequest) (*UpdateResourcesResponse, error)

UpdateIslandResources sets an island's memory limit and/or OOM priority. Memory applies live; an OOM-priority change reports RestartRequired (it takes effect on the next container recreate).

func (*Client) UpgradeIsland

func (c *Client) UpgradeIsland(ctx context.Context, name string) (*IslandInfo, error)

UpgradeIsland recreates an island's container against the current island image, preserving both workspace and agent state.

func (*Client) WakeIsland

func (c *Client) WakeIsland(ctx context.Context, name string) (*IslandInfo, error)

WakeIsland starts a hibernated island.

func (*Client) WatchActions added in v0.6.0

func (c *Client) WatchActions(ctx context.Context) (io.ReadCloser, error)

WatchActions opens an SSE stream of pending action approvals (`data: <JSON>` frames). The caller owns the returned reader and must Close it; cancel ctx to stop. Uses the timeout-free stream path so the long-lived stream isn't cut at the 30s default.

func (*Client) WorkspaceReady

func (c *Client) WorkspaceReady(ctx context.Context, name string) (WorkspaceReadyResponse, error)

WorkspaceReady reports whether the island's repo clone has landed in /workspace yet. Used by `dejima connect` to wait out provisioning.

func (*Client) WriteFile

func (c *Client) WriteFile(ctx context.Context, name, path string, body io.Reader) error

WriteFile uploads body into a file inside the island.

type ClientHistoryEntry

type ClientHistoryEntry struct {
	Label      string    `json:"label"`
	Island     string    `json:"island"`
	AttachedAt time.Time `json:"attached_at"`
	DetachedAt time.Time `json:"detached_at,omitempty"`
}

ClientHistoryEntry is one row in the recent-clients ring buffer.

type CloneIslandRequest

type CloneIslandRequest struct {
	NewName string `json:"new_name"`
}

CloneIslandRequest is the body of POST /v1/islands/{name}/clone.

type CreateIslandRequest

type CreateIslandRequest struct {
	Name      string    `json:"name,omitempty"`  // optional; derived from repo if empty
	Repo      string    `json:"repo"`            // required
	Agent     string    `json:"agent,omitempty"` // defaults to "claude-code"
	Image     string    `json:"image,omitempty"` // defaults to "dejima/island:latest"
	Resources Resources `json:"resources,omitempty"`
	// SeedPath, when set, is a host path bind-mounted read-only as the clone
	// source (see reposrc local-copy mode). Only valid against a local daemon;
	// Repo then holds the upstream URL to set as origin, or "" for no remote.
	SeedPath string `json:"seed_path,omitempty"`
	// Cmd is the entrypoint command for agent="headless" islands (e.g.
	// "python my_loop.py"). Required when Agent is "headless"; ignored
	// otherwise. The container runs the command via /bin/sh -c, so shell
	// quoting applies.
	Cmd string `json:"cmd,omitempty"`
	// Agents, when non-empty, seeds the island with multiple agents: element 0
	// is the primary, the rest are added as co-located agents at provision time.
	// When empty, the scalar Agent/Cmd above describe a single agent (back-compat).
	Agents []AgentSpecRequest `json:"agents,omitempty"`
	// Role is the island's purpose: "" (work island, default) or "home" (a Home
	// Island hosting an assistant brain). A home island must be headless (+cmd).
	Role string `json:"role,omitempty"`
	// GitHubIdentity names which daemon GitHub identity this island clones and
	// pushes as (see GET /v1/credentials/github). Empty uses the daemon default,
	// or the host's ~/.config/gh when no identities are configured.
	GitHubIdentity string `json:"github_identity,omitempty"`
	// Owner is a free-form creator label (e.g. "alice@laptop") and Tags are
	// free-form key=value labels (team=web, …); both are informational metadata
	// surfaced in IslandInfo for wrapper dashboards. Optional.
	Owner string            `json:"owner,omitempty"`
	Tags  map[string]string `json:"tags,omitempty"`
	// AllowNoIdentity overrides the doomed-private-clone gate: normally a remote
	// repo that isn't anonymously cloneable and has no GitHub identity is rejected
	// at create (it would come up as an empty, repo-less island). Set true (CLI
	// `--force`) to create anyway and authenticate later.
	AllowNoIdentity bool `json:"allow_no_identity,omitempty"`
}

CreateIslandRequest is the body of POST /v1/islands.

type CreateIslandResponse

type CreateIslandResponse struct {
	IslandInfo
	Token string `json:"token,omitempty"`
}

CreateIslandResponse is the result of POST /v1/islands: an IslandInfo (JSON-flattened via embedding) plus, only on a token-authenticated create by a Home Island, the new island's bearer Token. This is the parent-child spawn model — the parent brain receives the child's token and drives it over the same autonomy path, so there is no god-token. Operator-driven creates (unix socket / tailnet) leave Token empty, making the JSON byte-identical to a bare IslandInfo for existing clients.

type CreateScheduleRequest added in v0.8.3

type CreateScheduleRequest struct {
	Every string `json:"every,omitempty"`
	At    string `json:"at,omitempty"`
	Task  string `json:"task,omitempty"`
	Agent string `json:"agent,omitempty"`
}

CreateScheduleRequest is the body of POST /v1/islands/{name}/schedules. Exactly one of Every (recurring Go duration, e.g. "720h") or At (one-shot RFC3339 time) is required. Task is an optional prompt injected into Agent (id/label; ""=the primary) once the island wakes.

type CreateTerminalRequest

type CreateTerminalRequest struct {
	Label string `json:"label,omitempty"`
}

CreateTerminalRequest is the body of POST /v1/terminals (label optional).

type CreateTokenRequest

type CreateTokenRequest struct {
	Label string `json:"label,omitempty"`
	// Role is "owner", "operator", or "viewer".
	Role string `json:"role"`
	// Owner scopes the token to a tenant: an operator/viewer token sees + acts on
	// only the islands that tenant owns (and islands it creates become the
	// tenant's). Empty defaults to the host owner — i.e. an unscoped operator token
	// behaves as before (full access to the host operator's fleet). A RoleOwner
	// token is the host admin and sees all regardless. Owner-only to set (this
	// whole surface is capOwner).
	Owner string `json:"owner,omitempty"`
	// Islands optionally further narrows the token to specific island names; empty
	// grants it across all the owner's islands (still bounded by Role + Owner).
	Islands []string `json:"islands,omitempty"`
}

CreateTokenRequest is the body of POST /v1/tokens.

type CreateTokenResponse

type CreateTokenResponse struct {
	Token  TokenView `json:"token"`
	Secret string    `json:"secret"`
}

CreateTokenResponse carries the new token's metadata plus its bearer secret — the ONLY time the secret is ever returned. It is not stored in the clear, so a lost secret means minting a new token, not recovering this one.

type DeleteGitHubIdentityResponse

type DeleteGitHubIdentityResponse struct {
	AffectedIslands []string `json:"affected_islands,omitempty"`
}

DeleteGitHubIdentityResponse reports which islands still referenced the identity that was just deleted. Those islands keep working until their next credential reseed (reset/upgrade), at which point they fall back to the host gh or lose push auth — so the caller should warn about them.

type DeleteProviderCredentialResponse

type DeleteProviderCredentialResponse struct {
	AffectedIslands []string `json:"affected_islands,omitempty"`
}

DeleteProviderCredentialResponse reports which islands still reference the provider that was just deleted (their agents will read missing-provider-auth until reconfigured or pointed at another provider).

type DenyActionRequest added in v0.6.0

type DenyActionRequest struct {
	Reason string `json:"reason,omitempty"`
}

DenyActionRequest is the optional body of POST .../deny: a human-readable reason recorded in the ledger.

type EgressEventsResponse added in v0.6.9

type EgressEventsResponse struct {
	Events []egress.Event `json:"events"`
}

EgressEventsResponse is the read-API shape for an island's recent outbound connections, as observed by the egress proxy (Phase 1). Events is empty when the proxy is disabled or the island hasn't connected out yet.

type ErrorResponse

type ErrorResponse struct {
	Error string `json:"error"`
}

ErrorResponse is the body of any non-2xx response.

type ExecRequest

type ExecRequest struct {
	Cmd []string `json:"cmd"`
}

ExecRequest is the body of POST /v1/islands/:name/exec.

type ExecResponse

type ExecResponse struct {
	Stdout   string `json:"stdout"`
	Stderr   string `json:"stderr"`
	ExitCode int    `json:"exit_code"`
}

ExecResponse is returned by POST /v1/islands/:name/exec.

type GitHubDevicePollRequest added in v0.8.17

type GitHubDevicePollRequest struct {
	SessionID string `json:"session_id"`
	Name      string `json:"name"`              // identity name to store the captured token under
	Default   bool   `json:"default,omitempty"` // host owner only
	Shared    bool   `json:"shared,omitempty"`  // host owner only
}

GitHubDevicePollRequest is the body of POST /v1/credentials/github/device-flow/poll.

type GitHubDevicePollResponse added in v0.8.17

type GitHubDevicePollResponse struct {
	State    string `json:"state"`
	Interval int    `json:"interval,omitempty"`
	Identity string `json:"identity,omitempty"`
	Login    string `json:"login,omitempty"`
}

GitHubDevicePollResponse reports the flow state. State is one of authorization_pending | slow_down | expired | access_denied | authorized. On authorized, Identity + Login name the stored credential; on pending/slow_down, Interval is the seconds to wait before polling again.

type GitHubDeviceStartResponse added in v0.8.17

type GitHubDeviceStartResponse struct {
	SessionID       string `json:"session_id"`
	UserCode        string `json:"user_code"`
	VerificationURI string `json:"verification_uri"`
	ExpiresIn       int    `json:"expires_in"`
	Interval        int    `json:"interval"`
	Scopes          string `json:"scopes"` // surfaced so the UX can state what's granted
}

GitHubDeviceStartResponse is the body of POST /v1/credentials/github/device-flow/start. The client shows UserCode + VerificationURI and polls with SessionID. The device_code that exchanges for the token is held server-side and never returned.

type GitHubIdentitiesResponse

type GitHubIdentitiesResponse struct {
	Identities []githubid.Meta `json:"identities"`
}

GitHubIdentitiesResponse is the body of GET /v1/credentials/github: the daemon's GitHub identities without their tokens.

type GitHubReposResponse

type GitHubReposResponse struct {
	Repos  []githubid.Repo `json:"repos"`
	Capped bool            `json:"capped,omitempty"`
}

GitHubReposResponse is the body of GET /v1/credentials/github/:name/repos. Capped is true when the identity can see more repos than the single page returned, so the browser can say "showing the first N".

type GitInfo

type GitInfo struct {
	Branch     string `json:"branch"`
	Clean      bool   `json:"clean"`
	Ahead      int    `json:"ahead"`
	Behind     int    `json:"behind"`
	DirtyFiles int    `json:"dirty_files"`
}

GitInfo summarizes the workspace's git state. Only populated on the detail endpoint (GET /v1/islands/:name) and only for running islands. Computed lazily via container exec and cached briefly to avoid spamming the island.

type IslandDisk

type IslandDisk struct {
	WorkspaceBytes int64 `json:"workspace_bytes"`
	HomeBytes      int64 `json:"home_bytes"`
	TotalBytes     int64 `json:"total_bytes"`
}

IslandDisk reports an island's on-disk volume usage (detail endpoint only; from `docker system df -v`, cached). Bytes are 0 when the storage driver doesn't report size. WorkspaceBytes is the code volume, HomeBytes the per-island home (creds + agent state); Total is their sum.

type IslandGrantsResponse added in v0.6.0

type IslandGrantsResponse struct {
	Port       []PortScopeView       `json:"port"`
	Capability []CapabilityGrantView `json:"capability"`
	MCP        []MCPGrantView        `json:"mcp"`
	Links      []link.Grant          `json:"links"`
}

IslandGrantsResponse is the body of GET /v1/islands/{name}/grants — every grant type an island holds, in one typed shape. The per-type fields mirror the element types of the existing list endpoints (PortScopesResponse.Scopes, CapabilityGrantsResponse.Grants, MCPGrantsResponse.Grants, LinksResponse.Grants), so a consumer that already knows those shapes needs no new types. Each slice is non-nil (empty, never null) so a fresh deny-all island serializes as empty arrays rather than nulls. Links are filtered to the channels that touch this island (as From or To).

type IslandHealth

type IslandHealth struct {
	OOMKilled    bool `json:"oom_killed"`
	RestartCount int  `json:"restart_count"`
	ExitCode     int  `json:"exit_code,omitempty"`
}

IslandHealth surfaces crash-relevant facts that a remote client can't observe itself (they require container-engine access). Populated on the detail endpoint only. RestartCount > 0 or OOMKilled signal an unhealthy island.

type IslandIdentity added in v0.6.0

type IslandIdentity struct {
	Color string `json:"color"`
	Glyph string `json:"glyph"`
}

IslandIdentity is an operator-chosen color + glyph override for an island. Color is a hex string (#rgb or #rrggbb); Glyph is exactly one rune.

type IslandInfo

type IslandInfo struct {
	Name string `json:"name"`
	// Title is the cosmetic display name; empty means show Name. Name remains the
	// durable handle the CLI addresses by.
	Title string `json:"title,omitempty"`
	Repo  string `json:"repo"`
	// Agent is the island's agent type (e.g. "claude-code", "codex", "headless").
	Agent string `json:"agent"`
	Image string `json:"image"`
	// Cmd is the user-supplied entrypoint for headless islands; empty for
	// the built-in CLI agents.
	Cmd string `json:"cmd,omitempty"`
	// Role is "" (work island) or "home" (a Home Island hosting an assistant brain).
	Role  string            `json:"role,omitempty"`
	Owner string            `json:"owner,omitempty"`
	Tags  map[string]string `json:"tags,omitempty"`
	// GitHubCredMissing is set when the island NAMES a GitHub identity that no
	// longer resolves for its tenant (deleted, or now out-of-tenant under the
	// owner-scoping rules) — so clone/push will fail. A health surface so the
	// operator/member can re-connect (docs/github-identities.md), not a silent
	// break. Not set for islands that name no identity.
	GitHubCredMissing bool `json:"github_cred_missing,omitempty"`
	// SecretsCount is how many secrets the island has. Read from the per-island
	// metadata only — never the keychain — so listing stays cheap enough for the
	// dashboard's poll. A count, never the names' values.
	SecretsCount int    `json:"secrets_count,omitempty"`
	State        string `json:"state"`     // desired state from config
	Container    string `json:"container"` // observed status from runtime
	// NoHibernate is true when the island is pinned awake (exempt from idle
	// auto-hibernate). Set via PATCH /v1/islands/{name} (dejima pin/unpin).
	NoHibernate bool            `json:"no_hibernate,omitempty"`
	CreatedAt   time.Time       `json:"created_at"`
	LastUsedAt  time.Time       `json:"last_used_at"`
	Attached    []PresenceEntry `json:"attached,omitempty"`
	Stats       *IslandStats    `json:"stats,omitempty"`
	AgentState  *AgentStateInfo `json:"agent_state,omitempty"`
	Git         *GitInfo        `json:"git,omitempty"`
	Health      *IslandHealth   `json:"health,omitempty"`
	Disk        *IslandDisk     `json:"disk,omitempty"`
	// Resources are the island's configured caps + OOM priority (nil OOMPriority
	// means the smart default applies). Present on both the list and detail
	// endpoints — cheap (read from island config) and needed alongside Stats so a
	// client can compute usage as a "% of cap".
	Resources *Resources `json:"resources,omitempty"`
	// Agents is the island's agents. For islands created before multi-agent
	// support it carries a single synthesized entry mirroring Agent.
	Agents []AgentInfo `json:"agents,omitempty"`
	// BuiltVersion / UpgradedVersion are the version-skew stamp: the daemon build
	// the island's container was first created against, and the build of its most
	// recent `dejima upgrade` recreate. A stamp behind the running daemon means the
	// island was built from an older image and may carry stale /opt shims. Both
	// empty for islands created before version stamping (provenance unknown).
	BuiltVersion    string `json:"built_version,omitempty"`
	UpgradedVersion string `json:"upgraded_version,omitempty"`
	// NeverHeardFrom is the zero-heartbeat liveness flag: true when the island's
	// container is running yet NO agent has emitted a single agent-state event
	// since boot, and the island is past a short grace window (so a just-started
	// island isn't falsely flagged). This is the direct broken-shim signal — a
	// stale socket→TCP notify hook silently no-ops, so the heartbeat never fires
	// and mail-nudges / idle-hibernate / the idle metric all go dark with no error.
	NeverHeardFrom bool `json:"never_heard_from,omitempty"`
	// Identity is the operator-set visual identity (color + glyph) for the island.
	// Omitted when unset — the TUI then falls back to its deterministic per-name
	// default (islandIdentity). Set/cleared via PUT /v1/islands/{name}/identity.
	// (Backend populate + the PUT route are d5's; this field is the shared seam.)
	Identity *IslandIdentity `json:"identity,omitempty"`
}

IslandInfo is the public view of an island returned by the API.

type IslandStats

type IslandStats struct {
	MemoryUsageBytes uint64  `json:"memory_usage_bytes"`
	MemoryLimitBytes uint64  `json:"memory_limit_bytes"`
	CPUPercent       float64 `json:"cpu_percent"`
}

IslandStats is a snapshot of the container's resource usage.

type LinkActionRequest

type LinkActionRequest struct {
	To        string `json:"to"`
	ToAgent   string `json:"to_agent"`
	Topic     string `json:"topic"`
	Action    string `json:"action"`
	Params    string `json:"params,omitempty"`
	FromAgent string `json:"from_agent,omitempty"`
}

LinkActionRequest is the body of POST /v1/islands/{name}/link/action: island {name} (sender, token-pinned) asks {to}'s agent {to_agent} to run the NAMED, typed {action} (with {params}) over the granted channel {topic}. There is no free-form path — only named actions the destination exposed.

type LinkActionResponse

type LinkActionResponse struct {
	Status  string `json:"status"` // "executed" | "pending"
	Pending string `json:"pending,omitempty"`
}

LinkActionResponse reports the outcome of an action request: "executed" (a pre-authorized action delivered immediately) or "pending" (queued for operator approval, with the pending id).

type LinkExposedResponse

type LinkExposedResponse struct {
	Island  string   `json:"island"`
	Actions []string `json:"actions"`
}

LinkExposedResponse is an island's exposed action types.

type LinkGrantRequest

type LinkGrantRequest struct {
	From  string `json:"from"`
	To    string `json:"to"`
	Topic string `json:"topic"`
	// Actions pre-authorizes these named action types on this channel (Lane 5
	// Phase 3). Empty = info-only: any action invocation goes to the approval
	// queue. An action still also requires the destination island to expose it.
	Actions []string `json:"actions,omitempty"`
}

LinkGrantRequest is the body of POST /v1/links: an operator authorizes a directional info channel from→to on a topic. Operator-only. The grant is island→island; the recipient agent is chosen per message, not granted.

type LinkPendingResponse

type LinkPendingResponse struct {
	Pending []link.ActionRequest `json:"pending"`
}

LinkPendingResponse is the queued action approvals (operator view).

type LinkSendRequest

type LinkSendRequest struct {
	To        string `json:"to"`         // destination island
	ToAgent   string `json:"to_agent"`   // destination agent (required — no island-wide broadcast)
	Topic     string `json:"topic"`      // the granted topic
	Payload   string `json:"payload"`    //
	FromAgent string `json:"from_agent"` // sending agent id (optional)
}

LinkSendRequest is the body of POST /v1/islands/{name}/link/send: island {name} (the sender, pinned by its token) sends an info message addressed to a specific agent (ToAgent) in island To, on Topic. Allowed only if an operator granted {name}→To on Topic. FromAgent is the sending agent's id (self-reported within the sender's own trust domain; the island half of provenance is daemon-stamped, not this).

type LinksResponse

type LinksResponse struct {
	Grants []link.Grant `json:"grants"`
}

LinksResponse is the list of grants (GET /v1/links).

type ListSSHKeysResponse

type ListSSHKeysResponse struct {
	Keys []SSHKeyInfo `json:"keys"`
}

ListSSHKeysResponse is the set of fleet-wide authorized keys.

type LocalModelsResponse added in v0.8.58

type LocalModelsResponse struct {
	Pulled      []localmodel.InstalledModel `json:"pulled"`
	Recommended localmodel.Recommendation   `json:"recommended"`
}

LocalModelsResponse is the `GET /v1/local/models` body: what's pulled on the host plus the host-aware recommendation of what to run.

type MCPCallRequest

type MCPCallRequest struct {
	Island string          `json:"island,omitempty"`
	Server string          `json:"server"`
	Method string          `json:"method"`
	Params json.RawMessage `json:"params,omitempty"`
}

MCPCallRequest is the body of POST /v1/mcp/call. Island is supplied by an operator caller; a token-authenticated in-island caller (once that path is wired) is pinned to its own island and Island is ignored. Method must be in the brokered surface (mcpbroker.AllowedMethods); Params is the JSON-RPC params.

type MCPCallResponse

type MCPCallResponse struct {
	OK        bool            `json:"ok"`
	IsError   bool            `json:"is_error,omitempty"`
	Result    json.RawMessage `json:"result,omitempty"`
	LedgerSeq uint64          `json:"ledger_seq,omitempty"`
}

MCPCallResponse is the result of a brokered MCP call. OK reports protocol success with no application error; IsError reports a tools/call that completed with isError:true (the call ran — the tool reported a problem). Result is the raw JSON-RPC result.

type MCPGrantRequest

type MCPGrantRequest struct {
	Server string `json:"server"`
}

MCPGrantRequest is the body of POST /v1/islands/:name/mcp/grants — grant the island permission to invoke a named host MCP server.

type MCPGrantView

type MCPGrantView struct {
	Server    string    `json:"server"`
	GrantedAt time.Time `json:"granted_at"`
}

MCPGrantView is one MCP-server grant as returned by the API.

type MCPGrantsResponse

type MCPGrantsResponse struct {
	Grants []MCPGrantView `json:"grants"`
}

MCPGrantsResponse is the body of GET /v1/islands/:name/mcp/grants.

type MailboxPollResponse

type MailboxPollResponse struct {
	Messages []mailbox.Message `json:"messages"`
	Latest   int64             `json:"latest"`
}

MailboxPollResponse is the body of GET /v1/islands/{name}/mailbox: the visible messages after the requested cursor, plus the island's latest seq (a cursor to poll from next).

type MailboxSendRequest

type MailboxSendRequest struct {
	From    string `json:"from,omitempty"`
	To      string `json:"to,omitempty"`
	Topic   string `json:"topic,omitempty"`
	Payload string `json:"payload"`
}

MailboxSendRequest is the body of POST /v1/islands/{name}/mailbox. `from` is the sender agent id (self-reported — same-island agents are one trust domain); `to` empty broadcasts to the island.

type MailboxSendResponse added in v0.6.9

type MailboxSendResponse struct {
	mailbox.Message
	UnknownRecipient bool          `json:"unknown_recipient,omitempty"`
	Roster           []RosterAgent `json:"roster,omitempty"`
}

MailboxSendResponse is the body of POST /v1/islands/{name}/mailbox. The delivered message is embedded inline, so the JSON stays byte-compatible with the old (bare MailboxMessage) response — existing clients that decode a mailbox.Message keep working. The added fields are additive + omitempty:

  • UnknownRecipient is true when a DIRECTED send (`to` non-empty) named a recipient that matched NEITHER an id NOR a label in the island's CURRENT roster. Delivery STILL happened (the mailbox is intentionally permissive — you may address a handle that isn't a live agent yet, and the roster can be transiently empty on daemon restart, so a strict reject would false-fail legitimate sends). The CLI surfaces this as a sender-side warning.
  • Roster is the island's current agents at send time, returned so the CLI can render "delivered anyway, current roster: …" without re-deriving (and re- racing) the roster. Present only alongside UnknownRecipient.

The signal is server-authoritative: the daemon checks against the same roster it just resolved the recipient against, so a transient roster gap can't make the CLI warn from a roster that disagrees with what was actually checked.

type MoveAgentRequest added in v0.6.0

type MoveAgentRequest struct {
	Delta int `json:"delta"`
}

updateAgent changes an agent's cosmetic label. Everything else (id, type, worktree, session) is immutable — the id is the stable handle, the label is the renamable display name, mirroring the island Name / agent Label split. MoveAgentRequest reorders an agent within its island's list. Delta is the number of positions to shift (negative = toward the front); it's clamped to the ends.

type OverviewResponse

type OverviewResponse struct {
	TotalIslands       int       `json:"total_islands"`
	Running            int       `json:"running"`
	Hibernated         int       `json:"hibernated"`
	Errored            int       `json:"errored"`
	AttachedClients    int       `json:"attached_clients"`
	MemoryUsageBytes   uint64    `json:"memory_usage_bytes"`
	MemoryLimitBytes   uint64    `json:"memory_limit_bytes"`
	CPUPercent         float64   `json:"cpu_percent"`
	DaemonStartedAt    time.Time `json:"daemon_started_at"`
	WebhookCount       int       `json:"webhook_count"`
	DockerReachable    bool      `json:"docker_reachable"`
	IslandImagePresent bool      `json:"island_image_present"`
	IslandImage        string    `json:"island_image,omitempty"`
	// HostTerminalsEnabled lets a client (the TUI) show the Host section only
	// when the daemon was started with --host-terminals.
	HostTerminalsEnabled bool `json:"host_terminals_enabled"`
	// SSHAddr is the SSH-façade listen addr, empty unless dejimad was started
	// with --ssh. Lets clients (the TUI, `dejima ssh config/info`) show the
	// connection target and generate an ssh config entry. The bind host may be
	// wildcard/empty (":2222"); clients resolve a reachable host themselves.
	SSHAddr string `json:"ssh_addr,omitempty"`
	// SSHHostKey is the façade's host public key (OpenSSH "ssh-ed25519 AAAA…"
	// line), served with SSHAddr so a client pins it in a known_hosts file it
	// manages — so `dejima agent open`'s tunnel verifies the key over the trusted
	// API rather than TOFU, and a rotated key self-heals instead of failing with
	// "REMOTE HOST IDENTIFICATION HAS CHANGED". Empty on daemons predating this.
	SSHHostKey string `json:"ssh_host_key,omitempty"`
	// DaemonVersion / APIVersion let a client detect skew against the daemon.
	// APIVersion is 0 from daemons predating version reporting.
	DaemonVersion string `json:"daemon_version,omitempty"`
	APIVersion    int    `json:"api_version,omitempty"`
	// Panicked is true while the ~/.dejima/PANIC flag is set: every island is
	// stopped and the daemon won't auto-start them until panic is cleared.
	Panicked bool `json:"panicked,omitempty"`
	// Substrate memory: HostMemoryBytes is the daemon host's physical RAM;
	// VMMemoryBytes is the container runtime's memory ceiling (the colima/Docker
	// Desktop VM total on macOS — the pool ALL islands share); VMRecommendedBytes
	// is the size dejima suggests for this host. When the VM is far below the
	// recommendation the TUI raises a substrate banner — a too-small VM is the
	// root cause of island OOMs (#23). All 0 when undeterminable.
	HostMemoryBytes    uint64 `json:"host_memory_bytes,omitempty"`
	VMMemoryBytes      uint64 `json:"vm_memory_bytes,omitempty"`
	VMRecommendedBytes uint64 `json:"vm_recommended_bytes,omitempty"`
	// Owner / Role identify the AUTHENTICATED caller (multi-tenant "who am I"), so
	// a client can drive the own-vs-all lens: the host owner (role "owner") sees
	// all islands and can filter to Owner; a teammate is already server-filtered.
	// Empty on callers without a resolved identity.
	Owner string `json:"owner,omitempty"`
	Role  string `json:"role,omitempty"`
}

OverviewResponse is the body of GET /v1/overview — server-wide totals plus substrate health (Docker reachable, island image present).

type PanicRequest

type PanicRequest struct {
	Reason string `json:"reason,omitempty"`
}

PanicRequest is the optional body of POST /v1/panic.

type PanicResponse

type PanicResponse struct {
	Panicked bool   `json:"panicked"`
	Affected int    `json:"affected"`
	Reason   string `json:"reason,omitempty"`
}

PanicResponse is returned by the /v1/panic endpoints. Affected is the number of islands stopped (on engage) or restarted (on clear).

type PolicyAddRequest added in v0.6.0

type PolicyAddRequest struct {
	From     string `json:"from"`
	To       string `json:"to"`
	Action   string `json:"action"`
	MaxCount int    `json:"max_count,omitempty"`
	TTL      string `json:"ttl,omitempty"`
}

PolicyAddRequest creates a scoped auto-approve rule: for link From→To, auto-approve action-type Action up to MaxCount times (<=0 = unlimited within the window) until TTL elapses. TTL is a Go duration string ("1h", "30m"); "" means no expiry (discouraged). Destructive actions are never auto-approved regardless of any rule — that's enforced at request time, not here.

type PolicyListResponse added in v0.6.0

type PolicyListResponse struct {
	Rules []policy.Rule `json:"rules"`
}

PolicyListResponse is the operator view of active auto-approve rules.

type PortExportRequest

type PortExportRequest struct {
	Src string `json:"src"` // container path to export
}

PortExportRequest is the body of POST /v1/islands/:name/port/export — a brokered copy of a file out of the island into the host-owned export staging area (~/.dejima/projects/<name>/exports/). It never writes into a user scope; writing into a granted scope is the read-write milestone.

type PortExportResponse

type PortExportResponse struct {
	Src    string `json:"src"`  // container path
	Dest   string `json:"dest"` // host staging path
	Bytes  int64  `json:"bytes"`
	SHA256 string `json:"sha256"`
}

PortExportResponse reports a completed export to staging.

type PortIntakeRequest

type PortIntakeRequest struct {
	Scope  string `json:"scope"`          // scope name to read from
	SrcRel string `json:"src_rel"`        // path relative to the scope's host root
	Dest   string `json:"dest,omitempty"` // container path; default /intake/<scope>/<src_rel>
}

PortIntakeRequest is the body of POST /v1/islands/:name/port/intake — a brokered, read-only copy of a host file (within a granted scope) into the island.

type PortIntakeResponse

type PortIntakeResponse struct {
	Scope  string `json:"scope"`
	Src    string `json:"src"`  // resolved host path
	Dest   string `json:"dest"` // container path
	Bytes  int64  `json:"bytes"`
	SHA256 string `json:"sha256"`
}

PortIntakeResponse reports a completed intake.

type PortScopeRequest

type PortScopeRequest struct {
	HostPath string `json:"host_path"`
	Mode     string `json:"mode"` // "ro" (V1); "rw" is rejected until the read-write milestone
}

PortScopeRequest is the body of POST /v1/islands/:name/port/scopes.

type PortScopeView

type PortScopeView struct {
	Name      string    `json:"name"`
	HostPath  string    `json:"host_path"`
	Mode      string    `json:"mode"`
	GrantedAt time.Time `json:"granted_at"`
}

PortScopeView is one brokered host-file grant as returned by the API.

type PortScopesResponse

type PortScopesResponse struct {
	Scopes []PortScopeView `json:"scopes"`
}

PortScopesResponse is the body of GET /v1/islands/:name/port/scopes.

type PortWriteRequest

type PortWriteRequest struct {
	Scope   string `json:"scope"`
	Src     string `json:"src"`      // container path
	DestRel string `json:"dest_rel"` // path within the scope
}

PortWriteRequest is the body of POST /v1/islands/:name/port/write — copy a file out of the island INTO a read-write scope on the host.

type PortWriteResponse

type PortWriteResponse struct {
	Scope  string `json:"scope"`
	Src    string `json:"src"`  // container path
	Dest   string `json:"dest"` // host path written
	Bytes  int64  `json:"bytes"`
	SHA256 string `json:"sha256"`
}

PortWriteResponse reports a completed write into a scope.

type PresenceEntry

type PresenceEntry struct {
	Label    string    `json:"label"`
	JoinedAt time.Time `json:"joined_at"`
}

PresenceEntry describes one client attached to an island's session.

type ProviderCredentialsResponse

type ProviderCredentialsResponse struct {
	Providers []providercreds.Meta `json:"providers"`
}

ProviderCredentialsResponse is the body of GET /v1/credentials/providers: the daemon's LLM provider credentials WITHOUT their keys (providercreds.Meta carries only a masked hint).

type PushCredentialsRequest

type PushCredentialsRequest struct {
	CredentialsJSON string `json:"credentials_json"`
}

PushCredentialsRequest is the body of PUT /v1/credentials/claude. CredentialsJSON is the verbatim content of a Claude Code credentials file (the {"claudeAiOauth": ...} blob).

type PutGitHubIdentityRequest

type PutGitHubIdentityRequest struct {
	Login   string `json:"login"`
	ID      int64  `json:"id,omitempty"`   // GitHub numeric user id, for the canonical noreply commit email
	Host    string `json:"host,omitempty"` // defaults to github.com
	Token   string `json:"token"`
	Default bool   `json:"default,omitempty"` // make this the default identity (host owner only)
	Shared  bool   `json:"shared,omitempty"`  // host owner only: mark a host identity usable by every tenant's islands
}

PutGitHubIdentityRequest is the body of PUT /v1/credentials/github/:name — how a client (e.g. `dejima auth push --github`) seeds or updates an identity.

type PutProviderCredentialRequest

type PutProviderCredentialRequest struct {
	APIKey  string `json:"api_key"`
	BaseURL string `json:"base_url,omitempty"` // optional endpoint override
	EnvVar  string `json:"env_var,omitempty"`  // override the derived env-var name
	Default bool   `json:"default,omitempty"`  // make this the default provider
}

PutProviderCredentialRequest is the body of PUT /v1/credentials/providers/:provider — how a client (`dejima provider set`) seeds or updates a provider key. The key is write-only; it is never echoed back.

type PutSecretRequest added in v0.8.28

type PutSecretRequest struct {
	Value string `json:"value"`
}

PutSecretRequest sets or rotates one secret.

type RelabelTerminalRequest

type RelabelTerminalRequest struct {
	Label string `json:"label"`
}

RelabelTerminalRequest is the body of PATCH /v1/terminals/{id}.

type Resources

type Resources struct {
	Memory string `json:"memory,omitempty"`
	CPUs   string `json:"cpus,omitempty"`
	Disk   string `json:"disk,omitempty"`
	// OOMPriority stack-ranks islands for the OOM killer: higher = more protected
	// (killed later). nil = unset → smart default at create (headless brains start
	// expendable). Maps to docker --oom-score-adj (inverted) in the daemon.
	OOMPriority *int `json:"oom_priority,omitempty"`
}

Resources mirrors project.Resources for API transport.

type RosterAgent added in v0.6.9

type RosterAgent struct {
	ID    string `json:"id"`
	Label string `json:"label,omitempty"`
}

RosterAgent is the minimal (id, label) view of a current agent carried in a MailboxSendResponse so the sender can name the live agents in its warning.

type SSHKeyInfo

type SSHKeyInfo struct {
	Fingerprint string `json:"fingerprint"`
	Type        string `json:"type"`
	Comment     string `json:"comment"`
}

SSHKeyInfo is one authorized key, for listing.

type ScheduleInfo added in v0.8.3

type ScheduleInfo struct {
	ID        string    `json:"id"`
	Every     string    `json:"every,omitempty"`
	Task      string    `json:"task,omitempty"`
	Agent     string    `json:"agent,omitempty"`
	NextDue   time.Time `json:"next_due"`
	LastRun   time.Time `json:"last_run,omitempty"`
	CreatedAt time.Time `json:"created_at"`
}

ScheduleInfo is the public view of a wake schedule.

type SecretsResponse added in v0.8.28

type SecretsResponse struct {
	Secrets []secrets.Meta `json:"secrets"`
}

SecretsResponse lists an island's secrets as metadata.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the Dejima HTTP API server.

func NewServer

func NewServer(rt runtime.Runtime, log *slog.Logger, ev *events.Manager) *Server

func (*Server) AdoptExisting

func (s *Server) AdoptExisting(ctx context.Context)

AdoptExisting brings the runtime state into alignment with persisted project state. Called at daemon startup. Best-effort: errors are logged but do not prevent the daemon from serving.

func (*Server) AuditEnabled

func (s *Server) AuditEnabled() bool

AuditEnabled reports whether the operational audit log is on.

func (*Server) ClientHistory

func (s *Server) ClientHistory() []ClientHistoryEntry

ClientHistory returns the most recent attach/detach events (newest first).

func (*Server) CloseSessionsForRestart added in v0.8.14

func (s *Server) CloseSessionsForRestart() int

CloseSessionsForRestart marks the daemon as restarting and closes every attached session websocket with a reconnect-triggering close (Service Restart, 1012). Clients re-dial and resume the still-running in-island tmux, turning a daemon self-update/restart into a brief reconnect blink rather than a fleet-wide terminal drop. Call it during shutdown BEFORE http.Server.Shutdown (which does not close hijacked websockets). Returns the number closed so the caller can log it and pause briefly for the closes to flush.

func (*Server) EmitDaemonStarted

func (s *Server) EmitDaemonStarted(listen []string)

EmitDaemonStarted fires a daemon.started event carrying the build version and the active listen modes. On a headless host this is the only push-shaped way to learn the box rebooted or the daemon crashed and was restarted by its supervisor; it pairs with container.crashed from the watchdog.

func (*Server) EnableAudit

func (s *Server) EnableAudit(opts AuditOptions)

EnableAudit turns on the operational audit log: api.request + lifecycle records are appended to the hash-chained ledger. Off by default; dejimad calls this when started with --audit. The HMAC keying of the ledger file itself is a separate, ledger-wide setting (ledger.Configure), applied before the first append; this only governs whether the operational layer is recorded at all.

func (*Server) EnableAutonomy

func (s *Server) EnableAutonomy(dial string)

EnableAutonomy turns on the in-island → dejimad autonomy path: containers are provisioned with DEJIMA_HOST=dial and their per-island DEJIMA_TOKEN. dial is the address the container dials to reach this daemon (host-internal, e.g. host.docker.internal:<port>). Call only when the token listener is bound; an empty dial is a no-op.

func (*Server) EnableEgress added in v0.6.9

func (s *Server) EnableEgress(dial string, log *egress.Log, policy *egress.PolicyStore)

EnableEgress wires the island egress proxy: dial is the host:port islands reach the proxy at (injected as HTTPS_PROXY into new containers), log is where the proxy records destinations and the read API serves from, and policy is the per-island allow/deny store the operator mutates via the API (the same store the proxy enforces). Off by default; dejimad/main owns the proxy listener.

func (*Server) EnableHostTerminals

func (s *Server) EnableHostTerminals()

EnableHostTerminals turns on the operator host-terminal feature. It exposes uncontained shells on the daemon host, so it is off by default and meant to be a deliberate operator opt-in (`dejimad --host-terminals`).

func (*Server) EnableSSH

func (s *Server) EnableSSH(addr, hostKey string)

EnableSSH records the SSH-façade listen addr so clients (the TUI, `dejima ssh config/info`) can surface the connection target. Reporting only — the listener itself is owned by dejimad/main; this never opens a port.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns an http.Handler suitable for the daemon's listener. Handler returns the API handler for the fully-trusted listeners: the unix socket (filesystem-permission trust) and the tailnet-pinned TCP listener. Neither carries a per-request token; see TokenAuthHandler for the host-internal, token-authenticated autonomy path.

roleAuth wraps the mux to apply the team-auth model (roleauth.go): a request with no bearer token runs as the trusted owner; one carrying a token is attenuated to that token's role + island scope. It also lands the resolved Identity (and Lane 1's AuditIdentity) on the request context for downstream handlers and the audit log.

Composition: log → roleAuth (authenticate) → audit → mux (handle). roleAuth classifies on the mux but dispatches to auditMiddleware(mux), so the audit record is written with the authenticated identity already on the context (roleAuth stamps WithAuditIdentity). This is the authenticate→audit→handle order both Lane 1 and Lane 2 specified.

func (*Server) HostTerminalsEnabled

func (s *Server) HostTerminalsEnabled() bool

HostTerminalsEnabled reports whether the host-terminal feature is on.

func (*Server) IslandEvents

func (s *Server) IslandEvents(island string) []events.Event

IslandEvents returns the most recent events for one island (newest first).

func (*Server) RegisterActivity

func (s *Server) RegisterActivity(mux *http.ServeMux)

RegisterActivity registers the team activity-feed route (one append-only line in routes(), per the lane seam contract). Read-only and operator-surface only; classified capRead in roleRouteCap so viewers can observe team activity, and absent from tokenRouteAccess so an island token can never read the fleet feed.

func (*Server) RegisterAudit

func (s *Server) RegisterAudit(mux *http.ServeMux)

RegisterAudit registers the audit read/filter/export/verify route on mux. It's the single seam server.go wires in (one line), keeping the route table change per-lane to a one-liner.

func (*Server) RegisterAuth

func (s *Server) RegisterAuth(mux *http.ServeMux)

RegisterAuth registers the team-auth token-administration routes on mux. Called once from routes() (one append-only line per the lane seam contract). The owner-only gate is enforced by roleAuth via roleRouteCap, not re-checked here.

func (*Server) RegisterMCP

func (s *Server) RegisterMCP(mux *http.ServeMux)

RegisterMCP mounts the MCP-broker routes. Called once from server.go's routes() — the single shared-file seam this lane adds (append-only). Keeping the registrations here means the route surface lives beside its handlers.

func (*Server) RequireToken

func (s *Server) RequireToken()

RequireToken makes the operator surface reject anonymous (no-token) requests with 401, turning bearer tokens into a hard boundary rather than opt-in attenuation. Off by default: the trusted listeners (unix socket, tailnet) keep working without a token. Turn it on when the daemon is reached by callers that should hold only an attenuated service token (e.g. an off-tailnet control plane). Set from dejimad via the --require-token flag.

func (*Server) RevokeAllSessions

func (s *Server) RevokeAllSessions() int

RevokeAllSessions drops every active websocket client across every island. Returns the count of clients that were signaled.

func (*Server) RunClaudeAutoSeed added in v0.8.17

func (s *Server) RunClaudeAutoSeed(ctx context.Context)

RunClaudeAutoSeed is the backstop sweep: while the host is unseeded, it periodically scans the operator's running islands for a capturable login. It exists because a skewed in-island shim can silently stop POSTing agent-events (the socket→TCP skew that killed heartbeats for ~18h is the cautionary tale) — without the sweep, those exact islands would never auto-seed and the operator is back to a manual `dejima auth push` with no signal why. Self-disabling: once seeded it's a single bool check per tick. Run it in its own goroutine; returns when ctx is cancelled.

func (*Server) RunHeartbeatMonitor added in v0.8.3

func (s *Server) RunHeartbeatMonitor(ctx context.Context)

RunHeartbeatMonitor is the "monitor the monitor" alerter: it watches running islands and raises an operator alert (agent.silent, ledgered) when an agent's agent-state heartbeat goes silent past the grace — a stalled/crashed agent, or a skewed in-island shim that can't POST — and a recovery (agent.recovered) when it returns. Edge-triggered, so an ongoing silence alerts ONCE, not every tick. Runs unconditionally in its own goroutine; returns when ctx is cancelled.

func (*Server) RunIdleHibernator

func (s *Server) RunIdleHibernator(ctx context.Context, threshold time.Duration)

RunIdleHibernator hibernates running islands that have been idle — no attached client and no live agent process — for at least `threshold`. It is opt-in: threshold <= 0 disables it (the default), and it returns immediately.

It only ever *stops* an idle island (reclaiming its slice of the runtime's memory); it never deletes anything, and it never touches an island with a live agent process — so a working agent or an idling-but-alive Home Island brain is safe. Run it in its own goroutine; it returns when ctx is cancelled.

func (*Server) RunScheduler added in v0.8.3

func (s *Server) RunScheduler(ctx context.Context)

RunScheduler fires durable per-island scheduled wakes (project.Schedules). It runs unconditionally — independent of idle-hibernate — because the schedule is the always-on counterpart to hibernate: the daemon holds it and wakes the island on cadence. Runs in its own goroutine; returns when ctx is cancelled.

func (*Server) RunSpawnReaper added in v0.6.9

func (s *Server) RunSpawnReaper(ctx context.Context)

RunSpawnReaper periodically reaps ephemeral sub-agents that have exited, aged out (grant TTL), or whose parent is gone — freeing their max_concurrent slot. No-op islands (no ephemeral agents) cost a cheap roster check. Mirrors the idle-hibernate loop.

func (*Server) RunWakeNotifier

func (s *Server) RunWakeNotifier(ctx context.Context, interval time.Duration)

RunWakeNotifier periodically flushes queued nudges so a message that arrived while an agent was busy is delivered once it reaches a turn boundary. interval sets the retry cadence; <= 0 falls back to DefaultWakeFlushInterval. Run it in its own goroutine; returns when ctx is cancelled. A no-op loop when soft-notify is disabled.

func (*Server) RunWatchdog

func (s *Server) RunWatchdog(ctx context.Context, interval time.Duration)

RunWatchdog polls island container health on an interval and emits container.crashed when an island that should be running has exited unexpectedly, or its container restart count climbs (flapping under the restart policy). It only observes — it never starts or stops containers, so it can't fight AdoptExisting. Returns when ctx is cancelled; run it in its own goroutine.

func (*Server) SetWakeNotify

func (s *Server) SetWakeNotify(on bool)

SetWakeNotify toggles the default wake-on-message soft-notify (Lane 5 P3.5). The mailbox.arrival event still fires either way (the wrapper override path); this only gates Dejima's built-in nudge + wake-from-hibernate.

func (*Server) TokenAuthHandler

func (s *Server) TokenAuthHandler() http.Handler

TokenAuthHandler returns the API handler for the host-internal, token- authenticated TCP listener — the in-island → dejimad autonomy path. It must only ever back a listener bound to a host-internal address (loopback, reachable via host.docker.internal), never a LAN/0.0.0.0 bind: the token is the authorization, the bind limits exposure.

type SessionEnvelope

type SessionEnvelope struct {
	Type      string          `json:"type"`
	B64       string          `json:"b64,omitempty"`
	Rows      uint16          `json:"rows,omitempty"`
	Cols      uint16          `json:"cols,omitempty"`
	Term      string          `json:"term,omitempty"`
	ColorTerm string          `json:"colorterm,omitempty"`
	Attached  []PresenceEntry `json:"attached,omitempty"`
}

SessionEnvelope is the JSON framing on the websocket. Three message types:

  • {"type":"hello","attached":[...]} server → client on connect
  • {"type":"data","b64":"..."} both directions
  • {"type":"resize","rows":N,"cols":N} client → server
  • {"type":"presence","attached":[...]} server → client when others join/leave

Term/ColorTerm ride along on the FIRST resize (the client's opening message) and are ignored on later ones — they describe the client's terminal, which does not change mid-session. They are optional in both directions: an older client omits them and an older daemon ignores them, so either side upgrading alone is safe. See bridge.TermEnv for what the daemon does with them.

type SetIslandIdentityRequest added in v0.6.0

type SetIslandIdentityRequest struct {
	Color string `json:"color"`
	Glyph string `json:"glyph"`
}

SetIslandIdentityRequest is the body of PUT /v1/islands/{name}/identity: the operator-chosen color + glyph override. Both fields are required and validated server-side (hex color, single-rune glyph).

type SpawnGrantRequest added in v0.6.9

type SpawnGrantRequest struct {
	MaxConcurrent  int      `json:"max_concurrent"`
	MaxTotal       int      `json:"max_total,omitempty"`
	Types          []string `json:"types,omitempty"`
	TTL            string   `json:"ttl,omitempty"` // per-sub-agent lifetime, e.g. "1h"
	PerAgentMemory string   `json:"per_agent_memory,omitempty"`
	PerAgentCPUs   string   `json:"per_agent_cpus,omitempty"`
}

SpawnGrantRequest is the body of POST /v1/islands/{name}/spawn-grant — the operator opting an island into agent-initiated ephemeral sub-agents, with an explicit budget. Operator-only (see roleauth); an in-island token can never reach this route (it isn't in tokenRouteAccess), only spawn within a grant.

type SpawnGrantResponse added in v0.6.9

type SpawnGrantResponse struct {
	Granted bool         `json:"granted"`
	Grant   *spawn.Grant `json:"grant,omitempty"`
}

SpawnGrantResponse echoes an island's current grant. Granted=false means no grant (the deny default — the island's agents cannot spawn).

type SubscribeWebhookRequest

type SubscribeWebhookRequest struct {
	URL    string        `json:"url"`
	Secret string        `json:"secret,omitempty"`
	Events []events.Type `json:"events,omitempty"`
}

SubscribeWebhookRequest is the body of POST /v1/events/subscribe.

type TerminalsResponse

type TerminalsResponse struct {
	Terminals []hostterm.Terminal `json:"terminals"`
}

TerminalsResponse is the body of GET /v1/terminals.

type TokenView

type TokenView struct {
	ID        string    `json:"id"`
	Label     string    `json:"label,omitempty"`
	Role      string    `json:"role"`
	Owner     string    `json:"owner,omitempty"`   // tenant this token acts as (multi-tenant ownership)
	Islands   []string  `json:"islands,omitempty"` // scope; empty = all the owner's islands
	CreatedAt time.Time `json:"created_at"`
}

TokenView is the public, secret-free view of an issued token.

type TokensResponse

type TokensResponse struct {
	Tokens []TokenView `json:"tokens"`
}

TokensResponse is the body of GET /v1/tokens.

type UpdateIslandRequest

type UpdateIslandRequest struct {
	Title *string `json:"title,omitempty"`
	// NoHibernate pins the island awake (exempt from idle auto-hibernate). nil
	// leaves the current setting unchanged.
	NoHibernate *bool `json:"no_hibernate,omitempty"`
}

UpdateIslandRequest is the body of PATCH /v1/islands/{name}. Only cosmetic, in-place-editable fields live here (Name and infra identity are immutable). Fields are pointers so a request applies ONLY what it sends — a no_hibernate update doesn't clobber the title, and vice-versa.

type UpdateResourcesRequest

type UpdateResourcesRequest struct {
	Memory      *string `json:"memory,omitempty"`
	OOMPriority *int    `json:"oom_priority,omitempty"`
}

UpdateResourcesRequest is the body of PUT /v1/islands/:name/resources. Pointer fields distinguish "leave unchanged" (nil) from an explicit value (incl. "" for Memory → unlimited).

type UpdateResourcesResponse

type UpdateResourcesResponse struct {
	Resources       Resources `json:"resources"`
	RestartRequired bool      `json:"restart_required"`
}

UpdateResourcesResponse echoes the stored resources and flags whether a change needs a container recreate to take effect (true when OOMPriority changed — --oom-score-adj is set at create only; Memory applies live via docker update).

type WorkspaceReadyResponse

type WorkspaceReadyResponse struct {
	Ready bool `json:"ready"`
	// CloneFailed is set when the island entrypoint RECORDED a failed repo clone
	// (report_clone_failure in image/start.sh writes /home/dejima/.dejima/
	// clone-status). Only meaningful when Ready is false — its presence
	// distinguishes "clone failed" from "still cloning".
	CloneFailed bool `json:"clone_failed,omitempty"`
	// CloneReason is that classifier's value: "auth" | "not-found" | "error".
	// This set is a CONTRACT with report_clone_failure (writer) and the client's
	// cloneFailureHint map (reader) — keep the three in sync; an unknown value
	// still degrades to a generic hint client-side.
	CloneReason string `json:"clone_reason,omitempty"`
}

WorkspaceReadyResponse reports whether an island's repo clone has landed in /workspace yet (GET /v1/islands/:name/workspace-ready). `dejima connect` polls it to avoid attaching into a still-provisioning, empty workspace.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL