Skip to content

Team Sync

Team Sync connects developers, machines, and cloud AI agents into a single collaborative network. When you connect to a team, you get:

  • Observation sharing — Memories, decisions, gotchas, and discoveries sync across all connected nodes
  • Federated search & tool calls — Query any node’s local index from any other node
  • Cloud agent access — Cloud-hosted AI agents (Claude.ai, ChatGPT, etc.) call your local MCP tools through a secure HTTP endpoint

All of this runs through a Cloudflare Worker relay that OAK deploys and manages for you. Your codebase never leaves your machine — only MCP tool calls, their results, and observation payloads travel through the relay.

Your local daemon initiates the connection outward — no inbound ports, no firewall rules, no dynamic DNS. The Cloudflare Worker relays messages between all connected sides.

ComponentRoleRuns On
Cloudflare WorkerAccepts MCP requests and relays observationsCloudflare’s edge network (your account)
Durable ObjectManages WebSocket state, message routing, and observation bufferingCloudflare (co-located with Worker)
WebSocket ClientMaintains persistent outbound connection to WorkerYour local machine (inside OAK daemon)
DataSyncedNotes
Memory observationsYesGotchas, decisions, discoveries, bug fixes, trade-offs
SessionsNoSessions are local to each machine
Prompt batchesNoPrompt data stays local
ActivitiesNoTool execution logs stay local
Code indexNoEach machine indexes its own codebase

When connected to a team, MCP tool queries can be federated across all connected nodes:

  • Search fan-out — Set include_network=true on oak_search, oak_context, oak_sessions, oak_memories, or oak_stats to fan the query out to all connected nodes. Each node executes against its local index and returns results, which are merged and ranked. This means your agents can find code patterns and memories from across the entire team — without any node needing a copy of another’s full index.
  • Targeted tool calls — Set node_id on oak_resolve_memory, oak_activity, or oak_archive_memories to route the call to a specific remote node. Use oak_nodes to discover available nodes and their capabilities.
  • Cloud agent access — Cloud agents connected via MCP Streamable HTTP have the same federation capabilities as local agents.

Team sync requires a free Cloudflare account and Node.js v18+.

  1. Go to cloudflare.com/sign-up
  2. Enter your email and create a password
  3. Verify your email address

No credit card is required. The Workers free tier includes everything the relay needs.

Wrangler is Cloudflare’s CLI for managing Workers:

Terminal window
# Option 1: Use via npx (recommended — no global install needed)
npx wrangler --version
# Option 2: Global install
npm install -g wrangler
wrangler --version
Terminal window
npx wrangler login

This opens your browser for an OAuth flow. Verify authentication:

Terminal window
npx wrangler whoami
ResourceFree LimitTypical Usage
Worker requests100,000/day~500–2,000/day
Worker CPU time10ms/request~2–5ms/request
Durable Object requests100,000/day~500–2,000/day
Durable Object storage1 GB< 1 KB
WebSocket messagesUnlimited~1,000–5,000/day
Egress bandwidthFreeAll

For a typical developer workflow, free tier usage stays well under 5% of the daily limits.

If you’re the first team member setting up sync:

  1. Open the Teams page in the dashboard
  2. Click Deploy — this runs the turnkey deployment pipeline:
    • Scaffolds a Cloudflare Worker project in .oak/ci/cloud-relay/
    • Installs dependencies and verifies Cloudflare authentication
    • Deploys the Worker via wrangler
    • Connects the daemon over WebSocket
  3. Share the Relay URL and API Key with your team

Or from the CLI:

Terminal window
oak team cloud-init # Deploy and connect

The pipeline skips any phase that’s already complete. First run takes ~30–60 seconds; reconnecting takes ~2–3 seconds.

If a teammate has already deployed a relay:

  1. Open the Teams page in the dashboard
  2. Enter the Relay URL and API Key your teammate shared
  3. Click Connect

Or configure manually in .oak/config.yaml:

team:
relay_worker_url: https://oak-relay-myproject.you.workers.dev
api_key: <shared-api-key>
auto_sync: true
sync_interval_seconds: 3

Once connected, observations begin syncing immediately. On first connect, the relay drains any pending observations from other nodes so you receive the team’s full history.

The Teams page shows real-time connection status:

  • Connection Status — Green when connected to the relay, with Cloudflare account name
  • Online Nodes — List of connected team members with machine IDs
  • Sync Stats — Queue depth, last sync time, total events sent
  • Relay Buffer — Pending observations waiting to be drained to your node
Terminal window
oak team status # Show connection and sync status
oak team members list # List online team members

Control observation sync behavior from the Teams page or via configuration:

SettingDefaultRangeDescription
Auto syncOffStart sync automatically on daemon startup
Sync interval3s1–60sHow often the outbox flushes observations to the relay
# In .oak/config.yaml
team:
auto_sync: true
sync_interval_seconds: 3

The outbox worker uses exponential backoff on failures (up to 300 seconds) and resets to the base interval on success.

Control what data is shared via the data collection policy in Governance settings:

