Independent AI intelligence Two editions daily · ET
Fervor AI

Analysis · November 8, 2026 · repo

DIYgod/pinkyagent-securitymcpagent-harness

Pinky Lets AI Agents Use Your Phone, and Its Approval Gate Is the Part Worth Copying

The new open-source app puts "ask me first" outside the agent's reach. It also tells you exactly how an agent could walk around it.

Most "ask permission first" features in AI agents share an awkward secret. The program asking for permission is usually the same program that could skip asking.

That is fine when the worst case is a bad file edit. It gets less fine when the agent is holding your phone, the device with your bank app, your messages and the one-time codes that open everything else.

Pinky, an open-source app that climbed GitHub's trending boards this weekend, lets AI agents like Claude Code operate a real iPhone or Android phone. The interesting part is not that it can tap buttons. Plenty of tools can. It is where it puts the "yes."

The short version: Pinky makes the approval a separate program's job, treats silence as "no," and then, in its own FAQ, tells you the one route an agent could use to get around it. That combination is a design worth copying, whatever you build.

What Pinky is

Pinky is a desktop app for macOS, Windows and Linux. You plug in a phone over USB (or connect over Wi-Fi), and Pinky mirrors its screen on your computer.

Agents connect to it through MCP, the Model Context Protocol, a standard way for AI tools to plug into outside apps. Once connected, an agent can look at the phone's screen and tap, type and scroll, while you watch the mirror.

The README lists Claude Code, Claude Desktop, Codex, Cursor, VS Code, Copilot CLI, Windsurf and Gemini CLI as agents you can connect from its settings. It is Apache-2.0 licensed, has a few hundred stars (GitHub and the shields.io badge disagreed on November 8, roughly 360 to 410), and shipped release v2026.1108.14 the same day. The README calls its status "pre-alpha."

Where the "yes" lives

Here is the design choice that makes Pinky worth a look.

Think of a bank teller with a manager's key. The teller can do most things alone. For anything over a limit, the transaction stops until the manager turns a key that only the manager holds. The teller cannot turn it, however politely they ask.

Pinky works the same way. The agent talks to Pinky's gateway, a middle layer between the agent and the phone. Per the README, "the rules run in Pinky's gateway, so an agent can't approve itself." When a step needs you, the agent gets back a status called approval_pending instead of a result, and the step waits for a click in Pinky's window.

What waits by default:

  • Payments, trades and transfers.

What you can add in Settings > Safety:

  • Sends, orders, deletions, calls, installs, links that leave the app, and settings changes. Or every single step.

The README says Settings > Safety also offers "Ask before every action" and "Read-only mode."

Then there are the defaults that do not depend on catching a button at all. Banking, wallet and password-manager apps are hidden from agents, along with their notifications. An agent that needs one has to ask, and you can allow it for that task only. Agents cannot type into password or one-time-code fields, and codes inside notifications are masked.

Why a phone is a harder case than code

A coding agent mostly touches files you can roll back with git. A phone is full of actions with no undo: a payment, a sent message, a deleted photo, a two-factor code read off the lock screen. The agent also sees the phone the way you do, as pixels and buttons, not as an API with named, checkable operations. That is why Pinky has to guess which button is risky from its label, and why hiding whole apps by default matters more than any single rule.

Silence means no

The detail I liked most is small. The README states that "no answer within 60 seconds means no."

Most approval prompts fail the other way. If nobody answers, they either hang forever or, worse, time out into "go ahead." Pinky picks the safe failure. If you walked away from your desk, the payment does not happen.

There is also a stop button for when things go sideways. The README lists a "Stop all" shortcut, and clicking the mirror pauses the agent. On Android, touching the phone pauses it too.

The hole Pinky tells you about

Here is the part that earns trust. Pinky's FAQ says plainly that an agent which can run commands on your computer could reach the phone without Pinky, through adb for example, and skip its rules.

adb (Android Debug Bridge) is the command-line tool developers use to control Android phones over USB. Pinky uses it under the hood. If your agent also has a terminal, and Claude Code usually does, it can type adb shell input tap ... and talk to the phone directly. The gateway never sees the request.

That is the locked front door with the garage open. The manager's key protects the teller window, not the back office.

Pinky's advice is to run such agents in a sandbox with no access to the phone, or to plug the phone into a different computer and let the agent reach Pinky there over HTTP, as described in its MCP docs. Put the gate on a machine where the gate is the only road.

