Skip to content

Setting Up Remotes

There are two ways to connect Portuni to Google Drive:

  • Desktop, one click (recommended for most people). In Portuni.app, open Settings → Synchronizace and click Propojit Google Drive. This runs a normal Google sign-in, you pick a target (a folder on your own My Drive, or a Shared Drive), and you’re done — no Cloud Console, no JSON keys. Files sync under your Google identity. See Working in the App.
  • Service Account (headless servers, or advanced multi-remote routing). The rest of this guide. Use it when there is no desktop app to click through the sign-in — a central server, CI, or a deployment that fans several organizations out to different Shared Drives. It’s more setup (one-time admin in the Google Cloud Console) but it needs no interactive login.

This guide walks the Service-Account path from “I have a fresh Google account” to “Portuni is pushing files to a Shared Drive on my behalf.” Most of the work is one-time admin in the Google Cloud Console; the Portuni-side configuration is two MCP calls. If you’d rather be walked through it interactively, run the setup-drive-remote MCP prompt (in Claude Code, /mcp__portuni__setup-drive-remote) and an agent will guide you step by step and make the calls for you.

  • A Service Account (SA) with a JSON key, stored on each device that needs to sync.
  • One or more Google Shared Drives that the SA is a member of.
  • A registered Portuni remote pointing at each Shared Drive.
  • Routing rules that send each node type to the right remote.

Both auth paths exist. Which fits depends on whether there’s a person at a desktop to sign in:

Service Account Desktop OAuth
Setup One-time admin in Cloud Console One click in Settings → Synchronizace
Runs without a person present Yes (servers, CI, central mode) No — needs an interactive sign-in
Identity Fixed SA email, all actions attributed to SA Per-user, real audit on Drive’s side
Target Shared Drives the SA is a member of Your My Drive folder, or any Shared Drive you can access
Multi-remote routing (per-org Shared Drives) Full control via routing rules One target per connection
Compromise blast radius Drives the SA is in The user’s whole Drive

Reach for the Service Account when there’s no desktop to click through consent (a central server, CI), or when you’re fanning several organizations out to different Shared Drives with routing rules. Everyone else should use the desktop one-click flow — it’s simpler and attributes changes to the real user on Drive’s side.

Domain-wide delegation (a Workspace user acting on behalf of others) is still not implemented; see Workspace deployments with restricted Shared Drives below.

One-time admin setup (per Portuni deployment)

Section titled “One-time admin setup (per Portuni deployment)”
  1. Go to https://console.cloud.google.com.
  2. Create a new project. Pick any name – this is internal scaffolding. (“Portuni” is fine.)
  3. With the project selected, enable the Google Drive API:
    • Search for “Google Drive API” in the API library.
    • Click “Enable.”
  1. Cloud Console -> IAM & Admin -> Service Accounts.
  2. “Create Service Account.”
  3. Name it something memorable like portuni-sync. The full email becomes portuni-sync@<project>.iam.gserviceaccount.com – note this address; you’ll need it next.
  4. Skip the optional “grant access” steps. Portuni only needs the SA’s identity, not project-level permissions.
  1. Click into the new Service Account -> “Keys” tab -> “Add Key” -> “Create new key” -> JSON.
  2. Download the JSON file.
  3. Keep it somewhere safe but accessible – you’ll paste its contents into portuni_setup_remote shortly. Do NOT commit it to a git repo; treat it like a password.

For every Shared Drive Portuni will manage:

  1. Open the Shared Drive in Google Drive.
  2. “Manage members.”
  3. Add the SA’s email (portuni-sync@<project>.iam.gserviceaccount.com).
  4. Role: Content Manager (typically). Higher roles work; “Viewer” or “Commenter” don’t.

You’ll need the Shared Drive’s ID for each one. To get it:

  • Open the Shared Drive in your browser.
  • The URL looks like https://drive.google.com/drive/folders/0AXyz... – the long ID after /folders/ is the Shared Drive ID.

Optional: if you want Portuni to use a specific subfolder inside the Shared Drive as its root (instead of the drive’s root), grab that folder’s ID the same way. This is the root_folder_id parameter below.

Once admin work is done, each Shared Drive becomes a Portuni remote:

portuni_setup_remote {
"name": "drive-workflow",
"type": "gdrive",
"config": {
"shared_drive_id": "0AXyz...",
"root_folder_id": "1Abc..." // optional
},
"service_account_json": "<paste the entire JSON file contents here>"
}

What happens:

  • The public configuration (name, type, shared_drive_id, root_folder_id) is written to the remotes table in Turso.
  • The SA JSON is stored via the configured TokenStore (file / keychain / varlock) – never in Turso.

Repeat for each Shared Drive you’re registering.

