Skip to content

5.10b API Reference

One-line summary: OpenCode SDK provides 20 API modules, one permission-response method, and 32 event types covering sessions, files, configuration, MCP, LSP, and more.


📝 Course Notes

Key takeaways from this lesson:

5.10b API Reference Notes


API Module Overview

The SDK client exposes the following modules through the OpencodeClient class:

Version boundary

The tables in this chapter describe the V1 entry point, @opencode-ai/sdk. v1.18.22 continues to export and retain V1 while extending sessions, questions, the current location, event streams, paginated history, runtime operations, and permission requests through @opencode-ai/sdk/v2. Do not mix V2's flat parameters with the V1 { path, body } syntax used in this chapter.

Source: packages/sdk/js/package.json:12-20, V1 OpencodeClient:1157-1197, V2 Session3:5426-5873

ModuleDescriptionSource
globalGlobal event subscriptionsdk.gen.ts:233-243
projectProject managementsdk.gen.ts:245-265
sessionSession management (core)sdk.gen.ts:431-700
fileFile operationssdk.gen.ts:808-838
findSearch functionalitysdk.gen.ts:776-806
configConfiguration managementsdk.gen.ts:337-371
appApplication infosdk.gen.ts:840-864
tuiTUI interface controlsdk.gen.ts:1026-1143
eventEvent subscriptionsdk.gen.ts:1145-1155
authAuthentication managementsdk.gen.ts:866-926
providerModel providerssdk.gen.ts:753-774
mcpMCP server managementsdk.gen.ts:928-974
lspLSP server statussdk.gen.ts:976-986
formatterFormatter statussdk.gen.ts:988-998
commandCommand listsdk.gen.ts:703-713
pathPath informationsdk.gen.ts:407-417
vcsVersion control infosdk.gen.ts:419-429
ptyPTY terminal sessionssdk.gen.ts:267-335
toolTool management (experimental)sdk.gen.ts:373-393
instanceInstance managementsdk.gen.ts:395-405

Session Management

Sessions are the core module of the SDK, providing message sending, history management, and more.

Method List

MethodDescriptionReturn Type
session.list()List all sessionsSession[]
session.get({ path })Get a single sessionSession
session.create({ body })Create a new sessionSession
session.delete({ path })Delete a sessionboolean
session.update({ path, body })Update session propertiesSession
session.status()Get all session statuses{ [sessionID: string]: SessionStatus }
session.children({ path })Get child session listSession[]
session.todo({ path })Get session Todo listTodo[]
session.init({ path, body })Analyze project and create AGENTS.mdboolean
session.fork({ path, body })Fork session at specified messageSession
session.abort({ path })Abort running sessionboolean
session.share({ path })Share sessionSession
session.unshare({ path })Unshare sessionSession
session.diff({ path })Get session file changesFileDiff[]
session.summarize({ path, body })Summarize session contentboolean
session.messages({ path })Get session message list{info: Message, parts: Part[]}[]
session.message({ path })Get single message details{info: Message, parts: Part[]}
session.prompt({ path, body })Send message and wait for response{info: AssistantMessage, parts: Part[]}
session.promptAsync({ path, body })Send message asynchronously (no wait)204 No Content
session.command({ path, body })Send command{info: AssistantMessage, parts: Part[]}
session.shell({ path, body })Run shell commandAssistantMessage
session.revert({ path, body })Revert to specified messageSession
session.unrevert({ path })Redo the reverted message and file stateSession

Responding to permission requests

The Session class does not have a permission() method. Respond to permission requests with this direct method on OpencodeClient:

typescript
await client.postSessionIdPermissionsPermissionId({
  path: { id: "session-id", permissionID: "perm-id" },
  body: { response: "always" },  // "once" | "always" | "reject"
})

Undo / Revert / Redo

V1's session.revert() performs undo/revert: it moves the session boundary to the specified messageID (optionally narrowed to a partID), collects patches after that boundary, and restores the related file snapshot by default. session.unrevert() performs redo/unrevert: it restores the original snapshot and then clears the revert state. Both reject requests while the session is running.

typescript
// Undo: return to a specific message and roll back later file patches by default
await client.session.revert({
  path: { id: sessionID },
  body: { messageID: "msg-123" },
})

// Redo: restore the messages and file state that were just undone
await client.session.unrevert({ path: { id: sessionID } })

Setting snapshot: false disables only file-snapshot undo/redo; it does not remove message-boundary revert support.

Source: V1 sdk.gen.ts:678-700, session/revert.ts:38-98, config.ts:52-55

Code Example

typescript
// Create session
const session = await client.session.create({
  body: { title: "Code Refactoring Task" },
})

// Send message
const result = await client.session.prompt({
  path: { id: session.data!.id },
  body: {
    model: { providerID: "anthropic", modelID: "claude-opus-4-5-thinking" },
    parts: [{ type: "text", text: "Please help me refactor this function" }],
  },
})

// Get message list
const messages = await client.session.messages({
  path: { id: session.data!.id },
})

// Get Todo list
const todos = await client.session.todo({
  path: { id: session.data!.id },
})

// Fork session
const forked = await client.session.fork({
  path: { id: session.data!.id },
  body: { messageID: "msg-123" },
})

// Get file changes
const diff = await client.session.diff({
  path: { id: session.data!.id },
})

// Abort session
await client.session.abort({
  path: { id: session.data!.id },
})

// Share the session (generates an accessible URL)
const shared = await client.session.share({ path: { id: session.data!.id } })
console.log(`Share URL: ${shared.data?.share?.url}`)

// Stop sharing
await client.session.unshare({ path: { id: session.data!.id } })

prompt body Parameters

ParameterTypeDescription
partsArray<TextPartInput | FilePartInput | AgentPartInput | SubtaskPartInput>Message content parts
model{providerID, modelID}Specify model
noReplybooleanSet to true to not trigger AI response (inject context)
agentstringUse specified Agent

Token Usage and Cost

Every AI response includes token usage and cost, with no extra request required. The info field returned by session.prompt() (an AssistantMessage) contains cost and tokens:

typescript
const result = await client.session.prompt({
  path: { id: sessionID },
  body: {
    parts: [{ type: "text", text: "Analyze this code" }],
  },
})

const info = result.data?.info  // AssistantMessage
if (info) {
  console.log(`Cost: $${info.cost}`)
  console.log(`Input tokens: ${info.tokens.input}`)
  console.log(`Output tokens: ${info.tokens.output}`)
  console.log(`Reasoning tokens: ${info.tokens.reasoning}`)
  console.log(`Cache reads: ${info.tokens.cache.read}`)
  console.log(`Cache writes: ${info.tokens.cache.write}`)
}

Source: types.gen.ts:112-141 (AssistantMessage type)

Per-step usage: If a model runs multiple steps, such as tool calls, each completed step produces a StepFinishPart with its own cost and tokens, allowing you to measure usage for each step:

typescript
// Iterate over every Part in a message and report per-step usage
const msg = await client.session.message({
  path: { id: sessionID, messageID: "msg-1" },
})

for (const part of msg.data?.parts ?? []) {
  if (part.type === "step-finish") {
    console.log(`Step cost: $${part.cost}, output: ${part.tokens.output} tokens`)
  }
}

Source: types.gen.ts:315-332 (StepFinishPart type)

Calculate total usage for an entire session

Iterate over all messages returned by session.messages() and sum the cost and tokens values from each AssistantMessage.

Monitoring Tool Calls

Each ToolPart in an AI response records the complete lifecycle of a tool call. Inspect part.state to identify its current phase and obtain the input, output, and duration:

typescript
const msg = await client.session.message({
  path: { id: sessionID, messageID: "msg-1" },
})

for (const part of msg.data?.parts ?? []) {
  if (part.type !== "tool") continue
  console.log(`Tool: ${part.tool}`)
  const state = part.state
  switch (state.status) {
    case "completed":
      console.log(`  Result: ${state.output}`)
      console.log(`  Duration: ${state.time.end - state.time.start}ms`)
      break
    case "error":
      console.log(`  Error: ${state.error}`)
      break
    case "running":
      console.log(`  Running...`)
      break
    case "pending":
      console.log(`  Pending`)
      break
  }
}