This is the real lesson. An approval rule binds an agent only when the agent has no other way to the thing it protects.

Put this into practice

The lowest-friction setup, on a Mac with Homebrew:

brew install --cask diygod/tap/pinky
claude mcp add --scope user pinky -- pinkyctl mcp

The command is pinkyctl, not pinky, because another program named pinky is common on Unix systems. Other agents take the same server as JSON config:

{ "mcpServers": { "pinky": { "command": "pinkyctl", "args": ["mcp"] } } }

Windows and Linux installers are on the releases page.

Then, before you hand an agent your real phone:

  1. Open Settings > Safety and widen the gate. Turn on approvals for sends and deletions at least. Start with "Ask before every action" for your first few runs so you see what the agent tries.
  2. Separate the shell from the phone. If your agent can run terminal commands, either run it in a sandbox that cannot see USB devices, or plug the phone into a second computer and connect to Pinky over HTTP. Remote access is off by default: you turn on Settings > Remote agents, it listens on 127.0.0.1:7465 unless you pick another address, and every request needs the agent token. If you skip this, treat Pinky's rules as advice to the agent, not a lock.
  3. Try a dull task first. "Open Settings and tell me the battery health" shows you the loop: the agent reads the screen, taps, reads again. Expect it to be slower than doing it yourself. That is normal.
  4. Use a spare phone if you have one. The safest test device is the one without your banking apps.

Phone requirements, per the README: Android 10 through 17 over USB, or iPhone on iOS 17.4 and later. iOS 27 needs no helper app. iOS 17.4 through 26 needs Appium's WebDriverAgent (a small helper app that lets software drive an iPhone's screen), which Pinky signs with your own Apple ID, and with a free Apple ID that signature lasts 7 days.

Honest limitations

It is pre-alpha. The README says so, and points to a list of features that are built but still waiting for someone to try them.

Button detection reads labels. Pinky spots risky buttons by their text, in 10 languages, and the README warns that an unusual label could slip through. A banking app that calls its payment button something odd might not trigger the gate. Hiding those apps by default is the backstop.

Wi-Fi on older Android opens a door. On Android 10, "Use Wi-Fi instead" makes Pinky run adb tcpip on port 5555, and the README warns that any computer on the same network can then try to connect, until the phone restarts. Use it only on Wi-Fi you trust.

The Windows installer is unsigned, so SmartScreen will warn you.

The older-iPhone path is untested on real hardware. The README says the WebDriverAgent route "has not been tried on an iPhone below iOS 27 yet"; it was tested on iOS 27 and in simulators.

Banking apps may balk on Android. Pinky's companion app turns on an Android accessibility service while an agent works, and the README notes banking apps refuse to run next to one.

Telemetry is on by default. Per Pinky's telemetry doc, anonymous usage statistics are on from the first run with no notice. Turn them off in Settings > Privacy or set DO_NOT_TRACK=1.

The pattern to steal

Even if you never let an agent near your phone, the shape is easy to reuse. Here is a minimal sketch of the same idea for any tool an agent calls, written as plain Python. It is not Pinky's code, just the pattern:

RISKY = {"send_payment", "delete_file", "send_message"}

def gateway(action, args, ask_human):
    # The agent calls this. It never calls the tool directly.
    if action in RISKY:
        answer = ask_human(action, args, timeout_seconds=60)
        if answer != "yes":          # "no", or no answer at all
            return {"status": "denied"}
    return run_tool(action, args)

Three things make it work. The function that runs the tool is only reachable through the gateway. The human's answer arrives on a channel the agent cannot write to, like a desktop window or a phone push. And anything other than an explicit "yes," including a timeout, counts as a refusal.

The weak point is always the same one Pinky names: some other route to run_tool. In a real system that route is a shell, an API key sitting in an environment variable, or a second MCP server with the same powers. Find those before you trust the gate.

Pinky is a clean example of three rules for any approval system you build:

  1. Enforce the rule in a separate process the agent cannot write to.
  2. Make silence a "no."
  3. Write down, in public, the path that skips your gate.

That third one is rare. Most tools would rather you not think about it. If you are building agent permissions this quarter, read Pinky's FAQ first, then go find your own adb.

Sources: DIYgod/pinky README and MCP docs, reviewed at release v2026.1108.14 on November 8, 2026; star counts from GitHub and shields.io on November 8, 2026 (they differed); Model Context Protocol.