How the SA JSON is stored on each device is controlled by PORTUNI_TOKEN_STORE:

Store Where When to pick
file (default) $PORTUNI_WORKSPACE_ROOT/.portuni/tokens.json, mode 0600 Single-user laptop. Easy backup.
keychain OS keychain (macOS Keychain, libsecret, Windows Credential Manager) Hardened single-user device.
varlock Env vars populated by a password manager Team machines, CI, or 1Password / Bitwarden as source of truth

For the file store you don’t need to do anything – Portuni writes the JSON the first time portuni_setup_remote runs.

For keychain: set PORTUNI_TOKEN_STORE=keychain and re-run portuni_setup_remote to write through the keychain instead of a file.

For varlock: set PORTUNI_TOKEN_STORE=varlock plus PORTUNI_VARLOCK_WRITE_PROGRAM and PORTUNI_VARLOCK_WRITE_ARGS to teach Portuni how to write into your password manager. A typical 1Password setup:

op run -- env \
PORTUNI_TOKEN_STORE=varlock \
PORTUNI_VARLOCK_WRITE_PROGRAM=op \
PORTUNI_VARLOCK_WRITE_ARGS='item edit "portuni/{name}" {field}={value}' \
npm start

A registered remote does nothing until a routing rule sends nodes to it. portuni_set_routing_policy takes a single rules: array and replaces the entire routing table — every existing rule that isn’t in the new list is deleted. So write out the full intended policy in one call:

portuni_set_routing_policy {
rules: [
{ priority: 10, node_type: "process", org_slug: "workflow", remote_name: "drive-workflow" },
{ priority: 100, node_type: "process", org_slug: null, remote_name: "shared-processes" },
{ priority: 100, node_type: "project", org_slug: null, remote_name: "projects-hub" }
]
}

null on node_type or org_slug is a wildcard (“any”). Lower priority wins – use 10 for org-specific overrides and 100 for catch-all defaults. Tie-break is by insertion order within the rule list.

Verify with portuni_list_remotes – each remote shows the routing rules pointing at it.

Workflow’s setup ends up looking roughly like this:

Remote Holds
projects-hub All projects across all orgs
drive-workflow Workflow’s own processes, areas, principles
drive-tempo Tempo’s processes, areas, principles
drive-nautie Nautie’s processes, areas, principles

Routing rules:

project / * -> projects-hub / 100
process / workflow -> drive-workflow / 10
process / tempo -> drive-tempo / 10
process / nautie -> drive-nautie / 10
area / workflow -> drive-workflow / 10
area / tempo -> drive-tempo / 10
area / nautie -> drive-nautie / 10
principle / * -> drive-workflow / 100 (or wherever)

After this, portuni_store and portuni_pull “just work” – Portuni picks the right Shared Drive based on the node and pushes / pulls there.

Each device that runs Portuni needs the SA JSON via its own TokenStore. The recommended pattern is “one SA shared across all your devices” – distribute the same JSON to each machine. Per-device SAs add admin overhead without meaningfully changing the security picture in Phase 1.

Workspace deployments with restricted Shared Drives

Section titled “Workspace deployments with restricted Shared Drives”

Some Google Workspace setups configure Shared Drives so external members – which the SA technically is – can’t be added. In that case the SA flow won’t work. Three workarounds:

  1. Use the desktop OAuth flow instead (Settings → Synchronizace). It signs in as a real user, so it reaches any Shared Drive that user can access, plus their own My Drive — no external-member restriction applies. This is the simplest fix when there’s a desktop to click through.
  2. Remove the external-member restriction on the target drives (admin setting in Google Admin Console).
  3. Use a dedicated Workspace user (e.g. portuni-sync@yourdomain.com) and connect it via desktop OAuth. Portuni does not yet implement domain-wide delegation (one Workspace user acting headlessly on behalf of others), so this still needs an interactive sign-in.
  • Delete on Drive is soft. portuni_delete_file defaults to mode: "complete" (removes the local file, the DB row, and the remote copy). On Drive remotes, the remote-side delete moves the file to Drive Trash rather than truly destroying it (30-day recovery window). The unregister_only mode drops just the DB row without touching disk or remote — useful when the file is already gone from both.
  • Rename of a node does NOT rename the Drive folder. Folder paths are anchored on the immutable sync_key. Use portuni_rename_folder for an explicit, atomic rename of the visible folder name.
  • Native files (Docs / Sheets / Slides) are tracked but not round-trip synced. They have URL + modified-at metadata. Use portuni_snapshot to export a PDF / markdown / docx copy as a regular tracked file.
  • Drive versioning is the safety net. 30-day version history under Portuni’s audit log gives a second line of defense for anything overwritten.