How OpenCode Implements Session Sharing: Architecture and Code Deep Dive

OpenCode implements session sharing through a client-side ShareNext module that creates share records via REST API, persists metadata in SQLite, and continuously syncs session data to an Enterprise Share service using batched updates.

The anomalyco/opencode repository provides a real-time, resumable session-sharing system that works across CLI, web UI, and Slack integrations. When a user initiates a share, the system generates a unique link, stores it locally, and maintains a live synchronization channel for messages, diffs, and model updates.

Public API Interface

The sharing functionality is exposed through the Session class in packages/opencode/src/session.ts. This provides two primary methods for managing share state:

  • Session.share(sessionID) – Initiates the sharing process by invoking ShareNext.create.
  • Session.unshare(sessionID) – Terminates sharing by calling ShareNext.remove.
// Create a share link
await Session.share(sessionID)

// Remove the share link
await Session.unshare(sessionID)

These methods serve as the entry point for all client applications, abstracting the underlying synchronization complexity.

Client-Side Orchestration with ShareNext

The core sharing logic resides in packages/opencode/src/share/share-next.ts. This module handles the complete lifecycle of a shared session, from initial creation to continuous data synchronization.

Creating Shares

The create(sessionID) function performs three critical operations:

  1. Server Registration: POSTs to /api/share to generate a share record, receiving {id, url, secret}.
  2. Local Persistence: Stores the metadata in the session_share SQLite table using Database.use with onConflictDoUpdate logic.
  3. Initial Sync: Triggers fullSync to push the complete current session state to the server.

Synchronization Logic

ShareNext implements an efficient delta-sync mechanism through two key functions:

  • fullSync(sessionID) – Collects the entire session state via Session.get, Session.diff, MessageV2.stream, and model lists, then calls sync() with the complete payload.
  • sync(sessionID, data[]) – Buffers incremental updates in an in-memory queue. After a 1-second debounce period, it POSTs the batched JSON to /api/share/{id}/sync.

The init() function subscribes to internal bus events (Session.Updated, MessageV2.Updated, etc.) to automatically queue changes for synchronization without manual intervention.

Removing Shares

The remove(sessionID) function reverses the creation process:

  1. Retrieves the local share row from SQLite to obtain the secret.
  2. Sends DELETE /api/share/{id} with the secret for authentication.
  3. Deletes the local database row to clean up metadata.

Local Data Persistence

Share metadata is stored locally in SQLite via the schema defined in packages/opencode/src/share/share.sql.ts:

export const SessionShareTable = sqliteTable("session_share", {
  session_id: text().primaryKey().references(() => SessionTable.id, { onDelete: "cascade" }),
  id:        text().notNull(),
  secret:    text().notNull(),
  url:       text().notNull(),
  ...Timestamps,
})

This table maintains the mapping between local session IDs and remote share identifiers, enabling the client to retrieve the secret required for subsequent sync and delete operations.

Server-Side Implementation

HTTP API Routes

The server exposes sharing endpoints in packages/opencode/src/server/routes/session.ts:

Route Method Description
POST /:sessionID/share Creates a share record, returns full session object with share_url
DELETE /:sessionID/share Removes the share using Session.unshare
POST /api/share/:id/sync Receives batched sync data from clients

These routes serve as thin wrappers that delegate to the Enterprise Share service for actual storage operations.

Enterprise Share Service

The backend storage and synchronization logic is implemented in packages/enterprise/src/core/share.ts. This service provides the following core functions:

  • create({sessionID}) – Generates a deterministic share ID from the last 8 characters of the session ID, creates a UUID secret, and stores the record under the share/<id> prefix in the key-value store.
  • remove({id,secret}) – Validates the secret, deletes the share record, and cleans up associated share_data/* entries.
  • sync({share, data}) – Verifies the secret and writes incoming batch data to share_event/<shareID>/<timestamp> for later compaction.
  • data(shareID) – Retrieves compacted state and pending events, merges them using binary search-based ordering, and returns the full ordered list of Data objects.

The Share.Data type is a discriminated union supporting session, message, part, session_diff, and model variants, allowing the system to synchronize complex session state including code diffs and model configurations.

Real-World Usage Examples

CLI Integration

The OpenCode CLI supports session sharing via the session command in packages/opencode/src/cli/cmd/run.ts:

.command("session")
.option("share", { description: "Create a share link for the session", type: "boolean" })
.action(async (opts) => {
  if (opts.share) await Session.share(opts.sessionID)
})

Slack Integration

The Slack bot implementation in packages/slack/src/index.ts demonstrates programmatic sharing:

const shareResult = await client.session.share({ path: { id: createResult.data.id } })
if (!shareResult.error && shareResult.data) {
  console.log("🔗 Session shared:", shareResult.data.share?.url!)
}

Web UI Integration

The React-based web interface handles sharing through direct SDK calls:

// packages/web/src/pages/[...slug].md.ts
await Session.share(sessionID)
toast.success(t("toast.session.share.success.title"))

Summary

  • ShareNext module (packages/opencode/src/share/share-next.ts) orchestrates client-side sharing logic, handling creation, synchronization, and removal of share links.
  • SQLite persistence stores share metadata (ID, secret, URL) locally in the session_share table, enabling authenticated subsequent operations.
  • Batch synchronization queues incremental updates with a 1-second debounce, POSTing batched JSON to /api/share/{id}/sync for efficient real-time collaboration.
  • Enterprise Share service (packages/enterprise/src/core/share.ts) manages server-side storage using a key-value store with event sourcing (share_event/<id>/<timestamp>) and binary search-based merging for data retrieval.
  • Cross-platform support enables sharing from CLI, Slack bots, and React web interfaces through the unified Session.share API.

Frequently Asked Questions

How does OpenCode handle authentication for shared sessions?

OpenCode uses a UUID-based secret system generated during share creation. When Share.create is called in packages/enterprise/src/core/share.ts, it generates a unique secret that must be provided in subsequent sync and delete operations. The client stores this secret in the local SQLite session_share table and includes it in the Authorization header or request body when calling /api/share/{id}/sync or DELETE /api/share/{id}.

What data types are synchronized when sharing an OpenCode session?

The system synchronizes a discriminated union of data types defined in the Enterprise Share service. According to packages/enterprise/src/core/share.ts, the Share.Data type includes variants for session (full session state), message (chat messages), part (message components), session_diff (code changes), and model (AI model configurations). This comprehensive synchronization ensures that shared sessions maintain complete context including conversation history and code modifications.

How does OpenCode optimize network usage during session synchronization?

OpenCode implements a batching strategy with debouncing to minimize API calls. The ShareNext.sync function in packages/opencode/src/share/share-next.ts buffers incremental updates in an in-memory queue and waits for a 1-second debounce period before sending a single batched POST request to /api/share/{id}/sync. Additionally, the fullSync operation performs an initial complete synchronization, after which only delta updates are transmitted, reducing bandwidth consumption for long-running shared sessions.

Can shared sessions be accessed after the original client disconnects?

Yes, shared sessions persist independently of the original client connection. The Enterprise Share service in packages/enterprise/src/core/share.ts stores session data in a key-value store under the share/<id> prefix, with incremental updates written to share_event/<shareID>/<timestamp>. When a new viewer accesses the share URL, the Share.data function retrieves and compacts all stored events using binary search-based ordering, reconstructing the complete session state regardless of whether the original sharer is still online.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →