rtk-ai/rtk · error · anyhow::Error

OpenCode plugin is global-only. Use: rtk init -g --opencode

Error message

OpenCode plugin is global-only. Use: rtk init -g --opencode

What it means

The OpenCode plugin is installed into user-level OpenCode config (not a per-project file), so rtk init requires the global flag for it. The validation at src/hooks/init.rs:298 bails when install_opencode is set and global is false, and the message embeds the exact corrective command: `rtk init -g --opencode`.

Source

Thrown at src/hooks/init.rs:298

            anyhow::bail!("--codex cannot be combined with --opencode");
        }
        if claude_md {
            anyhow::bail!("--codex cannot be combined with --claude-md");
        }
        if hook_only {
            anyhow::bail!("--codex cannot be combined with --hook-only");
        }
        if matches!(patch_mode, PatchMode::Auto) {
            anyhow::bail!("--codex cannot be combined with --auto-patch");
        }
        if matches!(patch_mode, PatchMode::Skip) {
            anyhow::bail!("--codex cannot be combined with --no-patch");
        }
        run_codex_mode(global, ctx)?;
    } else {
        // Validation: Global-only features
        if install_opencode && !global {
            anyhow::bail!("OpenCode plugin is global-only. Use: rtk init -g --opencode");
        }

        if install_cursor && !global {
            anyhow::bail!("Cursor hooks are global-only. Use: rtk init -g --agent cursor");
        }

        if install_windsurf && !global {
            anyhow::bail!("Windsurf support is global-only. Use: rtk init -g --agent windsurf");
        }

        if install_windsurf {
            run_windsurf_mode(ctx)?;
        } else if install_cline {
            run_cline_mode(ctx)?;
        } else {
            // Mode selection (Claude Code / OpenCode)
            match (install_claude, install_opencode, claude_md, hook_only) {
                (false, true, _, _) => run_opencode_only_mode(ctx)?,

View on GitHub (pinned to d977e1c316)

Solutions

  1. Run it as the message says: `rtk init -g --opencode`
  2. If you wanted project-local setup, use the default mode instead: `rtk init` (installs Claude Code hooks/CLAUDE.md locally)
  3. Note the same rule for other global-only targets (cursor, windsurf) before combining flags

Example fix

# before (inside a project dir)
rtk init --opencode
# OpenCode plugin is global-only. Use: rtk init -g --opencode

# after
rtk init -g --opencode
Defensive patterns

Strategy: validation

Validate before calling

bash:
# OpenCode plugin installs user-level: require -g up front
if [[ "$*" == *--opencode* && "$*" != *-g* && "$*" != *--global* ]]; then
  echo "OpenCode plugin is global-only — rerunning with -g" >&2
  set -- -g "$@"
fi
rtk init "$@"

Type guard

rust:
fn opencode_invocation_valid(opencode: bool, global: bool) -> bool {
    !opencode || global
}

Try / catch

bash:
rtk init --opencode 2>err.txt || {
  grep -q 'global-only' err.txt && exec rtk init -g --opencode
}

Prevention

When it happens

Trigger: `rtk init --opencode` without -g/--global — e.g. running init inside a project directory expecting a local install; the flag parses, but the global-only check fails before installation.

Common situations: Following generic install docs while sitting in a repo; users assuming all integrations are project-local like the default Claude Code mode; scripted setup that passes --opencode unconditionally but -g only sometimes.

Related errors


AI-assisted analysis of rtk-ai/rtk@d977e1c316 (2026-08-16). Data as JSON: /api/errors/61e91f76cca3bc75. Report an issue: GitHub.