agentcookie

module
v0.14.0-beta.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2026 License: MIT

README

agentcookie

Your agent runs on a Mac that isn't your daily driver. It needs to act as you on every site you're already logged into. agentcookie keeps your second Mac's sessions in sync with your first Mac's, continuously, encrypted over your Tailscale tailnet, with zero per-site auth ceremony.

OpenClaw, Hermes, or any other agent runtime you point at the second Mac wakes up authenticated.

What it looks like

You browse normally on your first Mac. agentcookie watches Chrome's Cookies file and ships the diff to your second Mac the moment anything changes. On the second Mac, an agent does its work:

$ ssh second-mac 'instacart-pp-cli carts'
  Costco                 slug=costco   cart=757109404 items=5
  Safeway                slug=safeway  cart=3190      items=1

$ ssh second-mac 'ebay-pp-cli auctions "watch" --has-bids --ending-within 1h'
12 active auctions:
  $352   23 bids   1m   Apple Watch Ultra 2 49mm Titanium ...
  $115   26 bids   1m   Gucci 5500M Steel Quartz ...
  ...

$ ssh second-mac 'table-reservation-goat-pp-cli goat "omakase" --location seattle'
{ "results": [ { "name": "Omakase Dinner Series", "network": "tock", ... } ] }

No auth login. No Keychain prompt. No paste-the-cookie ritual. The agent's sessions were already there when the request hit.

The same is true for browser-driving agents. Point them at the agentcookie-managed Chrome profile on the second Mac and your agent sees the same logged-in state you have on your laptop. Or skip Chrome entirely: read the plaintext cookies sidecar at ~/.agentcookie/cookies-plain.db from any agent that knows cookies.

What this fixes

Logging in twice. Once on your laptop, once again on the Mac your agent lives on. Per site. Forever.

Tools that ship cookies between machines today assume a human is going to click "merge" or unlock a vault or open the destination browser. They were built for switching accounts between two laptops the same person uses. They weren't built for "the agent on the headless Mac mini needs my session in 30 seconds and there's nobody home."

agentcookie is the second pattern. One-way, continuous, unattended replication from the machine you live in to the machine your agents act from. Pairing-derived per-peer keys, allowlist + blocklist on both sides, AES-256-GCM over the Tailscale tailnet's WireGuard channel. The hard parts (macOS Keychain protections, Chrome's App-Bound Encryption, per-CLI auth conventions) are handled.

How it works

laptop                                              second Mac
======                                              ==========

Chrome cookies change
  |
  v
