Local by default,
honest about sync
Operon captures every prompt, response, and decision from your AI coding sessions. That data is sensitive. Here's exactly how we protect it — and exactly what leaves your machine when you turn cloud sync on.
How your data flows
By design, Operon keeps your development data local. Cloud sync is opt-in, requires a Pro+ account, and never uploads your repository as files — but it does sync session content by default. See exactly what below.
Local components
- AI Tools — Claude Code, Cursor, Codex, Gemini CLI, Aider
- Terminal Daemon — persistent PTY session manager
- Hook Receiver — localhost:47777, auth token required
- SQLite Database — local only, WAL mode, crash-safe
- Event Bus — typed async channel, in-process only
Everything above stays on your machine forever.
Pro tier and above
- RLS policies — per-user isolation enforced at DB layer
- Encrypted transit — HTTPS/TLS to Supabase
- userId ownership — verified on every query
- Realtime sync — authenticated WebSocket, no polling
What syncs by default:Events & traces, Tasks & decisions, token usage stats, session metadata — plus prompt text, agent response text, tool inputs/outputs, and code diffs. Turn code-content sync off per project in Settings.
Operon never uploads your repository as files.
Four guarantees we stand behind
These aren't aspirational policies — every item below is implemented and shipped in the current release.
Local-First by Default
- All data stored in local SQLite database
- WAL mode for crash-safe writes
- Schema versioning with migrations
- Integrity checks and auto-backup on corruption
- Zero cloud dependency in solo mode
Your Codebase Stays Put
- Operon never uploads your repository as files
- Terminal output stays on your machine
- File contents analyzed locally
- Git diffs computed locally via simple-git
- Cloud sync (Pro+): session content, on by default — configurable per project
- With cloud sync on, those diffs and your prompt/response text do sync by default — turn code-content sync off per project in Settings
Authenticated Hook System
- Hook receiver bound to 127.0.0.1 only (localhost)
- Persistent auth token stored in ~/.operon/config.json
- Token validated on every hook event
- Separate MCP write token from hook auth token
- No external network access required
Data Isolation
- userId ownership checks on all IPC handlers
- verifySessionAccess / verifyProjectAccess guards
- Scoped data exports per user
- Sign-out teardown: end sessions, kill PTYs, stop watchers
- SyncEngine backfill claims only recent data (last 60s)
Cloud Sync Security
Cloud sync requires a Pro+ account and is opt-in at the account level. Once on, session content syncs by default — you can turn code-content sync off per project, and your repository is never uploaded as files.
What syncs
- Events, traces, and tool execution records
- Tasks, decisions, and flight plan steps
- Token usage and cost statistics
- Session metadata (name, duration, project)
- Context monitor snapshots
- By default: prompt text, agent response text, tool inputs/outputs, and code diffs
What NEVER syncs
- Your repository as files — Operon never uploads the codebase itself
- Terminal output or raw shell buffers
- Local file paths or directory structures
HTTPS/TLS to Supabase — all data encrypted in transit
PostgreSQL with Row Level Security (RLS) — per-user isolation enforced at DB layer on every cloud_* table
Supabase Auth — GitHub/Google OAuth and email/password with CSRF validation
Team membership verified on every query — project-scoped data access
Supabase Realtime via authenticated WebSocket — no polling, no shared channels
Sync uses outbox + conflict resolution — offline-safe with no data loss
SyncEngine only claims sessions from the last 60 seconds on initial sign-in — never claims all NULL-owned local data
Local proj_xxx identifiers translated to cloud UUIDs at sync time — no cross-user identifier collisions
Tool execution records (including inputs/outputs) sync by default. Disable per-project with the sync_code_content setting.
Every cloud table, row-level isolated
Row Level Security (RLS) is enforced at the Postgres layer on every cloud_*table — the DB itself refuses to serve rows that don't match the requesting identity, so cross-user access requires an RLS policy defect, not just an application bug.
10+ cloud tables with RLS
- profiles
- teams + team_members + invites
- devices
- sync_records + sync_state + audit_log
- cloud_sessions + cloud_traces + cloud_tasks
- cloud_decisions + cloud_events + cloud_plans
- cloud_project_memory + cloud_patterns
- cloud_checkpoints + cloud_memory_audit
- cloud_orchestration_plans + cloud_orchestration_subtasks
- session_replays
Identity-bound reads and writes
- Every query is authenticated via Supabase JWT — no anonymous access
- Policies check
auth.uid()againstuser_id/team_idon every row - Admin roles use explicit service-role keys with full audit logging
- Team membership is re-verified on every read — leaving the team removes access immediately
- No raw SQL paths bypass RLS — all access goes through PostgREST
Error reports only with your consent
Operon's error reporter is wired through a consent store and a Sentry adapter — but neither runs unless you've explicitly opted in. And even then, an env-disable flag overrides consent.
Consent denied = zero telemetry
When consent is denied, Operon instantiates a no-op error reporter. No network calls, no Sentry initialization, no background hooks. The code path literally does nothing.
Double gate
Telemetry requires both user consent AND the absence of OPERON_DISABLE_TELEMETRY=1. Either gate closed = no telemetry. Enterprise installs can hard-disable via env without touching user settings.
Every change logged
Consent grants and revocations are persisted to thetelemetry_consent table with timestamps. Revoke anytime from Settings; the no-op reporter takes over on next app start.
Defense in depth
Operon is an Electron app — an attack surface we take seriously. Here's the full list of security controls in the current release.
- Content Security Policy — CSP headers restrict script execution to known origins — inline script injection blocked at the Electron layer.
- Web Security — Electron webSecurity is enabled. Node integration is off in the renderer process — no direct Node.js access from renderer code.
- Single Instance Lock — Prevents multiple Operon processes from running simultaneously — eliminates race conditions on local data and PTY ownership conflicts.
- Typed RPC with zod validation — Every main-process subsystem registers typed handlers via a Proxy-based RPC router. Every payload is zod-validated at the boundary before it touches business logic. Renderer calls via auto-typed rpc.* proxies — no string-indexed IPC channels.
- IPC Validation — All IPC handlers enforce: path traversal prevention with home boundary checks, tool enum validation, and string length limits on all inputs.
- Per-User Data Isolation — userId ownership guards run on every IPC handler and every engine query (SessionDNA, CrossSessionAnalyzer, TeamAnalyzer). verifySessionAccess / verifyProjectAccess enforce scope at query time — no cross-user data access paths.
- Error Boundaries — React ErrorBoundary catches renderer crashes — uncaught errors are isolated and displayed without crashing the entire UI or losing session state.
- Buffer Limits — Shell buffer capped at 512KB, response buffer at 256KB — prevents unbounded memory growth from runaway AI sessions or large terminal outputs.
- OAuth CSRF Protection — State parameter generated and validated on all OAuth flows — GitHub and Google sign-in both protected against cross-site request forgery.
- Credential Storage via Keytar — SSH connection credentials and integration tokens (Linear / GitHub / Jira / GitLab) are stored in the OS keychain via keytar — never in plaintext config, never in the SQLite database.
- HMAC-verified Webhooks — GitHub and Linear webhook receivers verify HMAC-SHA256 signatures on every inbound request. Failed signature = 401 with explicit error. No silent drops, no unauthenticated triggers.
- Injectable SSH Factory — The SSH connection pool accepts an injectable ssh2 factory — swappable for audit reviews, mocking in tests, or self-hosted identity systems. Transparency by design.
- Opt-In Telemetry — Telemetry consent is explicit per-install. ErrorReporter uses a Sentry adapter only when consent is granted AND no env-disable flag is set — otherwise a no-op reporter wins. Consent + env both required.
Execution security
AI agents are powerful — but unconstrained agents are a liability. Operon's harness enforces boundaries at the OS level, requires explicit approval at every step, and logs everything for audit.
Scope Enforcement
- Agents are restricted to developer-defined file boundaries
- Out-of-scope writes are detected by file system monitoring shortly after they land
- Violations trigger automatic git revert + PTY pause
- No tool cooperation required — enforcement works at the OS level
Checkpoint Gates
- Every plan step requires explicit developer approval
- Git snapshots created at each checkpoint for rollback
- Confidence scoring flags high-risk operations before approval
Intent Monitoring
- Real-time drift detection catches agents that exceed their mandate
- Heuristic-based (no data leaves your machine)
Audit Trail
- Every scope violation, checkpoint approval, and intent drift is logged
- Full audit trail synced to cloud for team visibility
- Decision log with rationale for every architectural choice
Session History for Compliance
- Complete session traces for review and audit
- Redaction controls for sensitive data
- Expiring links for controlled sharing
Your data, your terms
We're explicit about what we keep, where, and for how long.
Local Data
Stays on your machine forever. You own it — no expiry, no remote deletion. Export to JSON or CSV anytime from the Settings page.
Cloud Data
Retained while your account is active. Full deletion on account removal — no ghost records. GDPR-compliant deletion within 30 days.
Team Data
Scoped to team boundaries. Data removed from team namespace when a member leaves. Team admin can audit and export all team records.
Schema Backups
Local SQLite is automatically backed up before schema migrations. Corruption recovery: integrity check, auto-backup, and fresh DB on failure.
Security Roadmap
Transparency means showing what's built and what's next. These features are scoped, designed, and in the queue.
E2E Encryption
Encrypt sync payloads with team passphrase before Supabase storage — zero-knowledge metadata sync
Per-User Data Encryption
Encrypt SQLite at rest for shared-machine users — each profile fully isolated with its own key
Self-Hosted Relay
Docker container with Postgres for enterprise deployments — no Supabase dependency, full data residency control
Offline Auth Cache
Persist JWT locally for trusted offline startup — no more unauthenticated state on network loss
SOC 2 Compliance
Formal audit trail and compliance certification — required for regulated-industry and enterprise customers
Found a vulnerability?
We take responsible disclosure seriously. If you've found a security issue, please reach out directly — we keep all reports confidential.
We respond to all reports within 48 hours.
Security-first, always
Local-first, transparent, and security-first from day one.