The Flow Engine

The Flow Engine is the Swift library which the macOS app and the MCP server both use to move credentials between devices.

01. Execution Flows

The Flow Engine moves credentials as flows — directional motion between two devices, from a source into RAM, from RAM into a destination.

A flow is not an import and not an export. An import is also an export from somewhere else; those words pick one endpoint and pretend the other isn't part of the operation. Flow names the motion, not an endpoint, and names it honestly. It also carries the thing that makes the Flow Engine different from every other password-migration tool: no file in between. No CSV. No intermediate JSON on disk. No plaintext anywhere along the path.

The library has one entry point: FlowEngine.run(). Pass a source device to pull into SecuredBox. Pass a destination to push what is already in SecuredBox. Pass both to pull, preflight, and push in one call. A full pull-push flow holds a single-writer lock — a second pull-push flow initiated while the first is running is rejected with a failed event. Pull-only flows run concurrently.

Flows are fire-and-forget. The engine emits four event types and lets the caller handle them. The app renders them in the status bar; the MCP server aggregates them into one JSON response. Whatever the Flow Engine is doing right now, whoever called it can see.

started stepComplete complete failed

02. Instances Devices

A device is a user-configured instance of a connector. One Chrome profile is one device. One KeePassXC database is one device. One 1Password account is one device. Each has an ID of the form {connector}-{slug}chrome-default, keepasscli-passwords, onepassword-primary — and that is the identifier the app and the MCP server pass back to FlowEngine.run().

On launch, a discovery service scans the machine for what's present — Chrome profile folders, recently-opened .kdbx files, every installed Chromium variant — and reconciles the device table against what it finds. Runtime status (is the database openable, is the master password in the keychain, is the op CLI installed) is computed on demand and never persisted. The engine always asks fresh.

Seven connectors are included. The per-connector engineering — the AES-256-GCM Chrome decryption, Apple's CXP handoff, the keepassxc-cli write path — lives on the Protools page.

03. Staging SecuredBox

SecuredBox is the RAM-only hub every flow passes through. Sources append BoxItem records to it. Destinations read them out. It is never written to disk, never synced, never exposed over a network. It is cleared on app quit, at the end of a full flow, or when a client calls clear.

Every item is self-aware. A BoxItem knows what fields it actually carries — a Chrome record typically holds only url, username, and password; a KeePassXC record might also carry an OTP seed, a passkey blob, and notes. Every configured device publishes the fields it accepts. The preflight is what happens when the two meet: before a push runs, the Flow Engine computes the field-by-field gap between the working set and the destination's schema and returns a report with the complete event — which fields transfer, which get dropped per destination. A record with only a password (a PIN), only a username (a passkey handle), or only a note is still a credential; destinations handle whatever they're given rather than filter items out.

Every item knows what it has. Every device knows what it wants. Nothing writes until the gap is computed.

The three states

The Flow Engine holds three kinds of state, each in a different place, each with a different lifetime.

SecuredBox

The cargo. Credentials in flight. RAM only. Cleared on quit, on clear, or at the end of a full flow.

Keychain

The operational parameters connectors need to run: Chrome Safe Storage keys, KeePassXC master passwords, 1Password service tokens. Stored in the macOS Keychain, ACL-scoped to the signed Goodboy binary. Other processes cannot read them.

AppDB

The device catalog, settings, and flow logs. A local SQLite file at ~/Library/Application Support/Goodboy/goodboy.db. No credentials, no keychain values — only configs and metadata.

Credentials never leave the local machine. The Flow Engine opens no sockets, makes no analytics calls, writes no diagnostic files. The only credential file it ever writes is the Bitwarden JSON export, and only when the user has explicitly picked it as a destination.

04. Fields What the engine moves

Passwords. One-time password seeds. WebAuthn passkeys. Notes. Folders. Custom fields.

Not every device accepts every type. Chrome holds passwords only. KeePassXC holds almost everything. iCloud sits somewhere in between. The Flow Engine's job is to know the gap before the write begins, not to pretend the gap isn't there. The read/write table and the full field-preservation matrix live on the Protools page.

Open source.
MIT licensed.

The Flow Engine and the MCP server live in the same Swift package. Runtime dependencies: GRDB.swift for SQLite and the MCP Swift SDK for the JSON-RPC transport. Crypto primitives (AES-256-GCM, PBKDF2, SHA-256) come from Apple's CryptoKit and CommonCrypto. No other runtime dependencies. Requires macOS 26 (Tahoe) and Swift 6.2.

View on GitHub