agentcookie source --watch  (fsnotify on Chrome's Cookies SQLite)
  |
  | decrypt with Keychain key, filter against blocklist
  v
+----- HTTPS over Tailscale (AES-256-GCM, replay-defended) -----+
                                                                |
                                                                v
                                              agentcookie sink (LaunchAgent)
                                                |
                                                | one of three delivery surfaces:
                                                v
                                              1. Chrome's Cookies SQLite (re-encrypted for sink Keychain)
                                              2. Plaintext sidecar at ~/.agentcookie/cookies-plain.db
                                                 (env var: AGENTCOOKIE_PLAIN_COOKIES)
                                              3. Per-CLI adapter fan-out:
                                                   instacart  -> session.json
                                                   airbnb     -> config.toml + cookies.json
                                                   ebay       -> config.toml + cookies.json
                                                   pagliacci  -> config.toml + cookies.json
                                                   table-reservation-goat -> session.json

Three surfaces because different agents read cookies differently. A browser-driving agent uses surface 1 (or its own profile pointed at the sidecar). A CLI with a built-in adapter uses surface 3. A raw cookies consumer uses surface 2. The sink runs all three after every sync, so the agent picks what fits.

New adapters are roughly 50 lines of Go and a Register() call; the runbook walks through it.

Install

Prereqs: Tailscale running on both Macs, Chrome installed, Go 1.22+ (or a pre-built release).

# On both machines:
go install github.com/mvanhorn/agentcookie/cmd/agentcookie@latest

# On the first Mac (source):
agentcookie wizard install --as source --peer <second-mac-hostname>

# It prints a pairing code. On the second Mac (sink), paste:
agentcookie wizard install --as sink --peer <first-mac-hostname> \
  --code <pairing-code> --pair-url http://<first-mac-hostname>:9998/pair

The sink wizard installs a LaunchAgent, configures Chrome Safe Storage access (or skips it cleanly on a headless install where there's no GUI session to click prompts), and registers the five built-in adapters that fire after every sync. After install, all sync work runs unattended.

See docs/quickstart.md for the long-form walkthrough and docs/quickstart-beta.md for the headless flow if you're installing the second Mac over SSH.

Verify it's working

agentcookie doctor                           # both sides' health
agentcookie wizard verify-adapters           # per-adapter results from the last sync
agentcookie wizard verify-adapters --json    # same, structured for SSH agents

Healthy output:

ADAPTER                          STATUS  PUSHED  DETAIL
-------                          ------  ------  ------
instacart-pp-cli                 ok      33
airbnb-pp-cli                    ok      25
ebay-pp-cli                      ok      51
pagliacci-pp-cli                 skip            no matching cookies
table-reservation-goat-pp-cli    ok      36

last run: 4s ago

Status

macOS only on both ends today. The source side reads Chrome on macOS via the Keychain-backed decrypt path; the sink relies on macOS LaunchAgent and Keychain conventions. Linux and Windows are on the roadmap.

Working:

  • Continuous laptop to second-Mac sync via fsnotify on Chrome's Cookies file, debounced, allowlist + blocklist filtered, AES-256-GCM over Tailscale.
  • Three delivery surfaces on the sink (Chrome SQLite, plaintext sidecar, per-CLI adapter session files).
  • Five built-in PP CLI adapters: instacart, airbnb, ebay, pagliacci, table-reservation-goat (OpenTable + Tock).
  • Tailnet-only listeners on both ends; pair endpoint rate-limited with a 64-bit code.
  • Persistent replay defense; per-peer pairing-derived keys.
  • Apple Developer ID signed binaries; per-binary -T Keychain ACL on Chrome Safe Storage.
  • Headless second-Mac install over SSH with no GUI clicks required.
  • agentcookie doctor reports binary signature, Tailscale, config, keystore, listener bind, sink/source state, sealing posture, adapter coverage, CDP injector health.
  • 330+ unit tests across 23 packages.

Not yet:

  • More built-in adapters beyond the five above. Anything else uses the plaintext sidecar via AGENTCOOKIE_PLAIN_COOKIES.
  • agentcookie pair --rotate for live key rotation. Today: re-run wizard install on both sides.
  • One first-Mac, many second-Macs fan-out.
  • Linux and Windows on either side.
  • At-rest sealing of the sidecar + adapter session files is wired in but off by default; turns on via wizard set-keychain-access --enable-sealing once consumer-side support lands.

Documentation

Doc Use
Quickstart install on a laptop + second-Mac pair
Architecture module layout, sync lifecycle, security boundaries
Protocol v1 wire format spec for future client implementations
Threat model what agentcookie does and does not protect against
FAQ common questions
Headless quickstart SSH-only install on a headless second Mac
v0.10 keychain runbook sink's Keychain ACL setup
v0.11 adapter runbook adapter mechanism + how to write your own
v0.12 security runbook sealed master key, tailnet-only listeners, rate-limited pairing
v0.12 codesign runbook Developer ID signing, notarization, CI secrets, renewal
Install skill Claude Code skill so an agent can drive the install

License

MIT.

Directories

Path Synopsis
cmd
agentcookie command
Command agentcookie is the unified CLI for the agentcookie product.
Command agentcookie is the unified CLI for the agentcookie product.
spike-sink command
Command spike-sink runs an HTTP listener that accepts an AES-GCM-encrypted payload of cookies, decrypts it with the shared spike secret, and upserts each cookie into this machine's Chrome cookies SQLite.
Command spike-sink runs an HTTP listener that accepts an AES-GCM-encrypted payload of cookies, decrypts it with the shared spike secret, and upserts each cookie into this machine's Chrome cookies SQLite.
spike-source command
Command spike-source reads cookies for one host from the local Chrome SQLite/Keychain stack and POSTs them to a spike-sink running on another machine.
Command spike-source reads cookies for one host from the local Chrome SQLite/Keychain stack and POSTs them to a spike-sink running on another machine.
Package cookiesource is the importable PP-CLI integration point for the agentcookie bridge.
Package cookiesource is the importable PP-CLI integration point for the agentcookie bridge.
internal
cdp
Package cdp implements Chrome DevTools Protocol cookie injection against the agentcookie-owned Chrome profile.
Package cdp implements Chrome DevTools Protocol cookie injection against the agentcookie-owned Chrome profile.
chrome
Package chrome reads and writes Chrome cookies on macOS, handling the per-machine Safe Storage encryption via the macOS Keychain.
Package chrome reads and writes Chrome cookies on macOS, handling the per-machine Safe Storage encryption via the macOS Keychain.
chromectl
Package chromectl is the macOS Chrome lifecycle helper used by every agentcookie writer that needs Chrome briefly quit while it touches Chrome's on-disk state (cookies SQLite, Local Storage LevelDB, IndexedDB LevelDB).
Package chromectl is the macOS Chrome lifecycle helper used by every agentcookie writer that needs Chrome briefly quit while it touches Chrome's on-disk state (cookies SQLite, Local Storage LevelDB, IndexedDB LevelDB).
chromedirsync
Package chromedirsync packs and unpacks Chrome on-disk profile directories as portable tarballs for cross-machine sync.
Package chromedirsync packs and unpacks Chrome on-disk profile directories as portable tarballs for cross-machine sync.
chromepaths
Package chromepaths centralizes the on-disk Chrome profile paths agentcookie reads and writes.
Package chromepaths centralizes the on-disk Chrome profile paths agentcookie reads and writes.
cli
Package cli wires the cobra subcommand tree for the unified `agentcookie` binary.
Package cli wires the cobra subcommand tree for the unified `agentcookie` binary.
cli/httpserver
Package httpserver consolidates the timeout and body-size policy that agentcookie's HTTP listeners and clients all share.
Package httpserver consolidates the timeout and body-size policy that agentcookie's HTTP listeners and clients all share.
config
Package config loads agentcookie's on-disk configuration: source.yaml, sink.yaml, and allowlist.yaml.
Package config loads agentcookie's on-disk configuration: source.yaml, sink.yaml, and allowlist.yaml.
keystore
Package keystore manages per-peer symmetric keys derived during pairing.
Package keystore manages per-peer symmetric keys derived during pairing.
launchd
Package launchd generates and installs LaunchAgent plists for the agentcookie source and sink daemons.
Package launchd generates and installs LaunchAgent plists for the agentcookie source and sink daemons.
pairing
Package pairing implements the source-sink pairing handshake.
Package pairing implements the source-sink pairing handshake.
protocol
Package protocol defines the wire format the source uses to send sync payloads to the sink.
Package protocol defines the wire format the source uses to send sync payloads to the sink.
secretsbus
Package secretsbus's v2 adoption manifest.
Package secretsbus's v2 adoption manifest.
sinkpush
Package sinkpush pushes decrypted cookies from the agentcookie sink into each PP CLI's local session cache, bypassing the macOS Keychain on the read side.
Package sinkpush pushes decrypted cookies from the agentcookie sink into each PP CLI's local session cache, bypassing the macOS Keychain on the read side.
state
Package state is the shared state-file format that the source watcher and the sink daemon both write to ~/.agentcookie/.
Package state is the shared state-file format that the source watcher and the sink daemon both write to ~/.agentcookie/.
transport
Package transport is the spike's shared-secret AES-GCM wrapper for the HTTP-over-tailnet sync channel.
Package transport is the spike's shared-secret AES-GCM wrapper for the HTTP-over-tailnet sync channel.
tsclient
Package tsclient probes Tailscale state on the local machine.
Package tsclient probes Tailscale state on the local machine.
watcher
Package watcher runs the source-side fsnotify loop.
Package watcher runs the source-side fsnotify loop.
pkg
agentcookieadoption
Package agentcookieadoption is the author-side helper library for the agentcookie secrets-bus v2 adoption standard.
Package agentcookieadoption is the author-side helper library for the agentcookie secrets-bus v2 adoption standard.
agentcookiesecret
Package agentcookiesecret is the canonical Go reader for the agentcookie secrets bus.
Package agentcookiesecret is the canonical Go reader for the agentcookie secrets bus.
sidecar
Package sidecar exposes the public reader API for agentcookie's cookie sidecar SQLite.
Package sidecar exposes the public reader API for agentcookie's cookie sidecar SQLite.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL