Pushary - Approve AI requests from your lock screen

by
One command connects your AI agents to your lock screen. When Claude Code, Codex, Cursor, Gemini CLI, Hermes, or Claude Cowork stops to ask, you tap yes from your phone and the run keeps moving. New in this launch: native iPhone and Android apps. Pairing is a QR code you scan from the terminal, no key to paste. Per-tool policies auto-approve the safe reads. Every decision lands in an audit trail.

Add a comment

Replies

Best

Congrats on the launch, the fail-closed default for lost connectivity stood out, most agent tools just retry and hope. Curious how the auto-approve policies scope in practice: per project or repo, or one policy that applies account-wide, so a different agent session under the same account could end up inheriting an approval meant for a different job entirely.

 

Good instinct, that's the exact failure mode worth worrying about. Two different mechanisms here, and they behave differently.

A one-off approval, where you tap yes on a specific blocking call, is bound to that single request. It resolves that one call and nothing else. A different session asking for its own git push raises its own request with its own id, so an approval never carries from one job to another. The scenario you're describing doesn't happen.

The standing auto-approve rules are the separate thing. They live at the workspace level and match on the tool plus its arguments, so you scope them by pattern, not by session. Read() approving everywhere is deliberate, since reads are safe. Anything with real blast radius you'd pin down, like Edit(src/) or a specific command, so it can't quietly cover work it was never meant to. Finer per-repo scoping on those standing rules is where I'd most want your input, because teams running very different projects under one account is exactly who this has to fit.

 That distinction answers the worry cleanly, request-scoped one-offs can't leak between sessions. The standing rules are where I'd poke at the same edge you flagged: if two different repos under one account both have a path that matches the same pattern, say Edit(src/), does the match key include which repo or workspace raised the request, or is it purely tool plus args regardless of which project it came from? That's the exact case a multi-client setup would hit first.

 

