opencode-synced 0.3.0 → 0.4.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.
@@ -0,0 +1,6 @@
1
+ ---
2
+ description: Enable secrets sync (private repo required)
3
+ ---
4
+
5
+ Use the opencode_sync tool with command "enable-secrets".
6
+ If the user supplies extra secret paths, pass them via extraSecretPaths.
@@ -0,0 +1,11 @@
1
+ ---
2
+ description: Initialize opencode-synced configuration
3
+ ---
4
+
5
+ Use the opencode_sync tool with command "init".
6
+ The repo will be created automatically if it doesn't exist (private by default).
7
+ Default repo name is "my-opencode-config" with owner auto-detected from GitHub CLI.
8
+ If the user wants a custom repo name, pass name="custom-name".
9
+ If the user wants an org-owned repo, pass owner="org-name".
10
+ If the user wants a public repo, pass private=false.
11
+ Include includeSecrets if the user explicitly opts in.
@@ -0,0 +1,15 @@
1
+ ---
2
+ description: Link this computer to an existing sync repo
3
+ ---
4
+
5
+ Use the opencode_sync tool with command "link".
6
+ This command is for linking a second (or additional) computer to an existing sync repo that was created on another machine.
7
+
8
+ IMPORTANT: This will OVERWRITE the local OpenCode configuration with the contents from the synced repo. The only thing preserved is the local overrides file (opencode-synced.overrides.jsonc).
9
+
10
+ If the user provides a repo name argument, pass it as name="repo-name".
11
+ If no repo name is provided, the tool will automatically search for common sync repo names.
12
+
13
+ After linking:
14
+ - Remind the user to restart OpenCode to apply the synced config
15
+ - If they want to enable secrets sync, they should run /sync-enable-secrets
@@ -0,0 +1,6 @@
1
+ ---
2
+ description: Pull and apply synced OpenCode config
3
+ ---
4
+
5
+ Use the opencode_sync tool with command "pull".
6
+ If updates are applied, remind the user to restart OpenCode.
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Push local OpenCode config to the sync repo
3
+ ---
4
+
5
+ Use the opencode_sync tool with command "push".
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Resolve uncommitted changes in sync repo
3
+ ---
4
+
5
+ Use the opencode_sync tool with command "resolve" to automatically resolve uncommitted changes in the local sync repository using AI.
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Show opencode-synced status
3
+ ---
4
+
5
+ Use the opencode_sync tool with command "status" and report the results.
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from '@opencode-ai/plugin';
2
+ export declare const OpencodeConfigSync: Plugin;
@@ -0,0 +1,3 @@
1
+ import type { SyncPlan } from './paths.ts';
2
+ export declare function syncRepoToLocal(plan: SyncPlan, overrides: Record<string, unknown> | null): Promise<void>;
3
+ export declare function syncLocalToRepo(plan: SyncPlan, overrides: Record<string, unknown> | null): Promise<void>;
@@ -0,0 +1,9 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ type CommitClient = PluginInput['client'];
3
+ type Shell = PluginInput['$'];
4
+ interface CommitContext {
5
+ client: CommitClient;
6
+ $: Shell;
7
+ }
8
+ export declare function generateCommitMessage(ctx: CommitContext, repoDir: string, fallbackDate?: Date): Promise<string>;
9
+ export {};
@@ -0,0 +1,35 @@
1
+ import type { SyncLocations } from './paths.ts';
2
+ export interface SyncRepoConfig {
3
+ url?: string;
4
+ owner?: string;
5
+ name?: string;
6
+ branch?: string;
7
+ }
8
+ export interface SyncConfig {
9
+ repo?: SyncRepoConfig;
10
+ localRepoPath?: string;
11
+ includeSecrets?: boolean;
12
+ includeSessions?: boolean;
13
+ includePromptStash?: boolean;
14
+ extraSecretPaths?: string[];
15
+ }
16
+ export interface SyncState {
17
+ lastPull?: string;
18
+ lastPush?: string;
19
+ lastRemoteUpdate?: string;
20
+ }
21
+ export declare function pathExists(filePath: string): Promise<boolean>;
22
+ export declare function normalizeSyncConfig(config: SyncConfig): SyncConfig;
23
+ export declare function loadSyncConfig(locations: SyncLocations): Promise<SyncConfig | null>;
24
+ export declare function writeSyncConfig(locations: SyncLocations, config: SyncConfig): Promise<void>;
25
+ export declare function loadOverrides(locations: SyncLocations): Promise<Record<string, unknown> | null>;
26
+ export declare function loadState(locations: SyncLocations): Promise<SyncState>;
27
+ export declare function writeState(locations: SyncLocations, state: SyncState): Promise<void>;
28
+ export declare function applyOverridesToRuntimeConfig(config: Record<string, unknown>, overrides: Record<string, unknown>): void;
29
+ export declare function deepMerge<T>(base: T, override: unknown): T;
30
+ export declare function stripOverrides(localConfig: Record<string, unknown>, overrides: Record<string, unknown>, baseConfig: Record<string, unknown> | null): Record<string, unknown>;
31
+ export declare function parseJsonc<T>(content: string): T;
32
+ export declare function writeJsonFile(filePath: string, data: unknown, options?: {
33
+ jsonc: boolean;
34
+ mode?: number;
35
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ export declare class SyncError extends Error {
2
+ readonly code: string;
3
+ constructor(code: string, message: string);
4
+ }
5
+ export declare class SyncConfigMissingError extends SyncError {
6
+ constructor(message: string);
7
+ }
8
+ export declare class RepoDivergedError extends SyncError {
9
+ constructor(message: string);
10
+ }
11
+ export declare class RepoPrivateRequiredError extends SyncError {
12
+ constructor(message: string);
13
+ }
14
+ export declare class RepoVisibilityError extends SyncError {
15
+ constructor(message: string);
16
+ }
17
+ export declare class SyncCommandError extends SyncError {
18
+ constructor(message: string);
19
+ }
@@ -0,0 +1,47 @@
1
+ import type { SyncConfig } from './config.ts';
2
+ export interface XdgPaths {
3
+ homeDir: string;
4
+ configDir: string;
5
+ dataDir: string;
6
+ stateDir: string;
7
+ }
8
+ export interface SyncLocations {
9
+ xdg: XdgPaths;
10
+ configRoot: string;
11
+ syncConfigPath: string;
12
+ overridesPath: string;
13
+ statePath: string;
14
+ defaultRepoDir: string;
15
+ }
16
+ export type SyncItemType = 'file' | 'dir';
17
+ export interface SyncItem {
18
+ localPath: string;
19
+ repoPath: string;
20
+ type: SyncItemType;
21
+ isSecret: boolean;
22
+ isConfigFile: boolean;
23
+ }
24
+ export interface ExtraSecretPlan {
25
+ allowlist: string[];
26
+ manifestPath: string;
27
+ entries: Array<{
28
+ sourcePath: string;
29
+ repoPath: string;
30
+ }>;
31
+ }
32
+ export interface SyncPlan {
33
+ items: SyncItem[];
34
+ extraSecrets: ExtraSecretPlan;
35
+ repoRoot: string;
36
+ homeDir: string;
37
+ platform: NodeJS.Platform;
38
+ }
39
+ export declare function resolveHomeDir(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): string;
40
+ export declare function resolveXdgPaths(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): XdgPaths;
41
+ export declare function resolveSyncLocations(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): SyncLocations;
42
+ export declare function expandHome(inputPath: string, homeDir: string): string;
43
+ export declare function normalizePath(inputPath: string, homeDir: string, platform?: NodeJS.Platform): string;
44
+ export declare function isSamePath(left: string, right: string, homeDir: string, platform?: NodeJS.Platform): boolean;
45
+ export declare function encodeSecretPath(inputPath: string): string;
46
+ export declare function resolveRepoRoot(config: SyncConfig | null, locations: SyncLocations): string;
47
+ export declare function buildSyncPlan(config: SyncConfig, locations: SyncLocations, repoRoot: string, platform?: NodeJS.Platform): SyncPlan;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ import type { SyncConfig } from './config.ts';
3
+ export interface RepoStatus {
4
+ branch: string;
5
+ changes: string[];
6
+ }
7
+ export interface RepoUpdateResult {
8
+ updated: boolean;
9
+ branch: string;
10
+ }
11
+ type Shell = PluginInput['$'];
12
+ export declare function isRepoCloned(repoDir: string): Promise<boolean>;
13
+ export declare function resolveRepoIdentifier(config: SyncConfig): string;
14
+ export declare function resolveRepoBranch(config: SyncConfig, fallback?: string): string;
15
+ export declare function ensureRepoCloned($: Shell, config: SyncConfig, repoDir: string): Promise<void>;
16
+ export declare function ensureRepoPrivate($: Shell, config: SyncConfig): Promise<void>;
17
+ export declare function parseRepoVisibility(output: string): boolean;
18
+ export declare function fetchAndFastForward($: Shell, repoDir: string, branch: string): Promise<RepoUpdateResult>;
19
+ export declare function getRepoStatus($: Shell, repoDir: string): Promise<RepoStatus>;
20
+ export declare function hasLocalChanges($: Shell, repoDir: string): Promise<boolean>;
21
+ export declare function commitAll($: Shell, repoDir: string, message: string): Promise<void>;
22
+ export declare function pushBranch($: Shell, repoDir: string, branch: string): Promise<void>;
23
+ export declare function repoExists($: Shell, repoIdentifier: string): Promise<boolean>;
24
+ export declare function getAuthenticatedUser($: Shell): Promise<string>;
25
+ export interface FoundRepo {
26
+ owner: string;
27
+ name: string;
28
+ isPrivate: boolean;
29
+ }
30
+ export declare function findSyncRepo($: Shell, repoName?: string): Promise<FoundRepo | null>;
31
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ type SyncServiceContext = Pick<PluginInput, 'client' | '$'>;
3
+ interface InitOptions {
4
+ repo?: string;
5
+ owner?: string;
6
+ name?: string;
7
+ url?: string;
8
+ branch?: string;
9
+ includeSecrets?: boolean;
10
+ includeSessions?: boolean;
11
+ includePromptStash?: boolean;
12
+ create?: boolean;
13
+ private?: boolean;
14
+ extraSecretPaths?: string[];
15
+ localRepoPath?: string;
16
+ }
17
+ interface LinkOptions {
18
+ repo?: string;
19
+ }
20
+ export interface SyncService {
21
+ startupSync: () => Promise<void>;
22
+ status: () => Promise<string>;
23
+ init: (_options: InitOptions) => Promise<string>;
24
+ link: (_options: LinkOptions) => Promise<string>;
25
+ pull: () => Promise<string>;
26
+ push: () => Promise<string>;
27
+ enableSecrets: (_extraSecretPaths?: string[]) => Promise<string>;
28
+ resolve: () => Promise<string>;
29
+ }
30
+ export declare function createSyncService(ctx: SyncServiceContext): SyncService;
31
+ export {};
@@ -0,0 +1,17 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ type Client = PluginInput['client'];
3
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
4
+ export declare function createLogger(client: Client): {
5
+ debug: (message: string, extra?: Record<string, unknown>) => void;
6
+ info: (message: string, extra?: Record<string, unknown>) => void;
7
+ warn: (message: string, extra?: Record<string, unknown>) => void;
8
+ error: (message: string, extra?: Record<string, unknown>) => void;
9
+ };
10
+ export declare function showToast(client: Client, message: string, variant: 'info' | 'success' | 'warning' | 'error'): Promise<void>;
11
+ export declare function unwrapData<T>(response: unknown): T | null;
12
+ export declare function extractTextFromResponse(response: unknown): string | null;
13
+ export declare function resolveSmallModel(client: Client): Promise<{
14
+ providerID: string;
15
+ modelID: string;
16
+ } | null>;
17
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-synced",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Sync global OpenCode config across machines via GitHub.",
5
5
  "author": {
6
6
  "name": "Ian Hildebrand"