{"record":{"id":"4b1f01d9a6592385","repo":"atuinsh/atuin","slug":"expected-atuin-hook-agent-or-atuin-hook-install-agent","errorCode":null,"errorMessage":"expected `atuin hook <agent>` or `atuin hook install <agent>`","messagePattern":"expected `atuin hook <agent>` or `atuin hook install <agent>`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin/src/command/client/hook.rs","lineNumber":47,"sourceCode":"#[derive(Parser, Debug)]\n#[command(infer_subcommands = true, args_conflicts_with_subcommands = true)]\npub struct Cmd {\n    #[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).await,\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\n/// How the user makes an agent pick up a freshly installed extension. Only the\n/// extension-based agents need a nudge; command-hook agents load on next run.\nfn reload_hint(harness_name: &str) -> Option<&'static str> {\n    match harness_name {\n        \"pi\" => Some(\"Reload pi with `/reload` or restart pi.\"),\n        \"opencode\" => Some(\"Restart opencode to load the plugin.\"),","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin/src/command/client/hook.rs#L29-L65","documentation":"`atuin hook` supports two forms: `atuin hook <agent>` (fire the hook) or `atuin hook install <agent>` (install it). Running it with neither an action nor an agent gives no usable target, so `run` bails with usage guidance.","triggerScenarios":"Running bare `atuin hook` with no arguments — the match arm `(None, None)` in `HookCmd::run`.","commonSituations":"Typing the subcommand to explore it without args; a shell hook script losing its argument due to quoting bugs or an unset variable.","solutions":["Pass an agent: `atuin hook <agent>` to fire, or `atuin hook install <agent>` to install.","Check `atuin hook --help` for valid agents.","If invoked from a shell hook, verify the agent variable is set and quoted in the hook script."],"exampleFix":"# before\natuin hook\n\n# after\natuin hook install claude  # or: atuin hook claude","handlingStrategy":"validation","validationCode":"# shell: validate args before calling\ncase \"$#\" in\n  0) echo \"usage: atuin hook <agent> | atuin hook install <agent>\"; exit 1;;\nesac","typeGuard":null,"tryCatchPattern":"atuin hook \"$AGENT\" || { echo \"hook failed; pass an agent, e.g. atuin hook claude\"; exit 1; }","preventionTips":["Always pass an agent argument in shell hook scripts.","Quote and default the AGENT variable in wrapper scripts.","Check `atuin hook --help` for accepted agents."],"tags":["cli","missing-argument","hook"],"backgroundTag":"missing-cli-argument","analyzedSha":"900007c48045867e7f44b0f9bc55ad9dbe99ee0d","analyzedAt":"2026-09-19T12:52:51.491Z","contentChangedAt":"2026-09-19T12:52:51.491Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}