When you don't answer
What Pushary does when a permission push goes unanswered — the wait ladder, keyboard bypass, waiting for your phone, and tuning the window
Every gated tool call ends one of four ways: you approve it, you deny it, the terminal takes over, or (with a wait rule) Pushary keeps holding for your phone. Which one happens, and how long it takes, is the wait ladder. It is decided entirely by your policy for that tool, and it is the same ladder the hook enforces and pushary doctor prints, so what you read is what runs.
The ladder, by mode
| Mode | While you're away | If you don't answer |
|---|---|---|
push_first (default) | Ping your phone for pushFirstSeconds | Hand to the terminal, leaving the push live so either place still works |
push_only | Block and wait for your phone up to timeoutSeconds | Apply the timeout action: auto-approve, auto-deny, ask in the terminal, or wait |
terminal_only | Nothing — no push | The agent's own prompt decides |
notify_only | One-way heads-up, never blocks | The terminal decides immediately |
Wait N seconds, then the terminal
This is push_first with pushFirstSeconds — the default. Your phone buzzes, and if you don't tap within the window the terminal prompt appears while the phone push stays answerable. Set the window from the CLI:
# Ping the phone for 45s before the terminal takes over (site default)
npx @pushary/agent-hooks@latest wait 45
# See the full ladder for every tool
npx @pushary/agent-hooks@latest wait status
# Reset the default window
npx @pushary/agent-hooks@latest wait clearpushary wait <seconds> sets the * catch-all window that every tool without its own rule inherits. Per-tool windows live in the dashboard under Agent → Policies.
Keyboard bypass: at your desk, decide at your desk
When you're actively typing in the terminal, buzzing your phone is noise. Pushary detects terminal presence and, in push_first, holds the phone push and shows the native prompt immediately — no wait, no notification. It's automatic; there's nothing to toggle.
To force it for a stretch (every tool decides in the terminal, regardless of policy), use a mode override:
npx @pushary/agent-hooks@latest mode terminal_only --for 1h
npx @pushary/agent-hooks@latest mode status # check / clear with `mode clear`Wait for your phone: the wait action
Set a push_only rule's timeout action to wait and the hook holds for your phone instead of auto-deciding, then hands to the terminal at the ceiling — it never auto-denies. Good for a rule like "prod deploy: I'll approve from my phone."
How long wait can hold is bounded by the agent's hook budget (currently about 110s for Claude Code, 170s for Codex and Gemini, 45s for Cursor), then it falls to the terminal. A longer hold is on the roadmap; today wait means "use the whole window for the phone, and never auto-deny."
If Pushary can't reach you
The ladder always degrades to the safest available approver — you, at the keyboard:
- No device connected — the hook skips the wait and applies the timeout outcome right away (and the response carries a warning to connect a phone under Settings → Connections).
- Pushary unreachable — the hook fails open to the terminal (
ask), because an offline agent can't reach your phone anyway. - The window is longer than the hook can safely wait — the hook hands to the terminal rather than misapplying a timeout action for a window it couldn't fully serve.
See your own ladder
npx @pushary/agent-hooks@latest doctorDoctor prints a Wait Ladder section — your default window, any active mode override, and per-tool overrides — sourced from the same policy the hooks fetch.