{"record":{"id":"16133b506c8711f2","repo":"rtk-ai/rtk","slug":"at-least-one-of-install-claude-or-install-opencode","errorCode":null,"errorMessage":"at least one of install_claude or install_opencode must be true","messagePattern":"at least one of install_claude or install_opencode must be true","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/hooks/init.rs","lineNumber":327,"sourceCode":"\n        if install_windsurf {\n            run_windsurf_mode(ctx)?;\n        } else if install_cline {\n            run_cline_mode(ctx)?;\n        } else {\n            // Mode selection (Claude Code / OpenCode)\n            match (install_claude, install_opencode, claude_md, hook_only) {\n                (false, true, _, _) => run_opencode_only_mode(ctx)?,\n                (true, opencode, true, _) => run_claude_md_mode(global, opencode, ctx)?,\n                (true, opencode, false, true) => {\n                    run_hook_only_mode(global, patch_mode, opencode, ctx)?\n                }\n                (true, opencode, false, false) => {\n                    run_default_mode(global, patch_mode, opencode, ctx)?\n                }\n                (false, false, _, _) => {\n                    if !install_cursor {\n                        anyhow::bail!(\n                            \"at least one of install_claude or install_opencode must be true\"\n                        )\n                    }\n                }\n            }\n\n            // Cursor hooks (additive, installed alongside Claude Code)\n            if install_cursor {\n                install_cursor_hooks(ctx)?;\n            }\n        }\n    }\n\n    if !dry_run {\n        prompt_telemetry_consent()?;\n        // Best-effort: unconditionally re-run tracking-DB schema migrations during\n        // install/upgrade (bypassing the `user_version` gate `Tracker::new()` uses\n        // on its hot path). This both pre-warms the schema so the first PreToolUse","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/rtk-ai/rtk/blob/36788f6bd4932037caac5cbb1d15d6e2fb9f33da/src/hooks/init.rs#L309-L345","documentation":"In rtk init's non-codex branch, the match over install flags requires at least one of the Claude or OpenCode install targets. If none is selected and Cursor was also not requested, run() bail!s with this internal-style message. It guards against a no-op `rtk init` invocation that would otherwise silently do nothing.","triggerScenarios":"Running `rtk init -g` (or `rtk init`) with no mode/agent flags: install_claude=false, install_opencode=false, and install_cursor=false, hitting the `(false, false, _, _)` match arm.","commonSituations":"Users assuming bare `rtk init` has sensible defaults; scripts that strip flags dynamically and end up with an empty invocation; typos in agent names that disable the intended flag.","solutions":["Pass an explicit target: `rtk init` defaults aside, use `rtk init -g --opencode`, `rtk init --agent cursor`, or the default Claude mode flag","Check `rtk init --help` for the correct flag spelling for your target agent","If you wanted Codex mode, use `rtk init -g --codex` instead"],"exampleFix":"// before\nrtk init -g\n// after\nrtk init -g --opencode","handlingStrategy":"validation","validationCode":"const args = process.argv.slice(2);\nconst hasTarget = ['--codex','--opencode','--agent','--claude'].some(f => args.includes(f));\nif (args[0] === 'init' && !hasTarget) {\n  throw new Error('rtk init needs a target: --codex, --opencode, --agent <x>, or default Claude mode');\n}","typeGuard":null,"tryCatchPattern":"try {\n  execFileSync('rtk', ['init', '-g', '--opencode'], { stdio: 'inherit' });\n} catch (e) {\n  if (String(e.stderr).includes('at least one of install_claude or install_opencode')) {\n    console.error('No install target selected; add a mode/agent flag.');\n  }\n  throw e;\n}","preventionTips":["Never invoke bare `rtk init`; always pass at least one target flag","Check flag spelling (--agent cursor vs cursor) to avoid silently deselecting the target","When building flags dynamically, assert the final list is non-empty"],"tags":["cli","argument-validation","missing-argument","no-op"],"backgroundTag":"missing-required-argument","analyzedSha":"36788f6bd4932037caac5cbb1d15d6e2fb9f33da","analyzedAt":"2026-09-03T16:33:57.738Z","contentChangedAt":"2026-09-03T16:33:57.738Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}