Skip to content

Commit 260748a

Browse files
committed
feat: update path configuration to use XDG Base Directory for all platforms and add installation guides
1 parent f684c35 commit 260748a

4 files changed

Lines changed: 322 additions & 28 deletions

File tree

docs/DEV-SETUP.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Development Setup
2+
3+
Guide for developers and LLM coding agents to set up a local development environment for oc-sync.
4+
5+
## Prerequisites
6+
7+
- Node.js 18+
8+
- npm
9+
- GitHub Personal Access Token with `repo` scope
10+
- OpenCode installed
11+
12+
## Quick Setup
13+
14+
### 1. Clone and Build
15+
16+
```bash
17+
git clone https://github.com/ercin/opencode-sync.git
18+
cd opencode-sync
19+
npm install
20+
npm run build
21+
```
22+
23+
### 2. Register Plugin with OpenCode
24+
25+
Create or edit `~/.config/opencode/opencode.json`:
26+
27+
```json
28+
{
29+
"plugin": [
30+
"file:///absolute/path/to/opencode-sync/dist/index.js"
31+
]
32+
}
33+
```
34+
35+
Replace `/absolute/path/to/opencode-sync` with the actual path to your cloned repo.
36+
37+
### 3. Set GitHub Token
38+
39+
```bash
40+
export GITHUB_TOKEN=ghp_your_token_here
41+
```
42+
43+
The token needs `repo` scope to create and access the private sync repository.
44+
45+
### 4. Start OpenCode
46+
47+
```bash
48+
opencode
49+
```
50+
51+
### 5. Verify Plugin Loaded
52+
53+
Check the log file:
54+
55+
```bash
56+
cat ~/.local/share/opencode/log/opencode-sync.log
57+
```
58+
59+
Expected output:
60+
```
61+
[opencode-sync] Plugin starting...
62+
[opencode-sync] Token loaded from: environment variable
63+
[opencode-sync] Setting up sync storage...
64+
[opencode-sync] Creating sync repository...
65+
[opencode-sync] Linked to repo: username/.opencode-sync
66+
[opencode-sync] Plugin ready
67+
```
68+
69+
## Development Workflow
70+
71+
### Watch Mode
72+
73+
Run TypeScript compiler in watch mode for automatic rebuilds:
74+
75+
```bash
76+
npm run dev
77+
```
78+
79+
After each rebuild, restart OpenCode to pick up changes.
80+
81+
### Manual Build
82+
83+
```bash
84+
npm run build
85+
```
86+
87+
### Code Quality
88+
89+
```bash
90+
npm run check # Run all checks (typecheck + lint + format)
91+
npm run typecheck # TypeScript type checking
92+
npm run lint # ESLint
93+
npm run format # Prettier
94+
```
95+
96+
## File Structure
97+
98+
```
99+
src/
100+
├── plugin/ # OpenCode plugin integration
101+
│ ├── plugin.ts # Main plugin entry point
102+
│ └── state-manager.ts
103+
├── sync/
104+
│ ├── engine/ # Core sync orchestration
105+
│ ├── merge/ # Three-way merge logic
106+
│ ├── operations/ # Push/pull operations
107+
│ └── watcher/ # File system watcher
108+
├── storage/ # GitHub repo backend
109+
├── data/ # Local data loading/saving
110+
├── crypto/ # Encryption for credentials
111+
└── types/ # TypeScript type definitions
112+
```
113+
114+
## Log File Location
115+
116+
All plugin logs go to:
117+
118+
```
119+
~/.local/share/opencode/log/opencode-sync.log
120+
```
121+
122+
Tail logs in real-time:
123+
124+
```bash
125+
tail -f ~/.local/share/opencode/log/opencode-sync.log
126+
```
127+
128+
## Configuration
129+
130+
After first run, the plugin creates `~/.config/opencode/opencode-sync.json`:
131+
132+
```json
133+
{
134+
"token": "ghp_...",
135+
"machineId": "hostname-abc123",
136+
"repoOwner": "username",
137+
"repoName": ".opencode-sync",
138+
"autoSyncOnStartup": true,
139+
"continuousSync": true,
140+
"syncIntervalMinutes": 5,
141+
"sync": {
142+
"config": true,
143+
"state": true,
144+
"credentials": true,
145+
"sessions": true,
146+
"messages": true,
147+
"projects": true,
148+
"todos": true
149+
}
150+
}
151+
```
152+
153+
## Troubleshooting
154+
155+
### Plugin not loading
156+
157+
1. Check `opencode.json` has correct absolute path to `dist/index.js`
158+
2. Ensure `npm run build` completed successfully
159+
3. Check OpenCode logs: `~/.local/share/opencode/log/*.log`
160+
161+
### "No configuration found"
162+
163+
Set `GITHUB_TOKEN` environment variable or create config file manually.
164+
165+
### "Failed to create repo"
166+
167+
- Verify token has `repo` scope
168+
- Check if repo already exists at `github.com/username/.opencode-sync`
169+
170+
### Changes not reflecting
171+
172+
1. Run `npm run build`
173+
2. Restart OpenCode completely (not just the TUI)

