atuinsh/atuin · error
hook action cannot be combined with a positional agent
Error message
hook action cannot be combined with a positional agent
What it means
`atuin hook` treats a positional agent and an action as mutually exclusive: the action form is `atuin hook install <agent>` where the agent is a flag value, not a bare positional. Providing both `--install <agent>` and a positional agent is ambiguous, so `run` bails.
Solutions
- Use exactly one form: `atuin hook <agent>` or `atuin hook install --agent <agent>` per CLI syntax (check `atuin hook --help`).
- Remove the redundant positional argument when using the install action.
- Fix any wrapper script that passes both forms.
Example fix
# before atuin hook install claude # if CLI takes --agent, positional is rejected # after atuin hook install --agent claude
Defensive patterns
Strategy: validation
Validate before calling
# pass the agent exactly once, in the form your atuin version expects if [ -n "$AGENT" ] && [ -n "$INSTALL" ]; then echo "pass either 'atuin hook <agent>' or 'atuin hook install --agent <agent>'"; exit 1 fi
Try / catch
atuin hook install --agent "$AGENT" 2>&1 | grep -q 'combined with a positional agent' && echo "remove the duplicate positional agent"
Prevention
- Use one canonical invocation form in scripts.
- Don't concatenate the agent positionally when using an install action.
- Verify against `atuin hook --help` after upgrades.
When it happens
Trigger: Running e.g. `atuin hook install claude` where claude is also captured positionally, or combining `Some(Action::Install{..})` with `Some(agent)` in `HookCmd::run` — the `(Some(_), Some(_))` arm.
Common situations: Users typing `atuin hook install <agent>` expecting install to be global-ish while also passing the agent positionally; scripting that concatenates args and duplicates the agent.
Understand the failure class
Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.
Related errors
- `atuin hook ` is not supported. Use `atuin hook install `.
- expected `atuin hook
- A script named ' ' already exists
- agent does not use JSON hooks
- `atuin history tail` requires Atuin to be built with the…
AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19).
Data as JSON: /api/errors/bbccdeb31eaeb962.
Report an issue: GitHub.
Appendix: source
Thrown at crates/atuin/src/command/client/hook.rs:50
#[command(subcommand)]
action: Option<Action>,
/// Which agent's hook format to parse (e.g., "claude-code")
#[arg(value_name = "AGENT", hide = true)]
agent: Option<String>,
}
impl Cmd {
#[instrument(level = "trace", skip_all, err)]
pub async fn run(self, settings: &Settings) -> Result<()> {
match (self.action, self.agent) {
(Some(Action::Install { agent }), None) => install(&agent).await,
(None, Some(agent)) => handle(&agent, settings).await,
(None, None) => {
bail!("expected `atuin hook <agent>` or `atuin hook install <agent>`");
}
(Some(_), Some(_)) => {
bail!("hook action cannot be combined with a positional agent");
}
}
}
}
fn id_file_path(tool_use_id: &str) -> PathBuf {
std::env::temp_dir().join(format!("atuin-hook-{tool_use_id}"))
}
/// How the user makes an agent pick up a freshly installed extension. Only the
/// extension-based agents need a nudge; command-hook agents load on next run.
fn reload_hint(harness_name: &str) -> Option<&'static str> {
match harness_name {
"pi" => Some("Reload pi with `/reload` or restart pi."),
"opencode" => Some("Restart opencode to load the plugin."),
_ => None,
}
}View on GitHub (pinned to 900007c480)