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.
What you’ll end up with
Section titled “What you’ll end up with”- 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.
Service Account vs OAuth
Section titled “Service Account vs OAuth”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. Create a Google Cloud project
Section titled “1. Create a Google Cloud project”- Go to https://console.cloud.google.com.
- Create a new project. Pick any name – this is internal scaffolding. (“Portuni” is fine.)
- With the project selected, enable the Google Drive API:
- Search for “Google Drive API” in the API library.
- Click “Enable.”
2. Create the Service Account
Section titled “2. Create the Service Account”- Cloud Console -> IAM & Admin -> Service Accounts.
- “Create Service Account.”
- Name it something memorable like
portuni-sync. The full email becomesportuni-sync@<project>.iam.gserviceaccount.com– note this address; you’ll need it next. - Skip the optional “grant access” steps. Portuni only needs the SA’s identity, not project-level permissions.
3. Generate a JSON key
Section titled “3. Generate a JSON key”- Click into the new Service Account -> “Keys” tab -> “Add Key” -> “Create new key” -> JSON.
- Download the JSON file.
- Keep it somewhere safe but accessible – you’ll paste its contents into
portuni_setup_remoteshortly. Do NOT commit it to a git repo; treat it like a password.
4. Add the SA to each Shared Drive
Section titled “4. Add the SA to each Shared Drive”For every Shared Drive Portuni will manage:
- Open the Shared Drive in Google Drive.
- “Manage members.”
- Add the SA’s email (
portuni-sync@<project>.iam.gserviceaccount.com). - 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.
Per-remote setup
Section titled “Per-remote setup”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 theremotestable 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.
TokenStore tiers
Section titled “TokenStore tiers”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 startRouting rules
Section titled “Routing rules”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.
A working example
Section titled “A working example”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 / 100process / workflow -> drive-workflow / 10process / tempo -> drive-tempo / 10process / nautie -> drive-nautie / 10area / workflow -> drive-workflow / 10area / tempo -> drive-tempo / 10area / nautie -> drive-nautie / 10principle / * -> 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.
Per-device distribution
Section titled “Per-device distribution”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:
- 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.
- Remove the external-member restriction on the target drives (admin setting in Google Admin Console).
- 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.
What Drive users should expect
Section titled “What Drive users should expect”- Delete on Drive is soft.
portuni_delete_filedefaults tomode: "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). Theunregister_onlymode 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. Useportuni_rename_folderfor 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_snapshotto 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.
See also
Section titled “See also”- Files & Mirrors – the basic file flow
- Sync Tools – the rest of the tool surface
- Local Mirrors – how mirrors and remotes fit together