today the match key is tool plus args, not repo-aware. Two repos with the same src/ path both match a single Edit(src/**) rule, because the match never looks at which repo the call came from. Policies are scoped to the workspace behind your API key, so the blind spot is one key running across several repos, which multi-client setups hit first.

The fix is to fold the repo identity into the match key, so a standing rule is scoped to where it was created and you broaden it to the whole workspace deliberately, not by default. Narrow first, widened on purpose.

That's going up the list. "Same path name, different repo" is a case that looks fine right up until an approval quietly covers the wrong one, and it's much cheaper to fix now than after. Appreciate you pushing on it.

 Narrow-first, widened on purpose is exactly the right default for something with this much reach per key. Good on you for tracing it down to the match logic instead of just patching the symptom.

Showing a diff on tap is the right baseline, but I'd push on a different gap. The thing missing at approval time isn't only what's on the screen, it's what's in the approver's head. At the terminal the whole session is scrolled above you. On a lock screen you get one diff and none of the intent you set 40 minutes ago and have half-forgotten. So you end up approving "does this change look ok" when the real question is "does this still match the plan", and a diff alone can't answer that.

Second thing is the medium. A notification trains a reflex, notifications are things you clear. The format that makes tapping yes fast also nudges toward yes, because that's what we do with the other 200 a day.

So my question is less about richer previews and more: does anything reconnect the approval to the original goal, not just the pending step? Something that lets me answer "is the agent still on track" and not only "is this one command safe"?

 

Jernej, this is the best version of this critique I've seen, so I'll answer both halves straight.

On intent: you're closer to having it than the lock-screen framing suggests. Every approval already carries the intent we pull from the session, the last thing you actually told the agent, sitting next to the pending step. So you're not answering "does this diff look ok" cold, you're answering it with your own ask in view. What we don't do yet is pin the goal you set 40 minutes ago and show drift against it across a long run. The full session is captured server-side, so the material to answer "still on track" exists, it just isn't wired to the approval as a plan-versus-now check. That specific thing, is-it-on-track rather than is-this-step-safe, is what I want to build next.

On the medium: you're right that a notification trains a clear-it reflex, and it's the strongest argument against fast-yes I've heard. What saves it here is fail-closed. Clearing or ignoring a Pushary request never approves, it denies or waits. So the reflex that burns you on the other 200 fails safe on this one. And because policy keeps the safe stuff off your phone, the ones that reach you aren't in that pile. Where you're still right: the highest-stakes calls shouldn't feel like the rest, and making them deliberately higher friction is on me.

If you want to get into how you'd represent "the plan" so drift is checkable, I'd gladly entertain that too :)

  The way I'd make drift checkable is to stop treating the plan as prose and turn it into a small frozen contract at run start. Not the goal in a sentence, but the few things that would mean you've gone off it: allowed scope (these paths/modules), off-limits areas (don't touch auth or the payment code), a couple of invariants (public API stays stable, migrations stay reversible), and a short definition of done. The agent can draft that from the goal, you confirm it once, and it freezes.

After that "on track" stops being a judgment and becomes mechanical: does this step touch anything outside the contract or break an invariant. Then the approval can lead with the delta against the plan, not the diff in isolation. "This step edits auth, which you marked off-limits" is a very different prompt than "run this command". You're already capturing the session server-side, so this is a layer on top of what you have, not new plumbing.

The one trap: legitimate scope changes. Halfway through you decide the feature also needs Y. If that isn't its own explicit step ("agent wants to widen scope to include Y, approve?") then every real change reads as drift and you're back to alert fatigue, just a new flavour. So plan edits have to be first-class approvals, separate from step approvals.

Curious where you'd put the contract though: do you see the human writing those constraints, or the agent proposing them and the human just ratifying at run start?

 

Jernej, this is the right shape, and the contract framing is what unlocks it. On your actual question, I'd land on agent proposes, human ratifies, but with a split that keeps the ratify from dying of friction.

The off-limits areas and invariants are the durable part. Don't touch auth, don't touch payments, migrations stay reversible, public API stays stable, those don't change run to run. So they shouldn't be rewritten every time, they should be standing guardrails per repo that carry across runs. That's close to what the policy layer already does, so "off-limits" becomes a deny on those paths, set once. The per-run contract then shrinks to the part that actually varies: the scope for this task and the definition of done, which the agent drafts from the goal and you ratify against the standing guardrails.

I wouldn't have the human write it cold, because adoption dies, nobody hand-authors a contract before every run, and anything that adds friction at run start won't get used. But ratify can't be a rubber stamp for the reason you already named: wave through a contract the agent scoped too wide and you've just moved the reflexive yes up a layer. So the ratify view has to lead with the consequential bits, what's off-limits and what invariants are claimed, and make widening take a real tap.

The scope-change trap falls out of the same mechanism rather than needing a new one. The delta-check that flags drift is exactly what raises "agent wants to widen scope to include Y, approve?", one signal, two outcomes. And approving it has to amend the frozen contract, so the next ten steps in that area stop re-prompting. That's what keeps it from becoming a new flavour of fatigue.

Where it gets genuinely hard is invariants that aren't path-shaped. "Public API stays stable" is checkable, "migrations stay reversible" much less so without running something. That's the part I don't have a clean answer for yet, and it's where I'd keep pulling on this with you.

  Agent-proposes-human-ratifies with the guardrails standing per repo is exactly right, that's the version that actually gets used.

On the non-path invariants, I'd stop trying to check them at approval time and turn each one into a required artifact plus a cheap check that runs in the sandbox. "Migrations stay reversible" isn't provable from the diff, but you can require the step to ship a down-migration and have the sandbox run up, down, up and diff the schema. If it doesn't round-trip, that's your drift signal, and it surfaces to the approval instead of a human eyeballing it. "Public API stays stable" becomes a contract/snapshot test, any change to the public surface is the tripwire.

So maybe two kinds of invariant: path-shaped ones that are a static deny before the step, and check-shaped ones that run as a tripwire and only escalate to you when they fire. The human ratifies the invariant either way, the system just picks how it's enforced.

The honest limit is it only covers invariants you can write a check for. "Migrations reversible", yes. "This stays readable" or "this respects what the user actually meant", no, those stay human and the contract shouldn't pretend otherwise. But the mechanizable ones are most of the dangerous ones, so it's a fair trade.

Hey Aadil! Looks awesome and sounds so promising for every dev. Wish you all the best here!

 

Thanks Germán, really appreciate you stopping by. Means a lot. 🙏

if there are any questions you have after using the product I'm always here or email at

- Looks cool, and very useful for streamlining development workflows. An plans to integrate with in the future?

 

Thanks Brent! Short answer, yes, that's exactly the kind of agent I want to cover.

Today, if OpenCode can load an MCP server (most agents can), you can wire Pushary in right now through the "Other" option in setup and get the notifications and ask-a-human flow. The piece that makes it first-class, approve or deny on its tool calls, needs a pre-tool hook I can wrap, the same way Claude Code and Codex expose theirs. If OpenCode has that surface, a proper adapter is quick and I'd build it.

Point me at its hook or permission API and I'll take a real look.

 - Awesome, yes opencode does support MCP integration now.

 

Legend! <3

Love the switch to QR pairing! With one unified inbox, how does it handle multiple agents requesting approval at the exact same time?

 

Thanks Aren! They don't collide, because nothing is shared between them. Each request is its own item with its own id, tagged with the agent, session, and project it came from, so three agents asking at once show up as three separate cards in the inbox, each labeled so you can tell them apart.

You answer them independently, and answering one resolves only that request. An unanswered one waits or denies on its own timeout without holding up the others, and the finalize step is guarded so a fast double-tap or two devices can't record conflicting answers for the same request. Policies also quietly clear the safe ones, so a burst rarely lands on you all at once.

Since approvals happen right from the lock screen, what stops an accidental tap (say, phone in a pocket) from approving something with real blast radius? Is there a confirmation step or biometric check? or does every lock screen tap get treated the same regardless of what it's approving?

 

Clement, good thing to poke at, and no, every tap is not treated the same.

Deny is the only true one-tap, because denying is always safe. Approve is gated: the Approve action requires device authentication, so tapping it wakes Face ID or your passcode before anything registers. A phone in your pocket can't approve, the tap just hits the unlock wall and nothing happens.

There's a second layer too. When the server flags a decision as off or high-risk, it drops the one-tap Approve button from the lock screen entirely, so for those you can't approve from the notification at all, you open the app and go through the full context first.

So the accidental yes you're describing is exactly what the auth gate on approve is there for. Denying stays instant since it's always safe, and approving never happens without a deliberate unlock.

 That's a solid answer, the unlock wall makes sense! Curious if the high-risk threshold is user-configurable, or fixed by your classifier. And does Android get the same two-layer treatment as iOS?

 

Two good ones, and the honest answers differ by question.

On the threshold: it's currently computed, not a dial you set. The gate that drops one-tap approve fires when the action is classified destructive, or when it doesn't match the intent you gave the agent, so a high-consequence call that also looks off-plan loses the shortcut. What you do configure is the policy on top, you can force any tool to always ask or to deny outright, and an explicit rule you write wins over the classifier. So it's a fixed safety floor with your policy layered above it. A user-tunable risk slider isn't there yet, and if that's what you're after I'd rather say so than pretend the dial exists.

On Android: partly, and I won't claim full parity. The gating layer, dropping one-tap approve for the risky or off-plan calls, works on both, it's server-driven and the Android background handler enforces it too. The device-unlock wall on the everyday approve button is the iOS-specific piece, because that authentication flag is an iOS notification capability Android doesn't expose the same way. So on Android a routine approve isn't held behind Face ID at the notification layer yet. Closing that with an in-app biometric confirm on Android is on the list, and it's a fair gap to call out.

 Appreciate the straight answer, especially not pretending the risk dial exists. One practical follow-up: until the in-app biometric confirm ships on Android, would you recommend forcing "always ask" on high-consequence tool categories there to make up for the missing unlock wall?

Congrats on the launch man, almost overtook us too aha)

Is this essentially an app on mac and on iphone?

 

Haha appreciate it man, good luck with yours too )

Not quite an app on both ends. On the Mac side there's no desktop app, it's a one-command CLI that hooks into the agent you already run, Claude Code, Codex, whatever. On the phone side yes, it's a real native app, iPhone and Android, and there's a web version too if you'd rather not install anything. The agent keeps running on your machine, the phone is just where the decisions reach you.

Anyone running Claude Code or Cursor heavily knows the pain of an agent stuck waiting on a yes while you are away from the keyboard. Pushary going after that with lock-screen approvals is well targeted. The thing that would keep me using it is trust, showing enough of what the agent wants to do that I can approve safely from my phone. Get that right and this fits into a lot of workflows.

 

That's exactly the bar. A yes/no with no context is just a slower terminal. So the approval shows the real call, the exact command or file, the agent, and the project, and policies mean only the risky stuff reaches you in the first place. Richer previews like an inline diff before you approve are where we're headed next. If you run agents heavy, I'd want your read on where the context isn't enough yet.

'the slowest step in a run is usually you' is the honest line. do the auto-approve policies stay fixed per tool, or learn which yes/no i keep repeating?

 

thanks mate, killer question, we call it the autopilot, every week it learns from your approval behaviour and suggests edits to your policies, you can approve them with a tap too.

much love <3

Using the lock screen as the place where an agent reaches the human is a very natural and also great idea. Can teams require Face ID or another authentication step for especially sensitive approvals?

 

Right instinct, and it's exactly where this goes.

Today there's already a quiet baseline. The request lands on a device that's yours and already unlocked, and sensitive tools never auto-approve. You tag them, they wait for a real human or escalate, and nothing slips through if you drop off signal.

The Face ID layer you're describing is the next one. Both platforms hand us local biometric auth, and since policy is already per-tool, it drops in as a flag: require a biometric confirm on Approve for anything you mark sensitive. Tap Approve, Face ID re-checks, then it counts. That's on the build list.

If your team can tell me where you'd draw the "especially sensitive" line, I'll build it with you. That's the input that makes it sharp.

shoot me an email at and we can make it real from there <3