ZyVOP Logo
Content That Connects
SeriesAI NewsLeaderboardWrite for Us
ZyVOP Logo
Content That Connects

Empowering developers and creators with cutting-edge insights, comprehensive tutorials, and innovative solutions for the digital future.

Content

  • Categories
  • Tags
  • Badges
  • Leaderboard
  • Write Article
  • Newsletter

Company

  • About Us
  • API Documentation
  • Write for Us
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

ยฉ 2026 ZyVOP. Crafted with care for the developer community.

Made with โค๏ธ by the ZyVOP team
All systems operational
HomePair a Phone to a Mac AI Agent Without Putting the API Key in the QR Code

Pair a Phone to a Mac AI Agent Without Putting the API Key in the QR Code

Igor Ganapolsky
Igor GanapolskyFounder
August 14, 2026
3 min read
#AI agents#Mobile#Tailscale#security
๐Ÿ‘1

Pair a Phone to a Mac AI Agent Without Putting the API Key in the QR Code

Remote control for a local AI agent creates an awkward setup problem. The phone needs enough information to reach and authenticate to the computer, but a QR code is a poor place for a long-lived API key. QR payloads can end up in screenshots, camera history, debugging output, or a copied deep-link URL.

I build Hermes Mobile, an Android and iOS client for controlling a Hermes agent running on your own computer. The pairing path in the current code uses a short-lived, opaque pairing code instead of embedding the gateway key in the deep link. This is the implementation pattern, the tradeoffs, and a reproducible way to inspect it.

The client and gateway are different roles

The phone runs the mobile client. The Mac or other computer runs the Hermes gateway on port 8642. Wi-Fi and Tailscale only provide a network route between them:

phone client -> private Wi-Fi or Tailscale -> computer gateway :8642

That distinction matters during discovery. A computer picker should list machines that answer as Hermes gateways, not every device visible on the tailnet. The handset's own Tailscale address is intentionally filtered so the app does not offer to connect back to itself.

Put a one-time code in the link, not the gateway key

The setup link carries two pieces of pairing information:

hermes://setup?pairCode=HTYH6PSW&pairServer=http%3A%2F%2F100.x.y.z%3A8765

The pairCode is an opaque one-time value. pairServer identifies the private endpoint that can exchange it. The long-lived gateway credential is not a query parameter in this path.

On the phone, the exchange is deliberately small. Reduced to its essential operation, it is:

const response = await fetch(
  `${pairServer}/pair-exchange?code=${encodeURIComponent(pairCode)}`
);

if (!response.ok) return null;
const gatewayConfig = await response.json();

After a successful exchange, Hermes Mobile saves the returned key through platform secure storage backed by Android Keystore or iOS Keychain. The phone then uses the returned gateway URL and key for authenticated health checks and sessions.

Make replay fail

The computer keeps the pairing-code map in memory with an expiration time and a consumed flag. A valid exchange consumes the code. A second request with the same code fails. Unknown and expired codes fail too.

The current pairing page displays codes with a twenty-minute maximum lifetime so a user has time to move between screens, but the page refreshes the displayed code every minute. The important property is not merely that the code is short. It is that replay is rejected after the first successful exchange.

This approach does not magically make an untrusted network safe. The exchange endpoint still needs to be reachable only through a route you control, such as the same private Wi-Fi network or your Tailscale tailnet. If the pair server is exposed publicly, or if the computer itself is compromised, an opaque code is not a complete defense.

A practical verification sequence

You can test the pattern without printing the real credential:

  1. Start the computer gateway and pairing server.
  2. Confirm the generated setup link contains pairCode and pairServer but no key or apiKey field.
  3. Exchange the code once and verify the server returns HTTP 200.
  4. Repeat the exact exchange and verify it is rejected.
  5. Mint another code, wait beyond its configured TTL, and verify that exchange is rejected.
  6. On the phone, confirm an authenticated gateway health check succeeds after pairing.
  7. Turn off the active network route and confirm the app reports the connection loss instead of claiming it is still connected.

Hermes includes deterministic tests for self-peer filtering, single-use rejection, unknown-code rejection, and expiration. Those tests are useful because a green connection indicator alone cannot prove that a credential stayed out of the QR payload or that replay protection works.

Where this pattern helps

The same design applies to local development tools, home-lab dashboards, self-hosted assistants, and device-control apps. Keep discovery and authorization separate: discovering an IP address does not authorize it, and seeing a device on Tailscale does not prove that it runs the service you need.

Pair with an opaque, expiring capability; exchange it once over a private route; validate the service and credential; then store the resulting secret in the platform credential store. It is a small protocol, but it removes a surprisingly common credential leak from the setup flow.

If you want to use this workflow rather than build the mobile client yourself, Hermes Mobile is available as a paid Android app.

Igor Ganapolsky

Igor Ganapolsky

Founder

Builder of AI agent governance and safety systems - such as ThumbGate.ai and ThumbGate.app

Comments (0)

Login to post a comment.

Related Posts

Approve risky agent tools before they run

Coding agents should not get a free pass on destructive tools. A product-true take on approval gates before risky tools run โ€” and a web control plane to do it from anywhere.

Read article

Build React Native Apps: Offline-First Approach Using GraphQL and Caching

Building apps that work offline isnโ€™t just a nice-to-have anymore, itโ€™s essential. Network issues are real, especially in places with unstable connections. Whet...

Read article

Why same-Wi-Fi AI agent discovery fails on larger home networks

Your phone and Mac can show the same Wi-Fi icon and still fail automatic discovery. I ran into that exact problem while testing Hermes Mobile, the Android contr...

Read article

I got tired of paying $50/mo for AI video tools so I built and open-sourced my own

Honestly? I just got frustrated. I was paying for like 3 different AI video subscriptions, burning through credits, and still not getting what I wanted. So I did what any reasonable developer would do - I spent way more time building my own thing than I would've ever spent on subscriptions.

Read article

You Probably Don't Need Multi-Agents

I work across six or seven repositories on one project โ€” a big hybrid thing, part microfrontend, part backend, several apps that all talk to each other. When I ...

Read article