Skip to main content
The sync engine (src/sync/) provides bidirectional synchronization between profClaw’s internal ticket store and external platforms: GitHub Issues, Jira, and Linear.

Core Types

SyncAdapter Interface

Each platform implements SyncAdapter:

Sync Engine Config

Conflict Resolution

When the same ticket is modified locally and remotely between sync cycles, the ConflictStrategy determines which value wins: A SyncConflict record is created for every conflict:

Sync Queue

Operations are queued and processed with retry:

Webhook-Driven Sync

When webhooks are enabled (enableWebhooks: true), inbound webhook events from GitHub/Jira/Linear trigger immediate sync operations instead of waiting for the polling interval:
  1. Webhook arrives at /api/webhooks/:platform
  2. Adapter calls parseWebhook(payload) to extract a WebhookEvent
  3. Sync engine processes the event immediately
  4. Local ticket state updated within seconds of the external change

Pull Sync

On each polling cycle, the engine calls adapter.listTickets({ updatedAfter: lastSyncAt }) with the cursor from the previous sync. This fetches only changed tickets, minimizing API quota usage.

Push Sync

When a local ticket is created or updated, a SyncOperation is added to the queue. The adapter’s createTicket or updateTicket method is called asynchronously.

Status and Priority Mapping

Each adapter implements bidirectional mapping functions. For example, the GitHub adapter maps:
The Linear adapter maps workflow states by stateType (triage, backlog, started, completed, cancelled) to profClaw’s TicketStatus enum.

Multi-Device Sync

The sync system also handles profClaw-to-profClaw synchronization for multi-instance setups. Two profClaw instances can sync their task and conversation state over Tailscale or direct HTTP, using the same SyncAdapter interface with a profclaw platform adapter.