{"record":{"id":"57904733f57518f5","repo":"rtk-ai/rtk","slug":"codex-cannot-be-combined-with-hook-only","errorCode":null,"errorMessage":"--codex cannot be combined with --hook-only","messagePattern":"--codex cannot be combined with --hook-only","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/hooks/init.rs","lineNumber":286,"sourceCode":"    install_windsurf: bool,\n    install_cline: bool,\n    claude_md: bool,\n    hook_only: bool,\n    codex: bool,\n    patch_mode: PatchMode,\n    ctx: InitContext,\n) -> Result<()> {\n    let InitContext { dry_run, .. } = ctx;\n    // Validation: Codex mode conflicts\n    if codex {\n        if install_opencode {\n            anyhow::bail!(\"--codex cannot be combined with --opencode\");\n        }\n        if claude_md {\n            anyhow::bail!(\"--codex cannot be combined with --claude-md\");\n        }\n        if hook_only {\n            anyhow::bail!(\"--codex cannot be combined with --hook-only\");\n        }\n        if matches!(patch_mode, PatchMode::Auto) {\n            anyhow::bail!(\"--codex cannot be combined with --auto-patch\");\n        }\n        if matches!(patch_mode, PatchMode::Skip) {\n            anyhow::bail!(\"--codex cannot be combined with --no-patch\");\n        }\n        run_codex_mode(global, ctx)?;\n    } else {\n        // Validation: Global-only features\n        if install_opencode && !global {\n            anyhow::bail!(\"OpenCode plugin is global-only. Use: rtk init -g --opencode\");\n        }\n\n        if install_cursor && !global {\n            anyhow::bail!(\"Cursor hooks are global-only. Use: rtk init -g --agent cursor\");\n        }\n","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/rtk-ai/rtk/blob/d977e1c31621fe8704e6500ceeb9c7a0de2b6836/src/hooks/init.rs#L268-L304","documentation":"`rtk init --codex` is an exclusive mode that performs its own complete installation; the validation at src/hooks/init.rs:286 rejects --hook-only alongside it. --hook-only means 'install only hooks, skip other setup', which has no meaning inside codex mode's single-purpose flow.","triggerScenarios":"`rtk init --codex --hook-only`. The pair parses at the clap level and fails only in init's validation, with --codex named as the offending mode.","commonSituations":"Copying a minimal-install invocation (`rtk init --hook-only`) and appending --codex; scripts trying to keep the footprint small while adding Codex; misunderstanding codex mode as composable.","solutions":["Run `rtk init --codex` alone — codex mode is already a scoped, minimal install","If you wanted hook-only for Claude Code, drop --codex: `rtk init --hook-only`","Check `rtk init --help` before combining rarely-used flags"],"exampleFix":"# before\nrtk init --codex --hook-only\n# --codex cannot be combined with --hook-only\n\n# after\nrtk init --codex        # codex mode is already scoped\nrtk init --hook-only    # separate concern, separate run","handlingStrategy":"validation","validationCode":"bash:\nif [[ \"$*\" == *--codex* && \"$*\" == *--hook-only* ]]; then\n  echo \"--codex and --hook-only are mutually exclusive\" >&2\n  exit 2\nfi\nrtk init \"$@\"","typeGuard":"rust:\nfn codex_hook_only_conflict(codex: bool, hook_only: bool) -> bool {\n    codex && hook_only\n}","tryCatchPattern":"rust:\n// clap-level: #[arg(long, conflicts_with = \"hook_only\")] codex: bool,\nif let Err(e) = init::run(...) {\n    if e.to_string().contains(\"--codex cannot be combined with --hook-only\") { exit(2); }\n}","preventionTips":["Codex mode is already scoped/minimal — --hook-only adds nothing there","Keep hook-only for the Claude Code path","Declare the conflict in clap so users get usage errors, not runtime bails"],"tags":["init","cli","usage","flag-conflict","codex","hook-only"],"backgroundTag":null,"analyzedSha":"d977e1c31621fe8704e6500ceeb9c7a0de2b6836","analyzedAt":"2026-08-16T05:40:46.291Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}