opencode icon indicating copy to clipboard operation
opencode copied to clipboard

feat: add plugin scope support for desktop multi-project lifecycle

Open nick-vi opened this issue 1 month ago • 0 comments

Problem

The CLI and desktop app have fundamentally different lifecycles:

  • CLI: Single project, always starts from a project directory (process.cwd())
  • Desktop: Multi-project, starts without any project context, users select projects later

This difference wasn't accounted for in the plugin system. Plugins load regardless of whether a valid project context exists.

I discovered this while working on a plugin that requires project context (tsconfig.json). The CLI crashed when no tsconfig was present, which I initially handled poorly. But then the desktop crashed regardless - there's no project context on startup, so my plugin could never initialize.

This revealed that the plugin system has no way for plugins to declare whether they need project context.

Solution

1. Plugin scopes - Plugins can now declare "global" or "project" scope (default):

import { definePlugin } from "@opencode-ai/plugin"

export default definePlugin({
  scope: "global",
  plugin: async (input) => ({
    auth: { provider: "my-provider", ... }
  })
})

2. Predictable desktop startup - Desktop clients without explicit directory use home directory, ensuring worktree === "/" (no git repo).

3. Scope-aware loading - Project-scoped plugins skip loading when worktree === "/".

Migration for auth plugin authors

Wrap your plugin with definePlugin and set scope: "global":

// Before
export default async (input) => ({
  auth: { ... }
})

// After
import { definePlugin } from "@opencode-ai/plugin"

export default definePlugin({
  scope: "global",
  plugin: async (input) => ({
    auth: { ... }
  })
})

Backwards compatibility

  • Old plugins (plain functions) default to "project" scope
  • Built-in auth plugins hardcoded as global temporarily
  • CLI behavior unchanged

Follow-up

If accepted, I can update opencode-copilot-auth and opencode-anthropic-auth to use definePlugin, then remove the hardcoded list.

nick-vi avatar Dec 18 '25 13:12 nick-vi