The four tool-call states are:

StateDescriptionAvailable Fields
pendingWaiting to runinput (arguments), raw (raw input)
runningRunninginput, title, time.start
completedCompletedinput, output (result), title, time.{start,end}, attachments
errorFailedinput, error (error message), time.{start,end}

Source: types.gen.ts:237-305 (the four ToolState subtypes and ToolPart)

Session Code-Change Statistics

The Session type includes a summary field that records how much code the session changed, so you do not need to calculate a diff manually:

typescript
const session = await client.session.get({ path: { id: sessionID } })
const summary = session.data?.summary
if (summary) {
  console.log(`Files changed: ${summary.files}`)
  console.log(`Lines added: ${summary.additions}`)
  console.log(`Lines deleted: ${summary.deletions}`)
  // summary.diffs contains the diff for each file
}
FieldTypeDescription
summary.filesnumberNumber of files changed
summary.additionsnumberNumber of lines added
summary.deletionsnumberNumber of lines deleted
summary.diffsFileDiff[]?Per-file diff details

Source: types.gen.ts:533-560 (Session.summary field)


Project Management

MethodDescriptionReturn Type
project.list()List all projectsProject[]
project.current()Get current projectProject
typescript
// Get current project
const current = await client.project.current()
console.log(`Project path: ${current.data?.worktree}`)

// List all projects
const projects = await client.project.list()

Project Type

typescript
type Project = {
  id: string
  worktree: string      // Working directory
  vcsDir?: string       // VCS directory (e.g., .git)
  vcs?: "git"           // Version control type
  time: {
    created: number
    initialized?: number
  }
}

File Operations

MethodDescriptionReturn Type
file.list({ query })List files and directoriesFileNode[]
file.read({ query })Read file contentFileContent
file.status()Get file status (git changes)File[]
typescript
// List directory contents
const nodes = await client.file.list({
  query: { path: "src" },
})

// Read file
const content = await client.file.read({
  query: { path: "src/index.ts" },
})
console.log(content.data?.content)

// Get git status
const status = await client.file.status()
for (const file of status.data ?? []) {
  console.log(`${file.status}: ${file.path} (+${file.added}/-${file.removed})`)
}

Find Search Functionality

MethodDescriptionReturn Type
find.text({ query })Search text in file contentsMatch result array
find.files({ query })Find files/directories by namestring[]
find.symbols({ query })Find workspace symbolsSymbol[]

find.files Query Parameters

ParameterTypeDescription
querystringSearch pattern (supports glob; required)
dirs"true" | "false"Whether to return directories only (string; optional)
directorystringOverride search root directory (optional)
typescript
// Search text
const matches = await client.find.text({
  query: { pattern: "TODO|FIXME" },
})

// Find files
const tsFiles = await client.find.files({
  query: { query: "*.ts" },
})

// Find directories only
const dirs = await client.find.files({
  query: { query: "src", dirs: "true" },
})

// Find symbols
const symbols = await client.find.symbols({
  query: { query: "handleRequest" },
})

Config Configuration Management

MethodDescriptionReturn Type
config.get()Get current configurationConfig
config.update({ body })Update configurationConfig
config.providers()Get provider list and default models{providers, default}
typescript
// Get configuration
const config = await client.config.get()
console.log(`Current model: ${config.data?.model}`)

// Dynamically update configuration
await client.config.update({
  body: {
    model: "anthropic/claude-haiku-4-5",
    logLevel: "DEBUG",
  },
})

// Get provider information
const { providers, default: defaults } = (await client.config.providers()).data!

App Application Info

MethodDescriptionReturn Type
app.log({ body })Write log entryboolean
app.agents()List all AgentsAgent[]
typescript
// Write log
await client.app.log({
  body: {
    service: "my-plugin",
    level: "info",
    message: "Operation complete",
  },
})

// Get Agent list
const agents = await client.app.agents()
for (const agent of agents.data ?? []) {
  console.log(`${agent.name}: ${agent.description}`)
}

TUI Interface Control

MethodDescriptionReturn Type
tui.appendPrompt({ body })Append text to input boxboolean
tui.submitPrompt()Submit current inputboolean
tui.clearPrompt()Clear input boxboolean
tui.showToast({ body })Show notificationboolean
tui.openHelp()Open help dialogboolean
tui.openSessions()Open session selectorboolean
tui.openThemes()Open theme selectorboolean
tui.openModels()Open model selectorboolean
tui.executeCommand({ body })Execute TUI commandboolean
tui.publish({ body })Publish TUI eventboolean
tui.control.next()Get next TUI request-
tui.control.response()Submit TUI response-

showToast Parameters

ParameterTypeDescription
messagestringNotification content
titlestringNotification title (optional)
variant"info" | "success" | "warning" | "error"Notification type
durationnumberDisplay duration (milliseconds)
typescript
// Show success notification
await client.tui.showToast({
  body: {
    title: "Success",
    message: "File saved",
    variant: "success",
    duration: 3000,
  },
})

// Execute command
await client.tui.executeCommand({
  body: { command: "session.new" },
})

Auth Authentication Management

MethodDescriptionReturn Type
auth.set({ path, body })Set authentication credentialsboolean
auth.remove({ path })Remove MCP OAuth credentialsboolean
auth.start({ path })Start OAuth flow-
auth.callback({ path, body })OAuth callback-
auth.authenticate({ path })Auto OAuth (open browser)-
typescript
// Set API Key
await client.auth.set({
  path: { id: "anthropic" },
  body: { type: "api", key: "sk-xxx" },
})

// Set OAuth credentials
await client.auth.set({
  path: { id: "github" },
  body: {
    type: "oauth",
    access: "access-token",
    refresh: "refresh-token",
    expires: Date.now() + 3600000,
  },
})

Provider Management

MethodDescriptionReturn Type
provider.list()List all providers{ all: Provider[], default: Record<string, string>, connected: string[] }
provider.auth()Get provider authentication methodsRecord<string, ProviderAuthMethod[]>
provider.oauth.authorize({ path, body })OAuth authorize-
provider.oauth.callback({ path, body })OAuth callback-
typescript
// Get provider list
const providers = await client.provider.list()
for (const p of providers.data?.all ?? []) {
  console.log(`${p.name} (${p.id}): ${Object.keys(p.models).length} models`)
}

// Get authentication methods
const authMethods = await client.provider.auth()
for (const [providerID, methods] of Object.entries(authMethods.data ?? {})) {
  console.log(providerID, methods)
}

MCP Server Management

MethodDescriptionReturn Type
mcp.status()Get MCP server statusRecord<string, McpStatus>
mcp.add({ body })Dynamically add MCP server-
mcp.connect({ path })Connect MCP server-
mcp.disconnect({ path })Disconnect MCP server-
mcp.auth.*MCP OAuth authentication-

McpStatus Type

typescript
type McpStatus = 
  | { status: "connected" }
  | { status: "disabled" }
  | { status: "failed"; error: string }
  | { status: "needs_auth" }
  | { status: "needs_client_registration"; error: string }
typescript
// Get status
const status = await client.mcp.status()
for (const [name, value] of Object.entries(status.data ?? {})) {
  console.log(name, value.status)
}

// Dynamically add MCP server
await client.mcp.add({
  body: {
    name: "my-mcp",
    config: {
      type: "local",
      command: ["node", "mcp-server.js"],
    },
  },
})

// Connect/disconnect
await client.mcp.connect({ path: { name: "my-mcp" } })
await client.mcp.disconnect({ path: { name: "my-mcp" } })

LSP and Formatter Status

typescript
// LSP status
const lspStatus = await client.lsp.status()
for (const lsp of lspStatus.data ?? []) {
  console.log(`${lsp.name}: ${lsp.status}`)
}