SettingDefaultDescription
sync_observationstrueWhether observations are written to the team outbox
federated_toolstrueWhether this node’s MCP tools are advertised to the relay for remote calls

When sync_observations is set to false, observations are stored locally only and never sent to the relay. This is useful for sensitive projects or temporary opt-outs.

When federated_tools is set to false, other team nodes and cloud agents cannot call this node’s MCP tools remotely — even if the relay is connected. Local tool access is unaffected.

# In .oak/config.yaml
team:
governance:
data_collection:
sync_observations: true
federated_tools: true

You can also toggle both settings from the dashboard: Teams > Policy.

When connected to a team, cloud AI agents can connect to the relay’s MCP endpoint:

  • MCP Endpoint: https://<your-worker>.workers.dev/mcp
  • Agent Token: Displayed on the Teams page (masked with reveal/copy)

See MCP Configuration for per-agent setup instructions (Claude.ai, ChatGPT, mcp.json config files) and agent token details.

Click Leave Team on the Teams page, or disconnect via CLI:

Terminal window
oak team cloud-disconnect

This disconnects the relay and clears team configuration. The Worker is not deleted — you can rejoin later by re-entering the URL and key.

The deployment pipeline creates a Cloudflare Worker project at .oak/ci/cloud-relay/:

.oak/ci/cloud-relay/
src/
index.ts # Worker entry point — HTTP routing and CORS
auth.ts # Token validation logic
mcp-handler.ts # MCP Streamable HTTP request handling
relay-object.ts # Durable Object — WebSocket relay and state
types.ts # Shared TypeScript interfaces
wrangler.toml # Cloudflare config with tokens and bindings
package.json # Dependencies (minimal)
tsconfig.json # TypeScript config
.gitignore # Excludes wrangler.toml, node_modules/, .wrangler/

The scaffold’s .gitignore excludes wrangler.toml (contains secrets), node_modules/, and .wrangler/. Worker source code can be committed to version control.

Each project gets a unique Worker name derived from the project directory:

oak-relay-<sanitized-project-name>

For example, a project in ~/projects/my-app gets the Worker name oak-relay-my-app.

When you upgrade OAK, the Worker template may include protocol changes. To update:

Terminal window
oak team cloud-init --force

This re-scaffolds with the latest template, re-installs dependencies, and re-deploys. Existing tokens are preserved.

Terminal window
cd .oak/ci/cloud-relay
npx wrangler tail
Terminal window
cd .oak/ci/cloud-relay
npx wrangler delete # Remove from Cloudflare

To clean up the local scaffold: rm -rf .oak/ci/cloud-relay

The relay uses a two-token model to secure both sides:

TokenPurposeUsed By
relay_tokenAuthenticates the daemon to the WorkerLocal OAK daemon (WebSocket Sec-WebSocket-Protocol header)
agent_tokenAuthenticates cloud AI agents to the WorkerClaude.ai, ChatGPT, etc. (HTTP Authorization: Bearer header)

Both tokens are generated automatically during deployment using secrets.token_urlsafe(32) (256 bits of entropy each).

LocationContains
.oak/config.yamlBoth tokens
.oak/ci/cloud-relay/wrangler.tomlBoth tokens as env vars (excluded from git)
Cloudflare Workers secretsBoth tokens (encrypted at rest)

To rotate tokens (e.g., if compromised or to revoke all cloud agent access):

Terminal window
rm -rf .oak/ci/cloud-relay
oak team cloud-init

This generates fresh tokens and re-deploys. Update any cloud agents with the new agent token.

  • No inbound ports — The daemon initiates WebSocket outward. No incoming connections needed.
  • Transport encryption — All connections use TLS (HTTPS for MCP, WSS for WebSocket).
  • Blast radius — Each project has its own Worker with its own token pair.
  • CORS support — The Worker includes CORS headers for browser-based MCP clients.

Each machine produces its own backup file named {github_user}_{hash}.sql, stored in oak/history/ (git-tracked by default). This means every developer on the team has their own backup alongside the source code.

DataIncludedNotes
SessionsAlwaysFull session metadata including parent/child links
Prompt batchesAlwaysUser prompts, classifications, plan content
MemoriesAlwaysAll observations (gotchas, decisions, bug fixes, etc.)
ActivitiesConfigurableRaw tool execution logs — can be large. Controlled by backup settings or --include-activities flag

The default backup directory is oak/history/ inside your project. This is designed to be committed to git so backups travel with the codebase.

To use an alternative location (e.g., a secure network share):

  • Set the OAK_CI_BACKUP_DIR environment variable, or
  • Add it to your project’s .env file

Backups use content-based hashing for cross-machine deduplication:

TableHash Based On
sessionsPrimary key (session ID)
prompt_batchessession_id + prompt_number
memory_observationsobservation + type + context
activitiessession_id + timestamp + tool_name

Multiple developers’ backups can be merged without duplicates.

The daemon can create backups automatically on a configurable schedule. This ensures your CI data is always preserved without manual intervention.

Automatic backups are disabled by default. Enable them from the Backup Settings card on the Teams page, or via the configuration file:

# In .oak/config.{machine_id}.yaml
team:
backup:
auto_enabled: true
interval_minutes: 30
SettingDefaultDescription
Automatic backupsOffEnable periodic automatic backups
Include activitiesOnInclude the activities table in backups (larger files)
Backup before upgradeOnAutomatically create a backup before oak upgrade runs
Backup interval30 minHow often automatic backups run (5 min to 24 hours)

The backup interval field appears when automatic backups are enabled. Changes take effect on the next backup cycle.

  • The daemon runs a background loop that checks the interval and creates backups automatically
  • Each automatic backup replaces the previous one for your machine (one file per machine)
  • The “Include activities” setting applies to both automatic and manual backups when no explicit flag is given
  • The CLI --include-activities flag overrides the configured default

When Backup before upgrade is enabled (the default), running oak upgrade automatically creates a backup before applying any changes. This provides a safety net in case an upgrade modifies the database schema.

Terminal window
oak ci backup # Standard backup (uses configured defaults)
oak ci backup --include-activities # Include raw activities (overrides config)
oak ci backup --list # List available backups

Or use the Create Backup button on the Teams page in the dashboard.

Restore your own backup or any team member’s backup:

Terminal window
oak ci restore # Restore your own backup
oak ci restore --file oak/history/teammate_a7b3c2.sql # Restore a teammate's backup

After restore, ChromaDB is automatically rebuilt in the background to re-embed all memories with the current embedding model.

  • Older backup → newer schema: Missing columns use SQLite defaults (usually NULL). Works automatically.
  • Newer backup → older schema: Extra columns are stripped during import. A warning is logged but import proceeds. No data loss for columns that exist in both schemas.

The recommended way for teams to stay in sync. This single command handles the full workflow:

Terminal window
oak ci sync # Standard sync
oak ci sync --full # Rebuild index from scratch
oak ci sync --team # Merge all team backups
oak ci sync --dry-run # Preview without applying changes
  1. Stop daemon — Ensures clean state for data operations
  2. Restore backups — Applies your personal backup
  3. Start daemon — Brings the daemon back up
  4. Run migrations — Applies any schema changes from upgrades
  5. Create fresh backup — Saves current state
FlagDescription
--fullRebuild the entire code index from scratch
--teamAlso merge all team member backups from oak/history/
--include-activitiesInclude the activities table in backup (larger file)
--dry-runPreview what would happen without applying changes

“wrangler: command not found” — Install Node.js (which includes npm), then use npx wrangler --version or install globally with npm install -g wrangler.

“wrangler login” opens browser but auth fails — Check that popups aren’t blocked. Try an incognito window. Behind a corporate proxy, use an API token instead:

Terminal window
export CLOUDFLARE_API_TOKEN=your-api-token

Generate a token in the Cloudflare dashboard under My Profile > API Tokens with the Edit Cloudflare Workers template.

Worker deployment failed — Common causes:

  • Account not verified — Check email for a Cloudflare verification link
  • Subdomain not set — New accounts need to choose a *.workers.dev subdomain at Workers & Pages > Overview
  • Durable Object migration error — Re-scaffold: oak team cloud-init --force

npm install failed — Delete and retry: rm -rf .oak/ci/cloud-relay/node_modules && oak team cloud-init

Could not detect Worker URL — Check Cloudflare dashboard for the URL, then connect manually: oak team cloud-connect https://your-worker.your-subdomain.workers.dev

“Connection Refused” — Checklist:

  1. Verify Worker is deployed: curl https://your-worker.workers.dev/health
  2. Check URL: oak team cloud-url
  3. Ensure outbound WebSocket (wss://) is allowed
  4. Check daemon is running: oak team status

Instance shows “Offline”:

CauseSolution
Daemon not runningoak team start
Daemon restartingWait for auto-reconnect (exponential backoff, up to 60s)
Network interruptionConnection auto-recovers when network returns
Token mismatchRe-scaffold: rm -rf .oak/ci/cloud-relay && oak team cloud-init

WebSocket disconnects frequently — Check network stability. Review daemon logs (tail -50 .oak/ci/daemon.log) and Worker logs (cd .oak/ci/cloud-relay && npx wrangler tail).

“Token Invalid” or “Unauthorized” — For the relay token (daemon→Worker), check .oak/config.yaml. For the agent token (cloud agent→Worker), verify it matches the dashboard. Re-scaffold to reset: rm -rf .oak/ci/cloud-relay && oak team cloud-init

Token lost — Check the dashboard Teams page (reveal button), .oak/config.yaml, or .oak/ci/cloud-relay/wrangler.toml. If all lost, re-scaffold to generate fresh tokens.

MCP tool calls may time out if the codebase is very large (first search builds embeddings), network latency is high, or the daemon is under heavy load. Ensure indexing is complete (oak team status) before using cloud relay features.

  • MCP Configuration — Configure cloud AI agents to connect to your Team and Swarm MCP endpoints
  • Swarm — Connect different projects into a cross-project federation network