docs/LLM-INSTALL.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# LLM Agent Installation Guide for oc-sync
2+
3+
Copy and paste the following instructions to your LLM agent:
4+
5+
---
6+
7+
```
8+
## Task: Install and Configure oc-sync (OpenCode Sync Plugin)
9+
10+
You are helping the user install oc-sync, which syncs OpenCode data across machines using a private GitHub repository.
11+
12+
### Prerequisites Check
13+
Ask the user:
14+
1. "Do you have Node.js 18 or higher installed?" - If no, guide them to install from https://nodejs.org
15+
2. "Do you have a GitHub account?" - If no, guide them to create one at https://github.com
16+
17+
### Step 1: Install the Package
18+
Run this command:
19+
npm install oc-sync
20+
21+
### Step 2: Create Private GitHub Repository
22+
Guide the user:
23+
1. Go to https://github.com/new
24+
2. Repository name: suggest "opencode-sync-data" or ask user preference
25+
3. Set visibility to "Private" (important for security)
26+
4. Click "Create repository"
27+
5. Ask user: "What is your GitHub username?" - Save this as OWNER
28+
6. Ask user: "What did you name the repository?" - Save this as REPO
29+
30+
### Step 3: Generate GitHub Personal Access Token
31+
Guide the user step by step:
32+
1. Go to https://github.com/settings/tokens?type=beta
33+
2. Click "Generate new token"
34+
3. Token name: "opencode-sync"
35+
4. Expiration: recommend "90 days" or "No expiration" based on user preference
36+
5. Under "Repository access", select "Only select repositories" and choose the sync repo created in Step 2
37+
6. Under "Permissions" → "Repository permissions":
38+
- Contents: Read and write
39+
- Metadata: Read-only
40+
7. Click "Generate token"
41+
8. IMPORTANT: Tell user to copy the token immediately (starts with "github_pat_")
42+
9. Ask user: "Please paste your token here" - Save this as TOKEN
43+
44+
### Step 4: Generate Encryption Key
45+
Tell the user:
46+
"I'll generate a secure encryption key for you. This encrypts your data before uploading to GitHub."
47+
48+
Generate a random 32-character alphanumeric string for the user, or ask them to provide their own (minimum 16 characters).
49+
Save this as ENCRYPTION_KEY.
50+
51+
IMPORTANT: Tell user to save this key securely. If lost, synced data cannot be decrypted.
52+
53+
### Step 5: Create Configuration
54+
Create or update the OpenCode config file with these values:
55+
56+
{
57+
"plugins": {
58+
"oc-sync": {
59+
"token": "<TOKEN from Step 3>",
60+
"owner": "<OWNER from Step 2>",
61+
"repo": "<REPO from Step 2>",
62+
"branch": "main",
63+
"encryptionKey": "<ENCRYPTION_KEY from Step 4>"
64+
}
65+
}
66+
}
67+
68+
Show the user the complete config with their actual values filled in.
69+
70+
### Step 6: Verify Installation
71+
Tell user to restart OpenCode. The plugin will:
72+
- Auto-sync on startup
73+
- Watch for file changes
74+
- Push/pull automatically
75+
76+
### Troubleshooting
77+
If user reports errors:
78+
- "404 Not Found": Repository name or owner is wrong. Verify spelling.
79+
- "401 Unauthorized": Token is invalid or expired. Generate a new one.
80+
- "403 Forbidden": Token lacks required permissions. Recreate with Contents read/write.
81+
- "Encryption error": Key is less than 16 characters or contains invalid characters.
82+
83+
### Summary
84+
After setup, confirm with user:
85+
- GitHub username: [OWNER]
86+
- Repository: [REPO] (private)
87+
- Token: configured (never display full token)
88+
- Encryption: enabled with [length]-character key
89+
- Status: Ready to sync
90+
```
91+
92+
---

docs/SYNC-PATHS.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Sync Paths
2+
3+
OpenCode uses `xdg-basedir` which applies XDG Base Directory paths on **all platforms** (Linux, macOS, and Windows).
4+
5+
## Base Directories (All Platforms)
6+
7+
| Purpose | Path |
8+
|---------|------|
9+
| Config | `~/.config/opencode/` |
10+
| State | `~/.local/state/opencode/` |
11+
| Data | `~/.local/share/opencode/` |
12+
13+
## Sync Categories
14+
15+
| Category | Type | Path |
16+
|----------|------|------|
17+
| config | file | `~/.config/opencode/opencode.json` |
18+
| config | dir | `~/.config/opencode/commands/` |
19+
| config | dir | `~/.config/opencode/plugins/` |
20+
| state | file | `~/.local/state/opencode/kv.json` |
21+
| state | file | `~/.local/state/opencode/model.json` |
22+
| state | file | `~/.local/state/opencode/prompt-history.jsonl` |
23+
| credentials | file | `~/.local/share/opencode/auth.json` |
24+
| credentials | file | `~/.local/share/opencode/mcp-auth.json` |
25+
| sessions | dir | `~/.local/share/opencode/storage/session/` |
26+
| messages | dir | `~/.local/share/opencode/storage/message/` |
27+
| messages | dir | `~/.local/share/opencode/storage/part/` |
28+
| projects | dir | `~/.local/share/opencode/storage/project/` |
29+
| todos | dir | `~/.local/share/opencode/storage/todo/` |
30+
| todos | dir | `~/.local/share/opencode/storage/session_diff/` |
31+
32+
## Windows Note
33+
34+
On Windows, `~` refers to `C:\Users\<username>`. The full paths are:
35+
36+
| Purpose | Windows Path |
37+
|---------|--------------|
38+
| Config | `C:\Users\<username>\.config\opencode\` |
39+
| State | `C:\Users\<username>\.local\state\opencode\` |
40+
| Data | `C:\Users\<username>\.local\share\opencode\` |
41+
42+
OpenCode uses `xdg-basedir` which does NOT use `%APPDATA%` or `%LOCALAPPDATA%`.
43+
44+
## Source References
45+
46+
Paths verified from OpenCode source code:
47+
- `packages/opencode/src/global/index.ts` - Base directory definitions
48+
- `packages/opencode/src/auth/index.ts` - auth.json location
49+
- `packages/opencode/src/mcp/auth.ts` - mcp-auth.json location
50+
- `packages/opencode/src/storage/storage.ts` - Storage subdirectories
51+
- `packages/opencode/src/cli/cmd/tui/context/kv.tsx` - kv.json location

src/types/paths.ts

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,9 @@ export interface PathConfig {
1313
}
1414

1515
export function getPathConfig(homeDir: string): PathConfig {
16-
const isWindows = process.platform === 'win32';
17-
18-
if (isWindows) {
19-
const appData = process.env['APPDATA'] ?? `${homeDir}\\AppData\\Roaming`;
20-
const localAppData = process.env['LOCALAPPDATA'] ?? `${homeDir}\\AppData\\Local`;
21-
22-
return {
23-
configDir: `${appData}\\opencode`,
24-
stateDir: `${localAppData}\\opencode`,
25-
dataDir: `${localAppData}\\opencode`,
26-
pluginConfigPath: `${appData}\\opencode\\opencode-sync.json`,
27-
localStatePath: `${localAppData}\\opencode\\opencode-sync-state.json`,
28-
};
29-
}
30-
16+
// OpenCode uses xdg-basedir which applies XDG-style paths on ALL platforms
17+
// including Windows. See: https://github.com/sindresorhus/xdg-basedir
18+
// This means ~/.config, ~/.local/share, ~/.local/state are used everywhere.
3119
return {
3220
configDir: `${homeDir}/.config/opencode`,
3321
stateDir: `${homeDir}/.local/state/opencode`,
@@ -42,20 +30,10 @@ export function getCategoryPaths(pathConfig: PathConfig): Record<SyncCategory, s
4230
return {
4331
config: [
4432
`${pathConfig.configDir}/opencode.json`,
45-
`${pathConfig.configDir}/opencode.jsonc`,
46-
`${pathConfig.configDir}/AGENTS.md`,
47-
`${pathConfig.configDir}/agent`,
48-
`${pathConfig.configDir}/command`,
49-
`${pathConfig.configDir}/mode`,
50-
`${pathConfig.configDir}/tool`,
51-
`${pathConfig.configDir}/plugin`,
52-
`${pathConfig.configDir}/themes`,
53-
],
54-
state: [
55-
`${pathConfig.stateDir}/model.json`,
56-
`${pathConfig.stateDir}/prompt-history.jsonl`,
57-
`${pathConfig.stateDir}/prompt-stash.jsonl`,
33+
`${pathConfig.configDir}/commands`,
34+
`${pathConfig.configDir}/plugins`,
5835
],
36+
state: [`${pathConfig.stateDir}/model.json`, `${pathConfig.stateDir}/prompt-history.jsonl`],
5937
credentials: [`${pathConfig.dataDir}/auth.json`, `${pathConfig.dataDir}/mcp-auth.json`],
6038
sessions: [`${pathConfig.dataDir}/storage/session`],
6139
messages: [`${pathConfig.dataDir}/storage/message`, `${pathConfig.dataDir}/storage/part`],

0 commit comments

Comments
 (0)