// Formatter status
const formatterStatus = await client.formatter.status()
for (const fmt of formatterStatus.data ?? []) {
  console.log(`${fmt.name}: ${fmt.enabled ? "enabled" : "disabled"}`)
}

PTY Terminal Sessions

For managing pseudo-terminal sessions (experimental feature).

MethodDescriptionReturn Type
pty.list()List all PTY sessionsPty[]
pty.create({ body })Create PTY sessionPty
pty.get({ path })Get PTY session infoPty
pty.update({ path, body })Update PTY sessionPty
pty.remove({ path })Remove PTY sessionboolean
pty.connect({ path })Connect PTY sessionboolean

Pty Type

typescript
type Pty = {
  id: string
  title: string
  command: string
  args: string[]
  cwd: string
  status: "running" | "exited"
  pid: number
}
typescript
// Create PTY session
const pty = await client.pty.create({
  body: {
    command: "bash",
    cwd: "/home/user/project",
    title: "Dev Terminal",
  },
})

// Update window size
await client.pty.update({
  path: { id: pty.data!.id },
  body: {
    size: { rows: 24, cols: 80 },
  },
})

Tool Management (Experimental)

The following APIs are located at /experimental/ path and may change in future versions.

MethodDescriptionReturn Type
tool.ids()List all tool IDsstring[]
tool.list({ query })Get tool JSON SchemaToolListItem[]
typescript
// Get all tool IDs
const toolIds = await client.tool.ids()
console.log("Available tools:", toolIds.data)

// Get tool details (need to specify model)
const tools = await client.tool.list({
  query: {
    provider: "anthropic",
    model: "claude-opus-4-5-thinking",
  },
})

Path and VCS Information

typescript
// Get path information
const pathInfo = await client.path.get()
console.log(`State directory: ${pathInfo.data?.state}`)
console.log(`Config directory: ${pathInfo.data?.config}`)
console.log(`Worktree: ${pathInfo.data?.worktree}`)
console.log(`Current directory: ${pathInfo.data?.directory}`)

// Get VCS information
const vcsInfo = await client.vcs.get()
console.log(`Current branch: ${vcsInfo.data?.branch}`)

Instance Management

typescript
// Dispose current instance
await client.instance.dispose()

Command List

typescript
// Get all commands
const commands = await client.command.list()
for (const cmd of commands.data ?? []) {
  console.log(`/${cmd.name}: ${cmd.description}`)
}

Complete Event Types List

The SDK supports 32 real-time events, subscribable via client.event.subscribe().

Server Events

Event TypeDescriptionProperties
server.connectedServer connected-
server.instance.disposedInstance disposeddirectory

Installation Events

Event TypeDescriptionProperties
installation.updatedInstallation updatedversion
installation.update-availableUpdate availableversion

Session Events

Event TypeDescriptionProperties
session.createdSession createdinfo: Session
session.updatedSession updatedinfo: Session
session.deletedSession deletedinfo: Session
session.statusSession status changedsessionID, status
session.idleSession became idlesessionID
session.compactedSession compactedsessionID
session.diffSession file changessessionID, diff: FileDiff[]
session.errorSession errorsessionID?, error

Message Events

Event TypeDescriptionProperties
message.updatedMessage updatedinfo: Message
message.removedMessage removedsessionID, messageID
message.part.updatedMessage part updatedpart: Part, delta?: string
message.part.removedMessage part removedsessionID, messageID, partID

Permission Events

Event TypeDescriptionProperties
permission.updatedPermission request pendingPermission
permission.repliedPermission respondedsessionID, permissionID, response

File Events

Event TypeDescriptionProperties
file.editedFile editedfile
file.watcher.updatedFile watcher updatedfile, event: "add" | "change" | "unlink"

Todo Events

Event TypeDescriptionProperties
todo.updatedTodo list updatedsessionID, todos: Todo[]

Command Events

Event TypeDescriptionProperties
command.executedCommand executedname, sessionID, arguments, messageID

VCS Events

Event TypeDescriptionProperties
vcs.branch.updatedBranch switchedbranch?

LSP Events

Event TypeDescriptionProperties
lsp.updatedLSP status updated-
lsp.client.diagnosticsLSP diagnosticsserverID, path

TUI Events

Event TypeDescriptionProperties
tui.prompt.appendInput box text appendedtext
tui.command.executeTUI command executedcommand
tui.toast.showShow notificationtitle?, message, variant, duration?

PTY Events

Event TypeDescriptionProperties
pty.createdPTY session createdinfo: Pty
pty.updatedPTY session updatedinfo: Pty
pty.exitedPTY session exitedid, exitCode
pty.deletedPTY session deletedid

Event Listener Example

typescript
const events = await client.event.subscribe()

for await (const event of events.stream) {
  switch (event.type) {
    case "message.part.updated":
      // Incremental update, can be used for streaming display
      if (event.properties.delta) {
        process.stdout.write(event.properties.delta)
      }
      break
      
    case "session.status":
      const { sessionID, status } = event.properties
      if (status.type === "busy") {
        console.log(`Session ${sessionID} processing...`)
      } else if (status.type === "idle") {
        console.log(`Session ${sessionID} completed`)
      } else if (status.type === "retry") {
        console.log(`Session ${sessionID} retrying (${status.attempt})`)
      }
      break
      
    case "permission.updated":
      console.log(`Permission request: ${event.properties.title}`)
      // Can auto-respond to permission requests
      await client.postSessionIdPermissionsPermissionId({
        path: {
          id: event.properties.sessionID,
          permissionID: event.properties.id,
        },
        body: { response: "always" },  // "once" allows once | "always" always allows | "reject" rejects
      })
      break
      
    case "file.edited":
      console.log(`File modified: ${event.properties.file}`)
      break
      
    case "todo.updated":
      console.log(`Todo updated:`, event.properties.todos)
      break
  }
}

Complete Type Definitions

Core Types

typescript
// Session
type Session = {
  id: string
  projectID: string
  directory: string
  parentID?: string
  title: string
  version: string
  summary?: {
    additions: number
    deletions: number
    files: number
    diffs?: FileDiff[]
  }
  share?: { url: string }
  time: {
    created: number
    updated: number
    compacting?: number
  }
  revert?: {
    messageID: string
    partID?: string
    snapshot?: string
    diff?: string
  }
}

// Session status
type SessionStatus =
  | { type: "idle" }
  | { type: "busy" }
  | { type: "retry"; attempt: number; message: string; next: number }

// Message
type Message = UserMessage | AssistantMessage

type UserMessage = {
  id: string
  sessionID: string
  role: "user"
  agent: string
  model: { providerID: string; modelID: string }
  time: { created: number }
  summary?: { title?: string; body?: string; diffs: FileDiff[] }
  system?: string
  tools?: { [key: string]: boolean }
}

type AssistantMessage = {
  id: string
  sessionID: string
  role: "assistant"
  parentID: string
  modelID: string
  providerID: string
  mode: string
  path: { cwd: string; root: string }
  time: { created: number; completed?: number }
  error?: MessageError
  cost: number
  tokens: {
    input: number
    output: number
    reasoning: number
    cache: { read: number; write: number }
  }
  finish?: string
  summary?: boolean
}

Part Types

typescript
type Part =
  | TextPart
  | ReasoningPart
  | FilePart
  | ToolPart
  | StepStartPart
  | StepFinishPart
  | SnapshotPart
  | PatchPart
  | AgentPart
  | RetryPart
  | CompactionPart
  | SubtaskPart

type TextPart = {
  id: string
  sessionID: string
  messageID: string
  type: "text"
  text: string
  synthetic?: boolean
  ignored?: boolean
  time?: { start: number; end?: number }
  metadata?: { [key: string]: unknown }
}

type ToolPart = {
  id: string
  sessionID: string
  messageID: string
  type: "tool"
  callID: string
  tool: string
  state: ToolState
  metadata?: { [key: string]: unknown }
}

