opencode-multidevice-sync 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +15 -0
  3. package/README.md +111 -0
  4. package/README.ru.md +57 -0
  5. package/dist/cli/index.d.ts +3 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +460 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/cli/render.d.ts +45 -0
  10. package/dist/cli/render.d.ts.map +1 -0
  11. package/dist/cli/render.js +167 -0
  12. package/dist/cli/render.js.map +1 -0
  13. package/dist/cli/theme.d.ts +45 -0
  14. package/dist/cli/theme.d.ts.map +1 -0
  15. package/dist/cli/theme.js +88 -0
  16. package/dist/cli/theme.js.map +1 -0
  17. package/dist/core/backup.d.ts +13 -0
  18. package/dist/core/backup.d.ts.map +1 -0
  19. package/dist/core/backup.js +102 -0
  20. package/dist/core/backup.js.map +1 -0
  21. package/dist/core/fsx.d.ts +81 -0
  22. package/dist/core/fsx.d.ts.map +1 -0
  23. package/dist/core/fsx.js +353 -0
  24. package/dist/core/fsx.js.map +1 -0
  25. package/dist/core/git.d.ts +62 -0
  26. package/dist/core/git.d.ts.map +1 -0
  27. package/dist/core/git.js +162 -0
  28. package/dist/core/git.js.map +1 -0
  29. package/dist/core/guard.d.ts +5 -0
  30. package/dist/core/guard.d.ts.map +1 -0
  31. package/dist/core/guard.js +97 -0
  32. package/dist/core/guard.js.map +1 -0
  33. package/dist/core/health.d.ts +18 -0
  34. package/dist/core/health.d.ts.map +1 -0
  35. package/dist/core/health.js +88 -0
  36. package/dist/core/health.js.map +1 -0
  37. package/dist/core/host.d.ts +20 -0
  38. package/dist/core/host.d.ts.map +1 -0
  39. package/dist/core/host.js +50 -0
  40. package/dist/core/host.js.map +1 -0
  41. package/dist/core/index.d.ts +18 -0
  42. package/dist/core/index.d.ts.map +1 -0
  43. package/dist/core/index.js +18 -0
  44. package/dist/core/index.js.map +1 -0
  45. package/dist/core/jsonc.d.ts +20 -0
  46. package/dist/core/jsonc.d.ts.map +1 -0
  47. package/dist/core/jsonc.js +115 -0
  48. package/dist/core/jsonc.js.map +1 -0
  49. package/dist/core/lock.d.ts +14 -0
  50. package/dist/core/lock.d.ts.map +1 -0
  51. package/dist/core/lock.js +111 -0
  52. package/dist/core/lock.js.map +1 -0
  53. package/dist/core/overrides.d.ts +43 -0
  54. package/dist/core/overrides.d.ts.map +1 -0
  55. package/dist/core/overrides.js +169 -0
  56. package/dist/core/overrides.js.map +1 -0
  57. package/dist/core/paths.d.ts +36 -0
  58. package/dist/core/paths.d.ts.map +1 -0
  59. package/dist/core/paths.js +55 -0
  60. package/dist/core/paths.js.map +1 -0
  61. package/dist/core/preview.d.ts +3 -0
  62. package/dist/core/preview.d.ts.map +1 -0
  63. package/dist/core/preview.js +56 -0
  64. package/dist/core/preview.js.map +1 -0
  65. package/dist/core/repo.d.ts +57 -0
  66. package/dist/core/repo.d.ts.map +1 -0
  67. package/dist/core/repo.js +196 -0
  68. package/dist/core/repo.js.map +1 -0
  69. package/dist/core/reporter.d.ts +50 -0
  70. package/dist/core/reporter.d.ts.map +1 -0
  71. package/dist/core/reporter.js +63 -0
  72. package/dist/core/reporter.js.map +1 -0
  73. package/dist/core/sessions.d.ts +83 -0
  74. package/dist/core/sessions.d.ts.map +1 -0
  75. package/dist/core/sessions.js +508 -0
  76. package/dist/core/sessions.js.map +1 -0
  77. package/dist/core/settings.d.ts +68 -0
  78. package/dist/core/settings.d.ts.map +1 -0
  79. package/dist/core/settings.js +126 -0
  80. package/dist/core/settings.js.map +1 -0
  81. package/dist/core/setup.d.ts +48 -0
  82. package/dist/core/setup.d.ts.map +1 -0
  83. package/dist/core/setup.js +186 -0
  84. package/dist/core/setup.js.map +1 -0
  85. package/dist/core/sqlite.d.ts +37 -0
  86. package/dist/core/sqlite.d.ts.map +1 -0
  87. package/dist/core/sqlite.js +108 -0
  88. package/dist/core/sqlite.js.map +1 -0
  89. package/dist/core/stage.d.ts +44 -0
  90. package/dist/core/stage.d.ts.map +1 -0
  91. package/dist/core/stage.js +304 -0
  92. package/dist/core/stage.js.map +1 -0
  93. package/dist/core/sync.d.ts +52 -0
  94. package/dist/core/sync.d.ts.map +1 -0
  95. package/dist/core/sync.js +423 -0
  96. package/dist/core/sync.js.map +1 -0
  97. package/dist/plugin/index.d.ts +29 -0
  98. package/dist/plugin/index.d.ts.map +1 -0
  99. package/dist/plugin/index.js +88 -0
  100. package/dist/plugin/index.js.map +1 -0
  101. package/docs/MIGRATION.md +29 -0
  102. package/docs/ROADMAP.md +29 -0
  103. package/docs/SAFETY.md +31 -0
  104. package/examples/home-laptop.jsonc +31 -0
  105. package/examples/opencode-sync.overrides.jsonc +4 -0
  106. package/examples/work-laptop.jsonc +26 -0
  107. package/package.json +81 -0
@@ -0,0 +1,423 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { git, isGitRepo, parseNameStatus, parsePorcelainPaths, toGitError, } from "./git.js";
4
+ import { assertPrivateRemote, assertSafeTrackedFiles, createConfigBackup } from "./guard.js";
5
+ import { commitMessage, hostAlias } from "./host.js";
6
+ import { applyOverrides, configMatchesRepo, findConfigFile } from "./overrides.js";
7
+ import { getDatabasePath, getRoots } from "./paths.js";
8
+ import { previewSync } from "./preview.js";
9
+ import { LOCAL_RUNTIME_PATHS, assertPushLanded, assertRemoteReachable, ensureRepo, excludePathspecs, isLocalRuntimePath, unstageLocalRuntimePaths, writeRepoMetadata, } from "./repo.js";
10
+ import { emptySummary, silentReporter, summarize, totalChanges, } from "./reporter.js";
11
+ import { acknowledgeExport, exportSessions, importSessions } from "./sessions.js";
12
+ import { loadSettings, repoBranch, repoUrl } from "./settings.js";
13
+ import { sqliteAvailable } from "./sqlite.js";
14
+ import { createStageContext, normalizeConfigForRepo, prunePluginCache, stageIn, stageOut, } from "./stage.js";
15
+ class SyncError extends Error {
16
+ constructor(message) {
17
+ super(message);
18
+ this.name = "SyncError";
19
+ }
20
+ }
21
+ function prepare(options) {
22
+ const roots = options.roots ?? getRoots();
23
+ const settings = options.settings ?? loadSettings(roots.config);
24
+ const remote = repoUrl(settings);
25
+ if (!remote) {
26
+ throw new SyncError("No sync repository configured.\n" +
27
+ "Run `omds init` to create one, or `omds link <owner/repo>` to use an existing one.");
28
+ }
29
+ return {
30
+ root: roots.config,
31
+ branch: repoBranch(settings),
32
+ remote,
33
+ settings,
34
+ roots,
35
+ reporter: options.reporter ?? silentReporter,
36
+ force: options.force ?? false,
37
+ dryRun: options.dryRun ?? false,
38
+ };
39
+ }
40
+ function toChangedFiles(result, excludeRuntime) {
41
+ return parseNameStatus(result.ok ? result.stdout : "")
42
+ .filter((entry) => !excludeRuntime || !isLocalRuntimePath(entry.path))
43
+ .map((entry) => ({ kind: entry.kind, path: entry.path }));
44
+ }
45
+ // ── Push ────────────────────────────────────────────────────────────────────
46
+ export async function push(options = {}) {
47
+ if (options.dryRun)
48
+ return previewSync("push", options, pushImpl);
49
+ return pushImpl(options);
50
+ }
51
+ async function pushImpl(options) {
52
+ const ctx = prepare(options);
53
+ const { root, branch, reporter } = ctx;
54
+ if (!fs.existsSync(root))
55
+ throw new SyncError(`Config directory not found: ${root}`);
56
+ ensureRepo({ root, remote: ctx.remote, branch });
57
+ assertRemoteReachable(root, branch, "Push", true);
58
+ assertPrivateRemote(ctx.remote, ctx.settings);
59
+ const fetched = git(["fetch", "origin", branch], { cwd: root });
60
+ if (fetched.ok && !ctx.force && countCommits(root, `HEAD..origin/${branch}`) > 0)
61
+ throw new SyncError("Remote changed: pull first before exporting local sessions");
62
+ writeRepoMetadata(root);
63
+ try {
64
+ const result = await runPush(ctx);
65
+ if (!ctx.dryRun && ctx.settings.sessions.enabled)
66
+ await acknowledgeExport(getDatabasePath(ctx.roots), root, ctx.settings.sessions.pathMappings);
67
+ return result;
68
+ }
69
+ finally {
70
+ // Staging rewrites the on-disk config into its shareable form. Whatever
71
+ // happens next — success, conflict, network failure — this machine must be
72
+ // left with its own effective configuration, not the stripped one.
73
+ applyOverrides(ctx.roots.config);
74
+ }
75
+ }
76
+ async function runPush(ctx) {
77
+ const { root, branch, reporter } = ctx;
78
+ reporter.step("Staging local files");
79
+ stageIn(createStageContext(root, ctx.settings, reporter, ctx.force, ctx.roots));
80
+ const sessions = await maybeExportSessions(ctx);
81
+ git(["add", "-A"], { cwd: root });
82
+ unstageLocalRuntimePaths(root);
83
+ assertSafeTrackedFiles(root, ctx.settings);
84
+ const staged = git(["diff", "--cached", "--name-status"], { cwd: root });
85
+ const files = toChangedFiles(staged, true);
86
+ const summary = summarize(files);
87
+ if (files.length === 0) {
88
+ // No file changes, but a previous push may have failed after committing.
89
+ git(["fetch", "origin", branch], { cwd: root });
90
+ const ahead = countCommits(root, `origin/${branch}..HEAD`);
91
+ if (ahead > 0) {
92
+ if (ctx.dryRun) {
93
+ return done("push", false, summary, files, `${ahead} local commit(s) waiting to be pushed`, sessions);
94
+ }
95
+ reporter.step(`Pushing ${ahead} pending commit(s)`);
96
+ pushBranch(ctx, true);
97
+ return done("push", true, summary, files, `Pushed ${ahead} pending commit(s)`, sessions);
98
+ }
99
+ return done("push", false, summary, files, "Already up to date", sessions);
100
+ }
101
+ reporter.changes(summary, files);
102
+ if (ctx.dryRun) {
103
+ return done("push", true, summary, files, `${totalChanges(summary)} change(s) would be pushed`, sessions);
104
+ }
105
+ const alias = hostAlias(ctx.settings.machineAlias);
106
+ const commit = git(["commit", "-m", commitMessage("sync", alias)], { cwd: root });
107
+ if (!commit.ok)
108
+ throw toGitError("Commit", commit);
109
+ pushBranch(ctx, false);
110
+ return done("push", true, summary, files, `Pushed ${totalChanges(summary)} change(s)`, sessions);
111
+ }
112
+ function pushBranch(ctx, alreadyCommitted) {
113
+ const { root, branch, force, reporter } = ctx;
114
+ const hasRemoteBranch = git(["rev-parse", `origin/${branch}`], { cwd: root }).ok;
115
+ if (!hasRemoteBranch) {
116
+ const result = git(["push", "-u", "origin", branch], { cwd: root });
117
+ if (!result.ok)
118
+ throw toGitError("Push", result);
119
+ assertPushLanded(root, branch, "Push");
120
+ return;
121
+ }
122
+ if (force) {
123
+ // Refresh the tracking ref first. `--force-with-lease` compares against the
124
+ // local idea of the remote, so a stale ref makes it refuse the very
125
+ // overwrite the user explicitly asked for.
126
+ if (git(["fetch", "origin", branch], { cwd: root }).ok) {
127
+ const behind = countCommits(root, `HEAD..origin/${branch}`);
128
+ if (behind > 0) {
129
+ reporter.warn(`Overwriting ${behind} remote commit(s) that this machine does not have`);
130
+ }
131
+ }
132
+ const result = git(["push", "--force-with-lease", "origin", branch], { cwd: root });
133
+ if (!result.ok)
134
+ throw toGitError("Force push", result);
135
+ assertPushLanded(root, branch, "Force push");
136
+ return;
137
+ }
138
+ const rebase = git(["pull", "--rebase", "origin", branch], { cwd: root });
139
+ if (!rebase.ok) {
140
+ git(["rebase", "--abort"], { cwd: root });
141
+ throw new SyncError("The remote has changes that conflict with this machine.\n" +
142
+ "Run `omds pull` to take the remote version, or `omds push --force` to overwrite it.");
143
+ }
144
+ const result = git(["push", "origin", branch], { cwd: root });
145
+ if (!result.ok)
146
+ throw toGitError("Push", result);
147
+ assertPushLanded(root, branch, "Push");
148
+ void alreadyCommitted;
149
+ }
150
+ // ── Pull ────────────────────────────────────────────────────────────────────
151
+ export async function pull(options = {}) {
152
+ if (options.dryRun)
153
+ return previewSync("pull", options, pullImpl);
154
+ return pullImpl(options);
155
+ }
156
+ async function pullImpl(options) {
157
+ const ctx = prepare(options);
158
+ assertPrivateRemote(ctx.remote, ctx.settings);
159
+ try {
160
+ return await pullInternal(options);
161
+ }
162
+ finally {
163
+ applyOverrides(ctx.roots.config);
164
+ }
165
+ }
166
+ async function pullInternal(options) {
167
+ const ctx = prepare(options);
168
+ const { root, branch, reporter, force } = ctx;
169
+ fs.mkdirSync(root, { recursive: true });
170
+ createConfigBackup(root, ctx.roots.data);
171
+ if (!isGitRepo(root)) {
172
+ const state = ensureRepo({ root, remote: ctx.remote, branch });
173
+ if (state === "fresh") {
174
+ return done("pull", false, emptySummary(), [], "The sync repository is empty — push from another machine first.");
175
+ }
176
+ stageOut(createStageContext(root, ctx.settings, reporter, force, ctx.roots));
177
+ const sessions = await maybeImportSessions(ctx);
178
+ const count = git(["ls-files"], { cwd: root }).stdout.split("\n").filter(Boolean).length;
179
+ finishPull(ctx);
180
+ return done("pull", true, emptySummary(), [], `First pull complete — ${count} file(s)`, sessions, true);
181
+ }
182
+ ensureRepo({ root, remote: ctx.remote, branch });
183
+ reporter.step("Fetching from GitHub");
184
+ const fetched = git(["fetch", "origin", branch], { cwd: root });
185
+ if (!fetched.ok)
186
+ throw toGitError("Fetch", fetched);
187
+ const ahead = countCommits(root, `origin/${branch}..HEAD`);
188
+ if (!force && ahead > 0) {
189
+ throw new SyncError(`This machine has ${ahead} commit(s) that were never pushed.\n` +
190
+ "Run `omds push` first, or `omds pull --force` to discard them.");
191
+ }
192
+ const behind = countCommits(root, `HEAD..origin/${branch}`);
193
+ if (!force && behind === 0) {
194
+ // Nothing incoming, so the worktree does not need to be touched at all.
195
+ // Skipping the stash cycle here is what keeps a no-op pull fast on Windows.
196
+ const sessions = await maybeImportSessions(ctx);
197
+ return done("pull", Boolean(sessions?.imported), emptySummary(), [], "Already up to date", sessions, Boolean(sessions?.imported));
198
+ }
199
+ const stageCtx = createStageContext(root, ctx.settings, reporter, force, ctx.roots);
200
+ // The config file on disk carries this machine's overrides, so it always
201
+ // differs from HEAD. Rewinding it to the committed form first means the
202
+ // worktree is clean and the pull never has to stash-and-merge the one file
203
+ // that would conflict on every single run.
204
+ normalizeConfigForRepo(stageCtx);
205
+ const stashed = prepareWorktree(ctx);
206
+ const nameStatus = git(["diff", "--name-status", "HEAD", `origin/${branch}`], { cwd: root });
207
+ const files = toChangedFiles(nameStatus, true);
208
+ const summary = summarize(files);
209
+ if (ctx.dryRun) {
210
+ if (stashed)
211
+ restoreStash(ctx);
212
+ return done("pull", files.length > 0, summary, files, `${totalChanges(summary)} change(s) would be pulled`);
213
+ }
214
+ const reset = git(["reset", "--hard", `origin/${branch}`], { cwd: root });
215
+ if (!reset.ok) {
216
+ if (stashed)
217
+ restoreStash(ctx);
218
+ throw toGitError("Reset", reset);
219
+ }
220
+ if (stashed)
221
+ restoreStash(ctx);
222
+ stageOut(createStageContext(root, ctx.settings, reporter, force, ctx.roots));
223
+ const sessions = await maybeImportSessions(ctx);
224
+ finishPull(ctx);
225
+ reporter.changes(summary, files);
226
+ return done("pull", files.length > 0, summary, files, files.length > 0 ? `Pulled ${totalChanges(summary)} change(s)` : "Already up to date", sessions, true);
227
+ }
228
+ /** Re-apply machine-local settings and clean up caches after a pull. */
229
+ function finishPull(ctx) {
230
+ if (applyOverrides(ctx.roots.config)) {
231
+ ctx.reporter.detail("Re-applied per-machine overrides");
232
+ }
233
+ const pruned = prunePluginCache(ctx.roots.config, ctx.roots.cache);
234
+ if (pruned > 0)
235
+ ctx.reporter.detail(`Removed ${pruned} stale plugin package(s) from the cache`);
236
+ }
237
+ /**
238
+ * Get the worktree into a state where a hard reset is safe.
239
+ *
240
+ * Without `force` local edits are stashed and restored afterwards. With
241
+ * `force` they are discarded — but the runtime paths are still protected,
242
+ * because `git clean` would otherwise happily delete the user's database.
243
+ */
244
+ function prepareWorktree(ctx) {
245
+ const { root, force } = ctx;
246
+ git(["add", "-A"], { cwd: root });
247
+ unstageLocalRuntimePaths(root);
248
+ const hasStaged = git(["diff", "--cached", "--stat"], { cwd: root }).stdout.length > 0;
249
+ const untracked = git(["ls-files", "--others", "--exclude-standard", "--", ".", ...excludePathspecs()], { cwd: root });
250
+ const hasUntracked = untracked.ok && untracked.stdout.length > 0;
251
+ if (!hasStaged && !hasUntracked)
252
+ return false;
253
+ git(["reset", "HEAD"], { cwd: root });
254
+ if (force) {
255
+ git(["checkout", "--", "."], { cwd: root });
256
+ // `-e` takes gitignore-style patterns and *keeps* the matches. Using
257
+ // `:(exclude)` pathspecs here would invert the meaning and delete
258
+ // everything except the runtime paths.
259
+ git(["clean", "-fd", ...LOCAL_RUNTIME_PATHS.flatMap((p) => ["-e", p])], { cwd: root });
260
+ return false;
261
+ }
262
+ git(["add", "-A"], { cwd: root });
263
+ unstageLocalRuntimePaths(root);
264
+ const stash = git([
265
+ "stash",
266
+ "push",
267
+ "--include-untracked",
268
+ "-m",
269
+ "omds auto-stash",
270
+ "--",
271
+ ".",
272
+ ...excludePathspecs(),
273
+ ], { cwd: root });
274
+ if (!stash.ok)
275
+ throw toGitError("Stash", stash);
276
+ return !/No local changes to save/i.test(stash.stdout);
277
+ }
278
+ function restoreStash(ctx) {
279
+ const { root } = ctx;
280
+ const pop = git(["stash", "pop"], { cwd: root });
281
+ if (pop.ok)
282
+ return;
283
+ // A conflicting pop leaves the stash in place and the worktree half-merged.
284
+ // A half-merged opencode.jsonc stops OpenCode from starting, so reset to a
285
+ // known-good tree and tell the user exactly where their work still is.
286
+ git(["reset", "--hard", "HEAD"], { cwd: root });
287
+ throw new SyncError("Local changes conflicted with the incoming version.\n" +
288
+ "The worktree was rolled back to a clean state and your changes are still saved in the stash:\n" +
289
+ ` cd "${root}"\n` +
290
+ " git stash list\n" +
291
+ " git stash show -p stash@{0} # inspect\n" +
292
+ " git stash apply --index stash@{0} # restore manually\n" +
293
+ " git stash drop stash@{0} # discard\n" +
294
+ "Or re-run with --force to take the remote version.");
295
+ }
296
+ // ── Sessions ────────────────────────────────────────────────────────────────
297
+ async function maybeExportSessions(ctx) {
298
+ if (!ctx.settings.sessions.enabled)
299
+ return undefined;
300
+ if (!(await sqliteAvailable())) {
301
+ ctx.reporter.warn("Session sync is enabled but no SQLite driver is available — skipping.");
302
+ return undefined;
303
+ }
304
+ const database = getDatabasePath(ctx.roots);
305
+ ctx.reporter.step("Exporting sessions");
306
+ const result = await exportSessions(database, ctx.root, ctx.settings.sessions, ctx.reporter);
307
+ if (result.conflicts?.length)
308
+ throw new SyncError(`Session export conflicts: ${result.conflicts.join(", ")}. No push was performed.`);
309
+ for (const skipped of result.skippedTooLarge) {
310
+ ctx.reporter.warn(`Skipped "${skipped.title || skipped.id}" — ${formatBytes(skipped.bytes)} exceeds maxSessionBytes`);
311
+ }
312
+ if (result.written.length > 0) {
313
+ ctx.reporter.detail(`Exported ${result.written.length} session(s)`);
314
+ }
315
+ return { exported: result.written.length, skipped: result.skippedTooLarge.length };
316
+ }
317
+ async function maybeImportSessions(ctx) {
318
+ if (!ctx.settings.sessions.enabled)
319
+ return undefined;
320
+ if (!fs.existsSync(path.join(ctx.root, "_sessions")))
321
+ return undefined;
322
+ if (!(await sqliteAvailable())) {
323
+ ctx.reporter.warn("Session shards were pulled but no SQLite driver is available to import them.");
324
+ return undefined;
325
+ }
326
+ ctx.reporter.step("Importing sessions");
327
+ const result = await importSessions(getDatabasePath(ctx.roots), ctx.root, ctx.reporter, ctx.settings.sessions);
328
+ for (const failure of result.failed) {
329
+ ctx.reporter.warn(`Could not import ${failure.file}: ${failure.reason}`);
330
+ }
331
+ if (result.failed.length || result.conflicts.length)
332
+ throw new SyncError(`Session import stopped: ${result.failed.map((f) => f.reason).join("; ")} ${result.conflicts.map((c) => c.sessionId + ": " + c.reason).join("; ")}`);
333
+ if (result.imported > 0)
334
+ ctx.reporter.detail(`Imported ${result.imported} session(s)`);
335
+ return {
336
+ imported: result.imported,
337
+ skipped: result.skippedOlder,
338
+ conflicts: result.conflicts.length,
339
+ backup: result.backup,
340
+ };
341
+ }
342
+ export function status(options = {}) {
343
+ const roots = options.roots ?? getRoots();
344
+ const settings = options.settings ?? loadSettings(roots.config);
345
+ const branch = repoBranch(settings);
346
+ const remote = repoUrl(settings);
347
+ const root = roots.config;
348
+ const base = {
349
+ configured: Boolean(remote),
350
+ remote,
351
+ branch,
352
+ initialized: false,
353
+ ahead: 0,
354
+ behind: 0,
355
+ dirty: 0,
356
+ sessionsEnabled: settings.sessions.enabled,
357
+ sessionShards: countShards(root),
358
+ overridesActive: fs.existsSync(path.join(root, "opencode-sync.overrides.jsonc")),
359
+ machineAlias: hostAlias(settings.machineAlias),
360
+ };
361
+ if (!remote || !isGitRepo(root))
362
+ return base;
363
+ base.initialized = true;
364
+ const fetched = git(["fetch", "origin", branch], { cwd: root });
365
+ if (!fetched.ok)
366
+ throw toGitError("Status fetch", fetched);
367
+ base.ahead = countCommits(root, `origin/${branch}..HEAD`);
368
+ base.behind = countCommits(root, `HEAD..origin/${branch}`);
369
+ const dirty = git(["status", "--porcelain", "--", ".", ...excludePathspecs()], { cwd: root });
370
+ base.dirty = dirty.ok ? countRealChanges(root, dirty.stdout) : 0;
371
+ const log = git(["log", "-1", "--format=%s%n%cI"], { cwd: root });
372
+ if (log.ok) {
373
+ const [subject, date] = log.stdout.split("\n");
374
+ base.lastCommit = subject;
375
+ base.lastCommitDate = date;
376
+ }
377
+ return base;
378
+ }
379
+ function countShards(root) {
380
+ const dir = path.join(root, "_sessions");
381
+ if (!fs.existsSync(dir))
382
+ return 0;
383
+ return fs.readdirSync(dir).filter((f) => f.endsWith(".json.gz")).length;
384
+ }
385
+ /**
386
+ * Count genuinely uncommitted files.
387
+ *
388
+ * With overrides in use the config file always differs from the committed
389
+ * version, so a raw `git status` would report one modified file forever. That
390
+ * entry is dropped when the only difference is the overrides themselves.
391
+ */
392
+ function countRealChanges(root, porcelain) {
393
+ const paths = parsePorcelainPaths(porcelain);
394
+ if (paths.length === 0)
395
+ return 0;
396
+ const configFile = findConfigFile(root);
397
+ if (!configFile)
398
+ return paths.length;
399
+ const relative = path.relative(root, configFile).split(path.sep).join("/");
400
+ const head = git(["show", `HEAD:${relative}`], { cwd: root });
401
+ if (!configMatchesRepo(root, head.ok ? head.stdout : undefined))
402
+ return paths.length;
403
+ return paths.filter((file) => file !== relative).length;
404
+ }
405
+ // ── Helpers ─────────────────────────────────────────────────────────────────
406
+ function countCommits(root, range) {
407
+ const result = git(["rev-list", "--count", range], { cwd: root });
408
+ return result.ok ? Number(result.stdout) || 0 : 0;
409
+ }
410
+ function done(action, changed, summary, files, message, sessions, restartRequired = false) {
411
+ return { action, changed, summary, files, message, sessions, restartRequired };
412
+ }
413
+ export function formatBytes(bytes) {
414
+ if (bytes < 1024)
415
+ return `${bytes} B`;
416
+ if (bytes < 1024 * 1024)
417
+ return `${(bytes / 1024).toFixed(1)} KB`;
418
+ if (bytes < 1024 * 1024 * 1024)
419
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
420
+ return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
421
+ }
422
+ export { SyncError };
423
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export default function OpencodeMultideviceSync(ctx: {
2
+ client?: any;
3
+ directory?: string;
4
+ }): Promise<{
5
+ event?: undefined;
6
+ tool?: undefined;
7
+ } | {
8
+ event: ({ event }: {
9
+ event: {
10
+ type: string;
11
+ };
12
+ }) => Promise<void>;
13
+ tool: {
14
+ opencode_sync: {
15
+ description: string;
16
+ args: {
17
+ action: import("zod").ZodEnum<{
18
+ push: "push";
19
+ status: "status";
20
+ pull: "pull";
21
+ }>;
22
+ };
23
+ execute(args: {
24
+ action: "push" | "status" | "pull";
25
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<import("@opencode-ai/plugin").ToolResult>;
26
+ };
27
+ };
28
+ }>;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAqBA,wBAA8B,uBAAuB,CAAC,GAAG,EAAE;IAAE,MAAM,CAAC,EAAE,GAAG,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;;;;uBAkClE;QAAE,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;;;;;;;;;;;;;;;;GAgCvD"}
@@ -0,0 +1,88 @@
1
+ import fs from "node:fs";
2
+ import { tool } from "@opencode-ai/plugin";
3
+ import { withSyncLock } from "../core/lock.js";
4
+ import { getRoots } from "../core/paths.js";
5
+ import { CollectingReporter } from "../core/reporter.js";
6
+ import { loadSettings, repoUrl, settingsPath } from "../core/settings.js";
7
+ import { pull, push, status } from "../core/sync.js";
8
+ const startups = new Map();
9
+ const timers = new Map();
10
+ async function notify(client, message, failed = false) {
11
+ try {
12
+ await client?.app?.log?.({
13
+ body: { service: "opencode-multidevice-sync", level: failed ? "error" : "info", message },
14
+ });
15
+ }
16
+ catch { }
17
+ try {
18
+ await client?.tui?.showToast?.({
19
+ body: { title: "OpenCode Multidevice Sync", message, variant: failed ? "error" : "success" },
20
+ });
21
+ }
22
+ catch { }
23
+ }
24
+ export default async function OpencodeMultideviceSync(ctx) {
25
+ const roots = getRoots();
26
+ const client = ctx.client;
27
+ if (!fs.existsSync(settingsPath(roots.config)) || !repoUrl(loadSettings(roots.config)))
28
+ return {};
29
+ async function perform(action, announce) {
30
+ try {
31
+ const reporter = new CollectingReporter();
32
+ const result = await withSyncLock(roots.config, { waitMs: 30000 }, () => action === "push" ? push({ roots, reporter }) : pull({ roots, reporter }));
33
+ const message = `${action}: ${result.message}` +
34
+ (result.restartRequired ? ". Restart OpenCode to reload imported data/config." : "");
35
+ if (announce || result.changed)
36
+ await notify(client, message);
37
+ else
38
+ try {
39
+ await client?.app?.log?.({
40
+ body: { service: "opencode-multidevice-sync", level: "info", message },
41
+ });
42
+ }
43
+ catch { }
44
+ return true;
45
+ }
46
+ catch (error) {
47
+ await notify(client, `${action} failed: ${error.message}`, true);
48
+ return false;
49
+ }
50
+ }
51
+ let startup = startups.get(roots.config);
52
+ if (!startup) {
53
+ startup = loadSettings(roots.config).autoPullOnStartup
54
+ ? perform("pull", false)
55
+ : Promise.resolve(true);
56
+ startups.set(roots.config, startup);
57
+ }
58
+ return {
59
+ event: async ({ event }) => {
60
+ if (event.type !== "session.idle" || !loadSettings(roots.config).autoPushOnIdle)
61
+ return;
62
+ const previous = timers.get(roots.config);
63
+ if (previous)
64
+ clearTimeout(previous);
65
+ timers.set(roots.config, setTimeout(async () => {
66
+ timers.delete(roots.config);
67
+ if (await startup)
68
+ await perform("push", true);
69
+ else
70
+ await notify(client, "Auto-push paused: initial pull failed. Resolve the error and restart OpenCode.", true);
71
+ }, 1000));
72
+ },
73
+ tool: {
74
+ opencode_sync: tool({
75
+ description: "Sync this OpenCode installation with its configured private repository. Report status, push, or pull. Never resolves conflicts with force.",
76
+ args: { action: tool.schema.enum(["status", "push", "pull"]) },
77
+ async execute(args) {
78
+ if (args.action === "status")
79
+ return JSON.stringify(status({ roots }), null, 2);
80
+ return (await perform(args.action, true))
81
+ ? "Sync completed; see sync status and notifications."
82
+ : "Sync failed. Review the error notification/log; data was not force-overwritten.";
83
+ },
84
+ }),
85
+ },
86
+ };
87
+ }
88
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ # Migrating from opencode-github-sync 3.0.1
2
+
3
+ Do not migrate both devices blindly. This is an early preview. Test with isolated roots and disposable databases first.
4
+
5
+ 1. Finish work on the source computer and verify its last successful upstream push. Close OpenCode on both computers.
6
+ 2. Preserve a consistent SQLite backup, your configuration, and the sync repository history outside the synchronized directory. Never copy only a live DB while ignoring its WAL.
7
+ 3. Keep the existing PRIVATE sync repository; do not create a public replacement for your personal data.
8
+ 4. Install the same reviewed multidevice-sync tarball on both machines. The new CLI is `omds`; it does not take over `opencode-sync`.
9
+ 5. Keep `opencode-sync.jsonc` and `opencode-sync.overrides.jsonc`. Set `includeCredentials:false`, `includeState:false`, and initially both automatic flags to false.
10
+ 6. Remove the upstream package from the OpenCode plugin list. Move any `opencode-github-sync-safe.js` wrapper outside the plugins directory. Do not delete backups or credential files.
11
+ 7. Add the new installed plugin's absolute file URL. Do not put machine-specific paths into shared configuration without a local override.
12
+ 8. Run `omds doctor`, then `omds pull --dry-run`. Review all failures and conflicts. The first fork sync establishes content baselines only when local and remote history agree.
13
+ 9. Run `omds pull` and `omds push --dry-run`. Compare session/message/part counts and inspect at least one full conversation. A reserialization diff is expected once; repeated unchanged exports should not change shard bytes.
14
+ 10. If a legacy shard differs and no common baseline exists, the fork refuses to choose automatically. Preserve both copies and reconcile on disposable databases. Do not use force as an improvised data-repair tool.
15
+ 11. Repeat the checks on the other computer before enabling automatic operation. Keep one active device and wait for successful push before switching.
16
+
17
+ ## Isolation
18
+
19
+ The library supports explicit `roots`. CLI isolation variables are `SYNC_CONFIG_ROOT`, `SYNC_DATA_ROOT`, `SYNC_STATE_ROOT`, `SYNC_AGENTS_ROOT`, and `SYNC_CACHE_ROOT`. Use a LOCAL disposable Git remote for automated tests and keep secrets out of fixtures.
20
+
21
+ ## Paths
22
+
23
+ In `sessions.pathMappings`, `from` is the canonical shared path and `to` is this machine's local path. Import converts from-to; export converts back. Keep mappings one-to-one. The synthetic `global` project must already exist locally and is never overwritten from a shard.
24
+
25
+ ## Rolling back the application
26
+
27
+ Close OpenCode, remove only the new plugin entry, and restore the prior configuration from backup. Keep the known-good patched upstream package until both devices pass acceptance tests. Database restoration is separate: `omds restore BACKUP --offline` refuses journals and preserves a safety backup. Never delete WAL/SHM files to bypass that refusal.
28
+
29
+ The source repo is public; personal configuration, sessions and backups are not part of this migration guide or release artifacts.
@@ -0,0 +1,29 @@
1
+ # Roadmap
2
+
3
+ ## Included in the 0.1.0 preview
4
+
5
+ - Source-level fixes for upstream reports #2, #3 and #4.
6
+ - Deterministic shards and content-based conflict detection.
7
+ - Whole-batch import transaction and integrity validation.
8
+ - Verified backups, guarded offline restore, doctor and isolated previews.
9
+ - Canonical/local path mapping and credential-file opt-out defaults.
10
+ - Synthetic fixtures, CLI smoke tests and cross-platform CI.
11
+
12
+ ## Required before recommending broad production use
13
+
14
+ - Install the packaged fork on both real Windows devices and complete a round-trip Desktop acceptance test.
15
+ - Independent review of session schema coverage and Git conflict/recovery paths.
16
+ - Broader OpenCode version compatibility matrix and explicit schema adapters.
17
+ - More crash-injection tests, disk-full tests, large-history soak tests and plugin lifecycle tests.
18
+ - Reproducible npm registry publishing with maintainer authorization/provenance.
19
+
20
+ ## Planned, not implemented or promised by 0.1.0
21
+
22
+ - Distributed machine ownership lease with expiry and safe takeover.
23
+ - A conflict viewer and explicit reconciliation commands.
24
+ - Fine-grained config-only / sessions-only sync selection.
25
+ - Session deletion tombstones and deliberate remote retention policies.
26
+ - Full workspace/path portability beyond top-level mapped fields.
27
+ - Optional encryption and stronger secret scanning.
28
+
29
+ No automatic upgrades of a user's working installation are part of CI or package installation.