@oussamadouhou/session-sync (1.2.0)
Installation
@oussamadouhou:registry=npm install @oussamadouhou/session-sync@1.2.0"@oussamadouhou/session-sync": "1.2.0"About this package
@oussamadouhou/session-sync
OpenCode plugin that syncs sessions, messages (user + assistant), tool executions, parts, and all events to the Session Manager API.
Installation
npm install -g @oussamadouhou/session-sync
Or in your opencode.json:
{
"plugin": ["@oussamadouhou/session-sync"]
}
Configuration
Set the following environment variables:
# Required - API key for authentication
export SESSION_API_KEY="your-api-key"
# Optional - API base URL (default: https://session.intra.flexinit.nl)
export SESSION_API_URL="https://session.intra.flexinit.nl"
# Optional - Enable/disable sync (default: true)
export SESSION_SYNC_ENABLED="true"
# Optional - Enable debug logging (default: false)
export SESSION_SYNC_DEBUG="true"
# Optional - Batch size for message sync (default: 10)
export SESSION_SYNC_BATCH_SIZE="10"
# Optional - Retry attempts on API failure (default: 3)
export SESSION_SYNC_RETRY_ATTEMPTS="3"
# Optional - Initial retry delay in milliseconds (default: 1000)
export SESSION_SYNC_RETRY_DELAY_MS="1000"
# Optional - Max dedup map entries to prevent memory leaks (default: 10000)
export SESSION_SYNC_MAX_DEDUP_ENTRIES="10000"
# Optional - Health check interval in milliseconds (default: 300000 = 5 min, 0 to disable)
export SESSION_SYNC_HEALTH_CHECK_INTERVAL_MS="300000"
Features
- User + Assistant Message Sync: Captures BOTH user messages and AI responses via
message.updatedevent - Message Parts Sync: Text, tools, subtasks, reasoning parts via
message.part.updatedevent - Tool Execution Tracking: Full lifecycle (before/after) with inputs, outputs, timing
- Real-time Session Sync: Automatically syncs session creation and updates
- Cost & Token Tracking: Input/output/reasoning tokens, cache read/write, total cost per message
- Project & VCS Info: Tracks project metadata and git branch changes
- Error Tracking: Captures session errors with full error details
- Message Batching: Groups data for efficient API calls
- Deduplication: Prevents duplicate syncs within 5-second windows with bounded memory
- Retry with Backoff: Configurable retry with exponential backoff on failures
- Health Check: Periodic API connectivity verification with status reporting
- Graceful Shutdown: Proper cleanup on SIGINT, SIGTERM, and SIGHUP signals
- Todo Tracking: Syncs todo items from sessions
- Compaction Context: Adds sync and health status to session compaction summaries
What Gets Synced
| Event | Data Synced |
|---|---|
session.created |
Session metadata (id, project, directory, title) |
session.updated |
Updated session metadata |
session.compacted |
Session metadata after compaction |
message.updated |
User AND Assistant messages with role, model, tokens, cost, errors |
message.part.updated |
Text, tools, subtasks, reasoning parts with timing |
tool.execute.before |
Tool name, call ID, input arguments |
tool.execute.after |
Tool output, title, metadata, execution time |
todo.updated |
Todo items with status and priority |
project.updated |
Project ID, worktree, name, VCS type |
vcs.branch.updated |
Current git branch |
session.error |
Error name, message, retryable status |
How It Works
-
Session Events: When a session is created or updated, the plugin immediately syncs session metadata to the API.
-
Message Batching: Messages are queued and flushed in batches every 2 seconds (or 10 seconds if idle) to reduce API calls.
-
Deduplication: Each session and message is tracked to prevent duplicate syncs within a 5-second window.
-
Retry Logic: Failed API calls are retried with exponential backoff. Configurable via
SESSION_SYNC_RETRY_ATTEMPTS(default: 3) andSESSION_SYNC_RETRY_DELAY_MS(default: 1000ms). -
Health Check: The plugin periodically checks API connectivity (default: every 5 minutes). Health status is included in session compaction context. Configure interval via
SESSION_SYNC_HEALTH_CHECK_INTERVAL_MSor set to 0 to disable. -
Memory Management: Deduplication maps are bounded to prevent memory leaks under high load. Configure max entries via
SESSION_SYNC_MAX_DEDUP_ENTRIES(default: 10000).
API Endpoint
The plugin sends data to POST /admin/sync with the following payload:
{
session: {
id: string;
version: string;
project_id: string;
directory: string;
title?: string;
created_at: number;
updated_at?: number;
metadata?: object;
};
messages?: Array<{
id: string;
parent_id?: string;
role: string; // "user" | "assistant"
mode?: string;
agent?: string;
provider_id?: string;
model_id?: string;
created_at: number;
completed_at?: number;
cost?: number;
tokens_input?: number;
tokens_output?: number;
tokens_reasoning?: number;
tokens_cache_read?: number;
tokens_cache_write?: number;
finish_reason?: string;
error_name?: string;
error_message?: string;
}>;
parts?: Array<{
id: string;
message_id: string;
type: string; // "text" | "tool" | "subtask" | "reasoning" | "step-start" | "step-finish" | etc.
sequence_order?: number;
text?: string;
tool_name?: string;
tool_call_id?: string;
tool_status?: string; // "pending" | "running" | "completed" | "error"
tool_input?: string; // JSON string
tool_output?: string;
tool_title?: string;
tool_error?: string;
time_start?: number;
time_end?: number;
subtask_prompt?: string;
subtask_description?: string;
subtask_agent?: string;
subtask_command?: string;
step_cost?: number;
step_tokens_input?: number;
step_tokens_output?: number;
metadata?: object;
}>;
todos?: Array<{
task_id: string;
content: string;
status: string;
priority?: string;
updated_at?: number;
}>;
tool_executions?: Array<{
id: string;
session_id: string;
call_id: string;
tool_name: string;
input: string; // JSON string
output?: string;
title?: string;
status: string; // "running" | "completed" | "error"
error?: string;
time_start?: number;
time_end?: number;
metadata?: object;
}>;
file_edits?: Array<{
session_id: string;
file_path: string;
edited_at: number;
}>;
vcs_info?: {
branch?: string;
updated_at: number;
};
project_info?: {
id: string;
worktree: string;
name?: string;
vcs?: string;
updated_at: number;
};
errors?: Array<{
session_id?: string;
error_name: string;
error_message?: string;
error_data?: object;
occurred_at: number;
}>;
}
Debug Mode
Enable debug logging to see sync activity:
export SESSION_SYNC_DEBUG="true"
Output example:
[Session Sync] Initialized - API: https://session.intra.flexinit.nl
[Session Sync] Session created: ses_abc123
[Session Sync] Synced session ses_abc123: { messages: 5, parts: 12, todos: 0 }
[Session Sync] Message captured: msg_xyz789 (session: ses_abc123)
Development
# Install dependencies
bun install
# Build TypeScript
bun run build
# Watch mode
bun run dev
# Test locally
# Add to .opencode/opencode.jsonc:
# "plugin": ["file:///absolute/path/to/dist/index.js"]
Troubleshooting
No data syncing
- Check
SESSION_API_KEYis set - Check
SESSION_SYNC_ENABLEDis not "false" - Enable debug mode:
SESSION_SYNC_DEBUG=true
Duplicate syncs
The plugin has built-in deduplication (5s window). If you see duplicates:
- Check if multiple plugin instances are running
- Verify you're not loading the plugin twice in config
API errors
Enable debug mode to see retry attempts:
[Session Sync] Retry 1/3 in 1000ms: API error 401: Unauthorized
Health check status
The plugin includes a health check endpoint. In debug mode, you'll see:
[Session Sync] Health check: OK (45ms)
[Session Sync] Health check FAILED: Network error
Health status is also included in session compaction summaries.
License
MIT
Author
Oussama Douhou
Dependencies
Development Dependencies
| ID | Version |
|---|---|
| @types/node | ^22.0.0 |
| bun-types | ^1.2.0 |
| typescript | ^5.7.0 |
Peer Dependencies
| ID | Version |
|---|---|
| @opencode-ai/plugin | >=1.0.0 |