type ToolState =
  | { status: "pending"; input: object; raw: string }
  | { status: "running"; input: object; title?: string; time: { start: number } }
  | { status: "completed"; input: object; output: string; title: string; time: { start: number; end: number } }
  | { status: "error"; input: object; error: string; time: { start: number; end: number } }

Error Types

typescript
type MessageError =
  | ProviderAuthError
  | UnknownError
  | MessageOutputLengthError
  | MessageAbortedError
  | ApiError

type ApiError = {
  name: "APIError"
  data: {
    message: string
    statusCode?: number
    isRetryable: boolean
    responseHeaders?: { [key: string]: string }
    responseBody?: string
  }
}

AssistantMessage.error can be one of five types:

Error TypeMeaningCommon Cause
ProviderAuthErrorAuthentication failedAPI key is invalid or expired
MessageOutputLengthErrorOutput too longThe model's maximum output-token limit was exceeded
MessageAbortedErrorInterruptedThe user called session.abort() or the request timed out
ApiErrorAPI returned an errorRate limiting (429), server errors (500), and similar failures; inspect data.statusCode and data.isRetryable
UnknownErrorUnknown errorOther unclassified errors
typescript
const result = await client.session.prompt({ path: { id: sessionID }, body: { ... } })
const error = result.data?.info.error
if (error) {
  switch (error.name) {
    case "APIError":
      if (error.data.isRetryable) console.log("Retryable; try again later")
      else console.log(`API error ${error.data.statusCode}: ${error.data.message}`)
      break
    case "ProviderAuthError":
      console.log("API key problem; check the authentication configuration")
      break
    // ...
  }
}

Source: types.gen.ts:70-110 (the five MessageError subtypes)

Other Types

typescript
type Todo = {
  id: string
  content: string
  status: string  // pending, in_progress, completed, cancelled
  priority: string  // high, medium, low
}

type Permission = {
  id: string
  type: string
  pattern?: string | string[]
  sessionID: string
  messageID: string
  callID?: string
  title: string
  metadata: { [key: string]: unknown }
  time: { created: number }
}

type Agent = {
  name: string
  description?: string
  mode: "subagent" | "primary" | "all"
  builtIn: boolean
  topP?: number
  temperature?: number
  color?: string
  model?: { modelID: string; providerID: string }
  prompt?: string
  tools: { [key: string]: boolean }
  options: { [key: string]: unknown }
  maxSteps?: number
  permission: {
    edit: "ask" | "allow" | "deny"
    bash: { [key: string]: "ask" | "allow" | "deny" }
    webfetch?: "ask" | "allow" | "deny"
    doom_loop?: "ask" | "allow" | "deny"
    external_directory?: "ask" | "allow" | "deny"
  }
}

type FileDiff = {
  file: string
  before: string
  after: string
  additions: number
  deletions: number
}

Common Pitfalls

IssueCauseSolution
data returns undefinedRequest failed, check error fieldCheck result.error
Event stream disconnectedNetwork interruption or server restartImplement reconnection logic
tool.list returns emptyNeed to specify provider and modelAdd query parameters
Permission request no responseNeed manual responseUse postSessionIdPermissionsPermissionId
MCP status needs_authMCP server requires OAuth authenticationCall mcp.auth.authenticate

Lesson Summary

You learned:

  1. The complete method list for 20 API modules plus one permission-response method

  2. 32 event types and their properties

  3. Core type definitions: Session, Message, Part, Todo, Agent, etc.

  4. Experimental APIs: Tool management, PTY terminal


Next Lesson Preview

We have finished V1, but OpenCode also ships an evolving V2 entry point alongside it. In the next lesson, we cover 5.10c SDK V2: Next-Generation API.

You'll learn:

  • Top-level compatibility modules and the client.v2.* namespace
  • Standalone Permission and Question modules for managing permissions and questions across sessions
  • Enhanced Session3 methods: interrupt, wait, compact, switching models, and switching agents
  • New V2 concepts including Sync, Worktree, and Workspace
  • A complete guide to migrating from V1 to V2