Bidirectional sync between Paperclip issues and WritBase tasks.
- Event-driven sync — Paperclip issue events push to WritBase; WritBase webhooks push to Paperclip
- Periodic reconciliation — Full sync every 15 minutes catches missed webhook events
- Conflict resolution — Version-based optimistic concurrency with automatic retry
- Echo suppression — Prevents sync loops via actor ID detection and per-entity cooldowns
- Configurable direction — Pull (WritBase→Paperclip), push (Paperclip→WritBase), or bidirectional
- Paperclip instance (v2026.318.0+, plugin system required)
- WritBase workspace with a manager-role agent key
- Node.js 20+
npm install paperclip-plugin-writbaseThen register the plugin in your Paperclip instance.
| Field | Required | Description |
|---|---|---|
writbaseUrl |
Yes | Supabase Edge Function base URL (e.g. https://your-project.supabase.co/functions/v1/mcp-server) |
agentKey |
Yes | WritBase agent key (wb_<key_id>_<secret>). Must have manager role. |
project |
Yes | WritBase project slug to sync with |
companyId |
Yes | Paperclip company ID for issue creation/listing |
department |
No | WritBase department slug (required if workspace enforces department scoping) |
syncDirection |
No | pull, push, or bidirectional (default: bidirectional) |
npx writbase key create --name paperclip-sync --role managerThe key must have manager role to register webhook subscriptions.
| WritBase | Paperclip | Notes |
|---|---|---|
todo |
todo |
|
in_progress |
in_progress |
|
blocked |
blocked |
|
done |
done |
|
cancelled |
cancelled |
|
failed |
cancelled |
Lossy — original status preserved in metadata |
| Paperclip | WritBase | Notes |
|---|---|---|
backlog |
todo |
Lossy |
todo |
todo |
|
in_progress |
in_progress |
|
in_review |
in_progress |
Lossy |
done |
done |
|
blocked |
blocked |
|
cancelled |
cancelled |
Direct 1:1 mapping: low, medium, high, critical.
| WritBase | Paperclip | Direction |
|---|---|---|
description (first line) |
title |
Both |
description (remaining) + notes |
description |
Both |
due_date |
metadata in description | WritBase→Paperclip only |
is_archived |
hiddenAt |
Both |
Not mapped: blocked_by (DAG deps vs parentId hierarchy), assignee fields, labelIds, billingCode.
-
Paperclip → WritBase: Plugin subscribes to
issue.createdandissue.updatedevents viactx.events.on(). Events are debounced (500ms) and serialized per entity to prevent version conflicts. -
WritBase → Paperclip: Plugin registers a webhook subscription on WritBase for
task.created,task.updated,task.completed,task.failedevents. Incoming webhooks are verified via Standard Webhooks HMAC-SHA256.
A scheduled job runs every 15 minutes to catch events missed by webhooks (WritBase uses fire-and-forget delivery). It pages through all tasks updated since the last run (with a 60-second overlap window) and reconciles any unmapped or out-of-sync items.
- Every WritBase mutation stores the returned
versionin the sync mapping - On
version_conflict, the plugin refetches the current task version and retries (up to 3 times) - No cross-system timestamp comparison (avoids clock skew issues)
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Type check
npm run lint
# Watch mode
npm run devApache-2.0