diff --git a/.github/workflows/opencode-smoke.yml b/.github/workflows/opencode-smoke.yml index 8fc16fc..e6e3809 100644 --- a/.github/workflows/opencode-smoke.yml +++ b/.github/workflows/opencode-smoke.yml @@ -1,4 +1,4 @@ -name: Opencode Smoke +name: opencode smoke on: workflow_dispatch: @@ -45,17 +45,17 @@ jobs: - name: Install opencode env: - OPENCODE_INSTALL_DIR: ${{ runner.temp }}/opencode/bin + opencode_install_dir: ${{ runner.temp }}/opencode/bin run: | curl -fsSL https://opencode.ai/install | bash - echo "${OPENCODE_INSTALL_DIR}" >> "$GITHUB_PATH" + echo "${opencode_install_dir}" >> "$GITHUB_PATH" - name: Configure clean opencode home env: - OPENCODE_HOME: ${{ runner.temp }}/opencode-home + opencode_home: ${{ runner.temp }}/opencode-home PLUGIN_VERSION: ${{ steps.version.outputs.version }} run: | - export HOME="$OPENCODE_HOME" + export HOME="$opencode_home" export XDG_CONFIG_HOME="$HOME/.config" export XDG_CACHE_HOME="$HOME/.cache" export XDG_DATA_HOME="$HOME/.local/share" @@ -89,11 +89,11 @@ jobs: - name: Launch opencode (smoke) env: - OPENCODE_HOME: ${{ runner.temp }}/opencode-home - OPENCODE_SMOKE_TIMEOUT: ${{ inputs.timeout }} - OPENCODE_SMOKE_LOG: ${{ runner.temp }}/opencode-smoke.log + opencode_home: ${{ runner.temp }}/opencode-home + opencode_smoke_timeout: ${{ inputs.timeout }} + opencode_smoke_log: ${{ runner.temp }}/opencode-smoke.log run: | - export HOME="$OPENCODE_HOME" + export HOME="$opencode_home" export XDG_CONFIG_HOME="$HOME/.config" export XDG_CACHE_HOME="$HOME/.cache" export XDG_DATA_HOME="$HOME/.local/share" @@ -106,8 +106,8 @@ jobs: import time import sys - timeout = int(os.environ.get("OPENCODE_SMOKE_TIMEOUT", "20")) - log_path = os.environ.get("OPENCODE_SMOKE_LOG", "opencode-smoke.log") + timeout = int(os.environ.get("opencode_smoke_timeout", "20")) + log_path = os.environ.get("opencode_smoke_log", "opencode-smoke.log") cmd = ["opencode", "serve", "--port", "4096", "--hostname", "127.0.0.1"] proc = subprocess.Popen( diff --git a/.mise/tasks/local-pack-test b/.mise/tasks/local-pack-test index 2d7dbe5..5c34080 100755 --- a/.mise/tasks/local-pack-test +++ b/.mise/tasks/local-pack-test @@ -1,5 +1,5 @@ #!/usr/bin/env bash -#MISE description="Install packed plugin into OpenCode cache (production-like test)" +#MISE description="Install packed plugin into opencode cache (production-like test)" set -euo pipefail PLUGIN_LOCAL_FILE="${HOME}/.config/opencode/plugin/opencode-synced-local.ts" diff --git a/AGENTS.md b/AGENTS.md index fdc022c..c291745 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -67,6 +67,6 @@ ## Project Context -- **Type**: ES Module package for OpenCode plugin system +- **Type**: ES Module package for opencode plugin system - **Target**: Bun runtime, ES2021+ -- **Purpose**: Sync global OpenCode config across machines via GitHub +- **Purpose**: Sync global opencode config across machines via GitHub diff --git a/CHANGELOG.md b/CHANGELOG.md index 14fd66b..777611c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -111,11 +111,11 @@ All notable changes to this project will be documented here by Release Please. ### Features -- **sync**: Initial implementation of OpenCode configuration sync via GitHub +- **sync**: Initial implementation of opencode configuration sync via GitHub - **sync**: Support for secrets sync in private repositories - **sync**: Support for session history sync - **sync**: Support for prompt stash sync - **sync**: Added `/sync-*` slash commands for easy management -- **sync**: Added automatic sync on OpenCode startup +- **sync**: Added automatic sync on opencode startup - **sync**: Added AI-powered conflict resolution with `/sync-resolve` - **sync**: Automatic GitHub repository detection and creation during initialization diff --git a/README.md b/README.md index 4dcd04c..8e8a7f5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # opencode-synced -Sync global OpenCode configuration across machines via a GitHub repo, with optional secrets support for private repos. +Sync global opencode configuration across machines via a GitHub repo, with optional secrets support for private repos. ## Features -- Syncs global OpenCode config (`~/.config/opencode`) and related directories +- Syncs global opencode config (`~/.config/opencode`) and related directories - Optional secrets sync when the repo is private - Optional session sync to share conversation history across machines - Optional prompt stash sync to share stashed prompts and history across machines @@ -19,7 +19,7 @@ Sync global OpenCode configuration across machines via a GitHub repo, with optio ## Setup -Enable the plugin in your global OpenCode config (OpenCode will install it on next run): +Enable the plugin in your global opencode config (opencode will install it on next run): ```jsonc { @@ -28,7 +28,7 @@ Enable the plugin in your global OpenCode config (OpenCode will install it on ne } ``` -OpenCode does not auto-update plugins. To update, modify the version number in your config file. +opencode does not auto-update plugins. To update, modify the version number in your config file. ## Configure @@ -50,7 +50,7 @@ Run `/sync-link` to connect to your existing sync repo: If auto-detection fails, specify the repo name: `/sync-link my-opencode-config` -After linking, restart OpenCode to apply the synced settings. +After linking, restart opencode to apply the synced settings. ### Custom repo name or org @@ -101,7 +101,7 @@ in a private repo, set `"includeMcpSecrets": true` (requires `includeSecrets`). ### Sessions (private repos only) -Sync your OpenCode sessions (conversation history from `/sessions`) across machines by setting `"includeSessions": true`. This requires `includeSecrets` to also be enabled since sessions may contain sensitive data. +Sync your opencode sessions (conversation history from `/sessions`) across machines by setting `"includeSessions": true`. This requires `includeSecrets` to also be enabled since sessions may contain sensitive data. ```jsonc { @@ -158,8 +158,8 @@ If you want MCP secrets committed (private repos only), set `"includeMcpSecrets" Env var naming rules: - If the header name already looks like an env var (e.g. `CONTEXT7_API_KEY`), it is used directly. -- Otherwise: `OPENCODE_MCP__
` (uppercase, non-alphanumerics become `_`). -- OAuth client secrets use `OPENCODE_MCP__OAUTH_CLIENT_SECRET`. +- Otherwise: `opencode_mcp__
` (non-alphanumerics become `_`). +- OAuth client secrets use `opencode_mcp__OAUTH_CLIENT_SECRET`. ## Usage @@ -178,7 +178,7 @@ Env var naming rules: ### Trigger a sync -Restart OpenCode to run the startup sync flow (pull remote, apply if changed, push local changes if needed). +Restart opencode to run the startup sync flow (pull remote, apply if changed, push local changes if needed). ### Check status @@ -265,7 +265,7 @@ bun -e ' ### Local testing (production-like) To test the same artifact that would be published, install from a packed tarball -into OpenCode's cache: +into opencode's cache: ```bash mise run local-pack-test @@ -279,7 +279,7 @@ Then set `~/.config/opencode/opencode.json` to use: } ``` -Restart OpenCode to pick up the cached install. +Restart opencode to pick up the cached install. ## Prefer a CLI version? diff --git a/package.json b/package.json index 5b70f3e..0539445 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "opencode-synced", "version": "0.7.0", - "description": "Sync global OpenCode config across machines via GitHub.", + "description": "Sync global opencode config across machines via GitHub.", "author": { "name": "Ian Hildebrand" }, @@ -22,9 +22,7 @@ "publishConfig": { "access": "public" }, - "files": [ - "dist" - ], + "files": ["dist"], "dependencies": { "@opencode-ai/plugin": "1.0.85" }, @@ -51,8 +49,6 @@ "prepare": "husky" }, "lint-staged": { - "*.{js,ts,json}": [ - "biome check --write --no-errors-on-unmatched" - ] + "*.{js,ts,json}": ["biome check --write --no-errors-on-unmatched"] } } diff --git a/src/command/sync-link.md b/src/command/sync-link.md index 8e839f5..9344d43 100644 --- a/src/command/sync-link.md +++ b/src/command/sync-link.md @@ -5,11 +5,11 @@ description: Link this computer to an existing sync repo Use the opencode_sync tool with command "link". This command is for linking a second (or additional) computer to an existing sync repo that was created on another machine. -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). +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). If the user provides a repo name argument, pass it as name="repo-name". If no repo name is provided, the tool will automatically search for common sync repo names. After linking: -- Remind the user to restart OpenCode to apply the synced config +- Remind the user to restart opencode to apply the synced config - If they want to enable secrets sync, they should run /sync-enable-secrets diff --git a/src/command/sync-pull.md b/src/command/sync-pull.md index f487fbc..66a6a5f 100644 --- a/src/command/sync-pull.md +++ b/src/command/sync-pull.md @@ -1,6 +1,6 @@ --- -description: Pull and apply synced OpenCode config +description: Pull and apply synced opencode config --- Use the opencode_sync tool with command "pull". -If updates are applied, remind the user to restart OpenCode. +If updates are applied, remind the user to restart opencode. diff --git a/src/command/sync-push.md b/src/command/sync-push.md index 7dca3a9..cdc5a12 100644 --- a/src/command/sync-push.md +++ b/src/command/sync-push.md @@ -1,5 +1,5 @@ --- -description: Push local OpenCode config to the sync repo +description: Push local opencode config to the sync repo --- Use the opencode_sync tool with command "push". diff --git a/src/index.ts b/src/index.ts index cd26353..46b535f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -109,12 +109,12 @@ async function loadCommands(): Promise { return commands; } -export const OpencodeConfigSync: Plugin = async (ctx) => { +export const opencodeConfigSync: Plugin = async (ctx) => { const commands = await loadCommands(); const service = createSyncService(ctx); const syncTool = tool({ - description: 'Manage OpenCode config sync with a GitHub repo', + description: 'Manage opencode config sync with a GitHub repo', args: { command: tool.schema .enum(['status', 'init', 'link', 'pull', 'push', 'enable-secrets', 'resolve']) @@ -229,8 +229,8 @@ export const OpencodeConfigSync: Plugin = async (ctx) => { }; }; -export const OpencodeSynced = OpencodeConfigSync; -export default OpencodeConfigSync; +export const opencodeSynced = opencodeConfigSync; +export default opencodeConfigSync; function formatError(error: unknown): string { if (error instanceof Error) return error.message; diff --git a/src/sync/commit.ts b/src/sync/commit.ts index d6ee840..20df918 100644 --- a/src/sync/commit.ts +++ b/src/sync/commit.ts @@ -14,7 +14,7 @@ export async function generateCommitMessage( repoDir: string, fallbackDate = new Date() ): Promise { - const fallback = `Sync OpenCode config (${formatDate(fallbackDate)})`; + const fallback = `Sync opencode config (${formatDate(fallbackDate)})`; const diffSummary = await getDiffSummary(ctx.$, repoDir); if (!diffSummary) return fallback; @@ -24,7 +24,7 @@ export async function generateCommitMessage( const prompt = [ 'Generate a concise single-line git commit message (max 72 chars).', - 'Focus on OpenCode config sync changes.', + 'Focus on opencode config sync changes.', 'Return only the message, no quotes.', '', 'Diff summary:', diff --git a/src/sync/mcp-secrets.test.ts b/src/sync/mcp-secrets.test.ts index f4d8bfa..72215d0 100644 --- a/src/sync/mcp-secrets.test.ts +++ b/src/sync/mcp-secrets.test.ts @@ -92,11 +92,11 @@ describe('extractMcpSecrets', () => { mcp: { github: { headers: { - Authorization: 'Bearer {env:OPENCODE_MCP_GITHUB_AUTHORIZATION}', + Authorization: 'Bearer {env:opencode_mcp_GITHUB_AUTHORIZATION}', }, oauth: { clientId: 'public', - clientSecret: '{env:OPENCODE_MCP_GITHUB_OAUTH_CLIENT_SECRET}', + clientSecret: '{env:opencode_mcp_GITHUB_OAUTH_CLIENT_SECRET}', }, }, }, @@ -120,7 +120,7 @@ describe('extractMcpSecrets', () => { mcp: { gitlab: { headers: { - Authorization: 'Token {env:OPENCODE_MCP_GITLAB_AUTHORIZATION}', + Authorization: 'Token {env:opencode_mcp_GITLAB_AUTHORIZATION}', }, }, }, diff --git a/src/sync/mcp-secrets.ts b/src/sync/mcp-secrets.ts index 72dad4a..28bdf74 100644 --- a/src/sync/mcp-secrets.ts +++ b/src/sync/mcp-secrets.ts @@ -59,7 +59,7 @@ function buildHeaderEnvVar(serverName: string, headerName: string): string { function buildEnvVar(serverName: string, key: string): string { const serverToken = toEnvToken(serverName, 'SERVER'); const keyToken = toEnvToken(key, 'VALUE'); - return `OPENCODE_MCP_${serverToken}_${keyToken}`; + return `opencode_mcp_${serverToken}_${keyToken}`; } function toEnvToken(input: string, fallback: string): string { diff --git a/src/sync/paths.test.ts b/src/sync/paths.test.ts index 6cac1d8..e90b577 100644 --- a/src/sync/paths.test.ts +++ b/src/sync/paths.test.ts @@ -26,10 +26,10 @@ describe('resolveXdgPaths', () => { }); describe('resolveSyncLocations', () => { - it('respects OPENCODE_CONFIG_DIR', () => { + it('respects opencode_config_dir', () => { const env = { HOME: '/home/test', - OPENCODE_CONFIG_DIR: '/custom/opencode', + opencode_config_dir: '/custom/opencode', } as NodeJS.ProcessEnv; const locations = resolveSyncLocations(env, 'linux'); diff --git a/src/sync/paths.ts b/src/sync/paths.ts index eaa7a7d..73c5363 100644 --- a/src/sync/paths.ts +++ b/src/sync/paths.ts @@ -100,7 +100,7 @@ export function resolveSyncLocations( platform: NodeJS.Platform = process.platform ): SyncLocations { const xdg = resolveXdgPaths(env, platform); - const customConfigDir = env.OPENCODE_CONFIG_DIR; + const customConfigDir = env.opencode_config_dir; const configRoot = customConfigDir ? path.resolve(expandHome(customConfigDir, xdg.homeDir)) : path.join(xdg.configDir, 'opencode'); diff --git a/src/sync/service.ts b/src/sync/service.ts index a0874b0..5699402 100644 --- a/src/sync/service.ts +++ b/src/sync/service.ts @@ -296,17 +296,17 @@ export function createSyncService(ctx: SyncServiceContext): SyncService { const lines = [ `Linked to existing sync repo: ${found.owner}/${found.name}`, '', - 'Your local OpenCode config has been OVERWRITTEN with the synced config.', + 'Your local opencode config has been OVERWRITTEN with the synced config.', 'Your local overrides file was preserved and applied on top.', '', - 'Restart OpenCode to apply the new settings.', + 'Restart opencode to apply the new settings.', '', found.isPrivate ? 'To enable secrets sync, run: /sync-enable-secrets' : 'Note: Repo is public. Secrets sync is disabled.', ]; - await showToast(ctx.client, 'Config synced. Restart OpenCode to apply.', 'info'); + await showToast(ctx.client, 'Config synced. Restart opencode to apply.', 'info'); return lines.join('\n'); }), pull: () => @@ -339,8 +339,8 @@ export function createSyncService(ctx: SyncServiceContext): SyncService { lastRemoteUpdate: new Date().toISOString(), }); - await showToast(ctx.client, 'Config updated. Restart OpenCode to apply.', 'info'); - return 'Remote config applied. Restart OpenCode to use new settings.'; + await showToast(ctx.client, 'Config updated. Restart opencode to apply.', 'info'); + return 'Remote config applied. Restart opencode to use new settings.'; }), push: () => runExclusive(async () => { @@ -469,7 +469,7 @@ async function runStartup( lastPull: new Date().toISOString(), lastRemoteUpdate: new Date().toISOString(), }); - await showToast(ctx.client, 'Config updated. Restart OpenCode to apply.', 'info'); + await showToast(ctx.client, 'Config updated. Restart opencode to apply.', 'info'); return; }