The plugin must be installed in your OpenCode config directory:
# Linux/macOS
cd ~/.config/opencode && npm install oc-sync
# Windows (PowerShell)
cd $HOME\.config\opencode; npm install oc-syncAnd registered in opencode.json (in config directory):
{
"plugin": ["oc-sync"]
}See Sync Paths for platform-specific directory locations.
- Create a GitHub Personal Access Token with
reposcope - Set environment variable:
# Linux/macOS
export GITHUB_TOKEN=ghp_your_token_here
# Windows (PowerShell)
$env:GITHUB_TOKEN = "ghp_your_token_here"- Start OpenCode - the plugin automatically creates a private repo for sync storage
Add to your shell profile for persistence:
- Linux:
~/.bashrcor~/.zshrc - macOS:
~/.zshrc - Windows: Use System Environment Variables or PowerShell profile
Instead of environment variable, create opencode-sync.json in the config directory:
{
"token": "ghp_your_token_here"
}Config file token takes precedence over environment variable.
When the plugin starts with a valid token but no storage configured:
- Detects your GitHub username automatically
- Creates a new private repository called
.opencode-sync - Initializes the
.opencode-sync/directory with a manifest - Saves the repo info to
~/.config/opencode/opencode-sync.json - Future runs will use the same repository
After starting OpenCode, check the logs for:
[opencode-sync] Token loaded from: environment variable
[opencode-sync] Setting up sync storage...
[opencode-sync] Creating sync repository...
[opencode-sync] Linked to repo: username/.opencode-sync
[opencode-sync] Repo saved to config
[opencode-sync] Plugin ready
On subsequent runs:
[opencode-sync] Token loaded from: environment variable
[opencode-sync] Linked to repo: username/.opencode-sync
[opencode-sync] Plugin ready
| Option | Type | Default | Description |
|---|---|---|---|
token |
string | - | GitHub PAT with repo scope (required) |
repoOwner |
string | auto | GitHub username (auto-detected) |
repoName |
string | .opencode-sync |
Repository name for sync storage |
branch |
string | auto | Branch name (auto-detected: main/master) |
autoSyncOnStartup |
boolean | true |
Sync when OpenCode starts |
continuousSync |
boolean | true |
Watch files and sync on changes |
syncIntervalMinutes |
number | 5 |
Periodic sync interval |
fileWatcherDebounceMs |
number | 5000 |
Wait after file change before sync |
maxDebounceMs |
number | 30000 |
Max wait during heavy activity |
conflictStrategy |
string | auto-merge |
How to resolve conflicts |
advisoryLockTimeoutSeconds |
number | 30 |
Lock timeout for concurrent sync prevention |
maxRetryAttempts |
number | 3 |
Max retries on transient failures |
retryDelayMs |
number | 1000 |
Delay between retry attempts |
tombstoneGraceDays |
number | 30 |
Days before deleted item markers expire |
Control what gets synced:
{
"sync": {
"config": true,
"state": true,
"credentials": true,
"sessions": true,
"messages": true,
"projects": true,
"todos": true
}
}All categories are enabled by default. Disable messages if you have very large conversation history (8MB+).
| Strategy | Description |
|---|---|
auto-merge |
Attempt automatic three-way merge (default) |
local-wins |
Keep local changes on conflict |
remote-wins |
Keep remote changes on conflict |
newest-wins |
Keep whichever is newer |
ask |
Prompt for resolution |
{
"token": "ghp_your_token_here",
"repoOwner": "auto-detected-username",
"repoName": ".opencode-sync",
"autoSyncOnStartup": true,
"continuousSync": true,
"syncIntervalMinutes": 5,
"fileWatcherDebounceMs": 5000,
"maxDebounceMs": 30000,
"sync": {
"config": true,
"state": true,
"credentials": true,
"sessions": true,
"messages": true,
"projects": true,
"todos": true
},
"conflictStrategy": "auto-merge",
"advisoryLockTimeoutSeconds": 30,
"maxRetryAttempts": 3,
"retryDelayMs": 1000,
"tombstoneGraceDays": 30
}Note: machineId, keySalt, and passphraseHash are auto-generated and should not be manually edited.