Skip to content

[Workspaces] Plugins cannot log to OpenCode's log system #27285

@jamesmurdza

Description

@jamesmurdza

Description

Description

Plugins cannot write to OpenCode's log files. The TUI plugin runtime has internal logging, but this is not exposed to plugin authors. Plugins can only use console.log/warn/error, which appears briefly in the terminal before the TUI takes over and is not captured in OpenCode's log files.

This makes debugging plugin issues extremely difficult, especially for workspace adapter plugins.

Current Behavior

The plugin runtime has its own logging:

// runtime.ts lines 117, 124-135
const log = Log.create({ service: "tui.plugin" })

function fail(message: string, data: Record<string, unknown>) {
  log.error(text, next)
  console.error(`[tui.plugin] ${text}`, next)  // Goes to stderr, lost when TUI starts
}

function warn(message: string, data: Record<string, unknown>) {
  log.warn(message, data)
  console.warn(`[tui.plugin] ${message}`, data)
}

But plugins themselves have no access to Log.create() or any logging API.

Impact

  • Debugging plugin issues is extremely difficult
  • Users who don't run OpenCode from a terminal never see console.* output
  • Plugin authors can't provide diagnostic information for troubleshooting
  • Workspace adapter errors (e.g., connection failures) are invisible
  • Makes it harder to diagnose issues like missing environment variables

Suggested Fix

Location: packages/opencode/src/cli/cmd/tui/plugin/runtime.ts

Expose a logging API to plugins via the plugin input/context:

// In plugin API types
interface PluginInput {
  log: {
    debug(message: string, data?: Record<string, unknown>): void
    info(message: string, data?: Record<string, unknown>): void
    warn(message: string, data?: Record<string, unknown>): void
    error(message: string, data?: Record<string, unknown>): void
  }
}

// In plugin runtime, when calling plugin hooks:
const pluginLog = Log.create({ service: `plugin.${pluginId}` })

const input: PluginInput = {
  log: {
    debug: (msg, data) => pluginLog.debug(msg, data ?? {}),
    info: (msg, data) => pluginLog.info(msg, data ?? {}),
    warn: (msg, data) => pluginLog.warn(msg, data ?? {}),
    error: (msg, data) => pluginLog.error(msg, data ?? {}),
  },
  // ... other input fields
}

Plugin authors could then use:

export async function create(input: PluginInput) {
  input.log.info("Creating workspace", { config })

  try {
    const workspace = await provider.create(config)
    input.log.info("Workspace created", { workspaceId: workspace.id })
  } catch (err) {
    input.log.error("Failed to create workspace", { error: err.message })
    throw err
  }
}

Related Issues

Workaround

None effective. Plugin authors can use console.log() but output is lost once TUI initializes.

Context

This issue was identified during development of the Daytona OpenCode plugin: daytonaio/daytona#4504

Plugins

No response

OpenCode version

1.14.48

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

Ubuntu 24.04

Terminal

No response

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions