From e11429d71a7e24b6121c573500a627f724d55f8b Mon Sep 17 00:00:00 2001 From: j4rviscmd Date: Tue, 20 Jan 2026 17:35:18 +0900 Subject: [PATCH 1/2] feat: auto-copy slash command files on plugin initialization - Add command-installer.ts to copy command files during plugin init - Remove manual postinstall setup requirement from README - Add --target bun to build script for Node.js API support - Bump version to 0.1.1 This eliminates the need for users to manually run postinstall after installing the plugin. Co-Authored-By: Claude Opus 4.5 --- README.md | 11 ++----- package.json | 4 +-- src/config/command-installer.ts | 55 +++++++++++++++++++++++++++++++++ src/config/index.ts | 1 + src/index.ts | 3 ++ 5 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 src/config/command-installer.ts diff --git a/README.md b/README.md index bc8caba..01984a7 100644 --- a/README.md +++ b/README.md @@ -40,15 +40,8 @@ Add the plugin to your `opencode.json`: } ``` -> [!CAUTION] -> **One-time setup required**: OpenCode does not execute npm postinstall scripts. -> Run this command once after initial installation to enable slash commands: -> -> ```bash -> cd ~/.cache/opencode/node_modules/opencode-agent-modes && node dist/postinstall.js -> ``` - -The following command files are copied to `~/.config/opencode/command/`: +The following command files are automatically copied to +`~/.config/opencode/command/` when the plugin initializes: - `mode-performance.md` - `mode-economy.md` diff --git a/package.json b/package.json index af2d169..f75f374 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "opencode-agent-modes", - "version": "0.1.0", + "version": "0.1.1", "description": "OpenCode plugin to switch agent modes between performance and economy presets", "module": "src/index.ts", "main": "dist/index.js", @@ -24,7 +24,7 @@ }, "scripts": { "typecheck": "tsc --noEmit", - "build": "bun build src/index.ts --outdir dist --format esm && bun build scripts/postinstall.ts --outdir dist --format esm --target node && tsc -p tsconfig.build.json", + "build": "bun build src/index.ts --outdir dist --format esm --target bun && bun build scripts/postinstall.ts --outdir dist --format esm --target node && tsc -p tsconfig.build.json", "lint": "bunx biome check src/", "format": "prettier --write 'src/**/*.ts'", "format:check": "prettier --check 'src/**/*.ts'", diff --git a/src/config/command-installer.ts b/src/config/command-installer.ts new file mode 100644 index 0000000..5f30074 --- /dev/null +++ b/src/config/command-installer.ts @@ -0,0 +1,55 @@ +import { copyFileSync, mkdirSync, readdirSync, existsSync } from "node:fs"; +import { homedir } from "node:os"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +/** + * Target directory for OpenCode command files + */ +const COMMANDS_DEST = join(homedir(), ".config", "opencode", "command"); + +/** + * Copies slash command markdown files to OpenCode's command directory. + * + * This function is called during plugin initialization to ensure + * command files are available without manual postinstall execution. + * + * @returns Number of files copied, or -1 if source directory not found + */ +export function copyCommandFiles(): number { + // Resolve the commands directory relative to this file + // In dist: dist/config/command-installer.js -> dist/../commands = commands/ + const __dirname = dirname(fileURLToPath(import.meta.url)); + const commandsSrc = join(__dirname, "..", "..", "commands"); + + // Skip if commands directory doesn't exist (shouldn't happen in production) + if (!existsSync(commandsSrc)) { + console.warn( + "[agent-mode-switcher] Commands directory not found:", + commandsSrc + ); + return -1; + } + + try { + // Ensure destination directory exists + mkdirSync(COMMANDS_DEST, { recursive: true }); + + // Find all markdown files in the commands directory + const files = readdirSync(commandsSrc).filter((f) => f.endsWith(".md")); + + // Copy each command file to the OpenCode config directory + for (const file of files) { + copyFileSync(join(commandsSrc, file), join(COMMANDS_DEST, file)); + } + + return files.length; + } catch (error) { + // Non-fatal: log warning but don't block plugin initialization + console.warn( + "[agent-mode-switcher] Warning: Could not copy command files:", + error instanceof Error ? error.message : String(error) + ); + return -1; + } +} diff --git a/src/config/index.ts b/src/config/index.ts index ee0a8e8..c0eef16 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,3 +1,4 @@ export * from './types.ts' export * from './loader.ts' export * from './initializer.ts' +export * from './command-installer.ts' diff --git a/src/index.ts b/src/index.ts index c7ae551..9566262 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import { tool } from "@opencode-ai/plugin"; import type { Plugin } from "@opencode-ai/plugin"; import { ModeManager } from "./modes/index.ts"; +import { copyCommandFiles } from "./config/index.ts"; /** * OpenCode Agent Mode Switcher Plugin @@ -14,6 +15,8 @@ const modeSwitcherPlugin: Plugin = async ({ client }) => { // Initialize on startup with error handling try { await modeManager.initialize(); + // Copy slash command files to ~/.config/opencode/command/ + copyCommandFiles(); } catch (error) { // Log error but don't block opencode startup console.error( From c1fc4b48fba2bace2f4f58664f5c8f62a741a9a2 Mon Sep 17 00:00:00 2001 From: j4rviscmd Date: Tue, 20 Jan 2026 17:45:00 +0900 Subject: [PATCH 2/2] chore: remove unused postinstall script postinstall is no longer needed since command files are now copied during plugin initialization. Co-Authored-By: Claude Opus 4.5 --- package.json | 3 +-- scripts/postinstall.ts | 47 ------------------------------------------ 2 files changed, 1 insertion(+), 49 deletions(-) delete mode 100644 scripts/postinstall.ts diff --git a/package.json b/package.json index f75f374..90849af 100644 --- a/package.json +++ b/package.json @@ -24,14 +24,13 @@ }, "scripts": { "typecheck": "tsc --noEmit", - "build": "bun build src/index.ts --outdir dist --format esm --target bun && bun build scripts/postinstall.ts --outdir dist --format esm --target node && tsc -p tsconfig.build.json", + "build": "bun build src/index.ts --outdir dist --format esm --target bun && tsc -p tsconfig.build.json", "lint": "bunx biome check src/", "format": "prettier --write 'src/**/*.ts'", "format:check": "prettier --check 'src/**/*.ts'", "test": "bun test", "test:watch": "bun test --watch", "test:coverage": "bun test --coverage", - "postinstall": "node dist/postinstall.js", "prepublishOnly": "bun run build" }, "keywords": [ diff --git a/scripts/postinstall.ts b/scripts/postinstall.ts deleted file mode 100644 index 265c9f2..0000000 --- a/scripts/postinstall.ts +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env node - -/** - * Postinstall script for opencode-agent-modes - * - * Copies command files to ~/.config/opencode/command/ - * Uses Node.js standard APIs only for Bun/Node compatibility. - */ - -import { copyFileSync, mkdirSync, readdirSync } from "node:fs"; -import { homedir } from "node:os"; -import { dirname, join } from "node:path"; -import { fileURLToPath } from "node:url"; - -/** - * Directory path constants for command file installation - * - * - __dirname: Resolves to the directory containing this script - * - COMMANDS_SRC: Source directory containing command markdown files - * - COMMANDS_DEST: Target directory in user's OpenCode config - */ -const __dirname = dirname(fileURLToPath(import.meta.url)); -const COMMANDS_SRC = join(__dirname, "..", "commands"); -const COMMANDS_DEST = join(homedir(), ".config", "opencode", "command"); - -try { - // Ensure destination directory exists, creating parent directories if needed - mkdirSync(COMMANDS_DEST, { recursive: true }); - - // Find all markdown files in the commands directory - const files = readdirSync(COMMANDS_SRC).filter((f) => f.endsWith(".md")); - - // Copy each command file to the OpenCode config directory - for (const file of files) { - copyFileSync(join(COMMANDS_SRC, file), join(COMMANDS_DEST, file)); - } - - console.log( - `[opencode-agent-modes] Copied ${files.length} command files to ${COMMANDS_DEST}`, - ); -} catch (error) { - // Non-fatal: do not block npm install on copy failure - console.warn( - "[opencode-agent-modes] Warning: Could not copy command files:", - error, - ); -}