{"record":{"id":"bbccdeb31eaeb962","repo":"atuinsh/atuin","slug":"hook-action-cannot-be-combined-with-a-positional-agent","errorCode":null,"errorMessage":"hook action cannot be combined with a positional agent","messagePattern":"hook action cannot be combined with a positional agent","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin/src/command/client/hook.rs","lineNumber":170,"sourceCode":"    #[command(subcommand)]\n    action: Option<Action>,\n\n    /// Which agent's hook format to parse (e.g., \"claude-code\")\n    #[arg(value_name = \"AGENT\", hide = true)]\n    agent: Option<String>,\n}\n\nimpl Cmd {\n    #[instrument(level = \"trace\", skip_all, err)]\n    pub async fn run(self, settings: &Settings) -> Result<()> {\n        match (self.action, self.agent) {\n            (Some(Action::Install { agent }), None) => install(&agent),\n            (None, Some(agent)) => handle(&agent, settings).await,\n            (None, None) => {\n                bail!(\"expected `atuin hook <agent>` or `atuin hook install <agent>`\");\n            }\n            (Some(_), Some(_)) => {\n                bail!(\"hook action cannot be combined with a positional agent\");\n            }\n        }\n    }\n}\n\nfn id_file_path(tool_use_id: &str) -> PathBuf {\n    std::env::temp_dir().join(format!(\"atuin-hook-{tool_use_id}\"))\n}\n\nasync fn handle(agent_name: &str, settings: &Settings) -> Result<()> {\n    let agent = Agent::from_name(agent_name)?;\n\n    if let InstallKind::Extension { reload_hint, .. } = agent.install_kind() {\n        bail!(\n            \"`atuin hook {agent_name}` is not supported. Use `atuin hook install {agent_name}`. \\\n             {reload_hint}\"\n        );\n    }","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/atuinsh/atuin/blob/c0c717ab04c881764bcad4b3d169a507e2432643/crates/atuin/src/command/client/hook.rs#L152-L188","documentation":"The hook command's run() rejects combinations where both an action (like install) and a positional agent are supplied. The two forms are mutually exclusive: either `install <agent>` or a bare `<agent>`. Supplying both is ambiguous, so it bails with this message.","triggerScenarios":"Running something like `atuin hook install claude extra-position` — i.e. clap parses both Some(Action::Install) and Some(agent).","commonSituations":"Misreading the CLI grammar and passing an agent both as the install subcommand argument and as a free positional; scripts concatenating arguments incorrectly.","solutions":["Use only one form: `atuin hook install claude` or `atuin hook claude`","Remove the extra positional argument","Check `atuin hook --help` for the accepted syntax"],"exampleFix":"// before\natuin hook install claude codex\n// after\natuin hook install claude","handlingStrategy":"validation","validationCode":"# exactly one form\nif [[ $# -gt 2 || ($1 == \"install\" && $# -gt 2) ]]; then\n  echo \"usage: atuin hook <agent> | atuin hook install <agent>\"; exit 2\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never combine the install action with a bare positional agent","Quote and count arguments in wrapper scripts","Stick to one documented invocation form"],"tags":["cli","usage","arguments","hook"],"backgroundTag":"mutually-exclusive-flags","analyzedSha":"c0c717ab04c881764bcad4b3d169a507e2432643","analyzedAt":"2026-09-12T07:40:01.341Z","contentChangedAt":"2026-09-12T07:40:01.341Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}