/** * omoa.mjs — Unified OpenCode skill for oh-my-openagent management * * PURPOSE: * Single skill to manage oh-my-openagent from within OpenCode sessions. * Combines toggle, status, and post-upgrade cleanup into one interface. * * STATE FILE: * ~/.config/opencode/omoa-enabled * - If this file exists, omoa is enabled * - If this file does not exist, omoa is disabled * * HOW IT WORKS: * - Toggle: Creates/deletes state file, restarts server * - Status: Checks if state file exists * - Post-upgrade: Removes omoa plugin from opencode.json after upstream install * - The opencode-start.sh script checks for state file at startup * - If present, injects omoa via OPENCODE_CONFIG_CONTENT * * USAGE: * skill("omoa") — Load this skill * Then use the helper functions: * - omoa_status: Check if omoa is enabled * - omoa_enable: Enable omoa (create state file, restart server) * - omoa_disable: Disable omoa (delete state file, restart server) * - omoa_toggle: Toggle omoa on/off * - omoa_post_upgrade: Clean opencode.json after upstream install * * CLI EQUIVALENT: * omoa [on|off|status|toggle] * omoa-post-upgrade * * UPSTREAM REPO: * https://git.hibbhome.com/Hibbhome/opencode-omoa-toggle * * CREATED: 2026-05-03 */ import { tool } from "@opencode-ai/plugin/tool"; import { execSync } from "node:child_process"; import { existsSync, writeFileSync, unlinkSync, readFileSync, writeFileSync as writeSync } from "node:fs"; const STATE_FILE = "/home/kenny/.config/opencode/omoa-enabled"; const CONFIG_FILE = "/home/kenny/.config/opencode/opencode.json"; export const OmoaPlugin = async (_ctx) => { return { tool: { /** * Check if omoa is enabled */ omoa_status: tool({ description: "Check if oh-my-openagent is enabled", args: {}, async execute() { const enabled = existsSync(STATE_FILE); return enabled ? "oh-my-openagent is ENABLED (state file exists)" : "oh-my-openagent is DISABLED (no state file)"; }, }), /** * Enable omoa */ omoa_enable: tool({ description: "Enable oh-my-openagent (create state file, restart server)", args: {}, async execute() { try { writeFileSync(STATE_FILE, new Date().toISOString()); execSync("systemctl --user restart opencode-serve.service"); return "oh-my-openagent ENABLED. Server restarting..."; } catch (err) { return `Error: ${err.message}`; } }, }), /** * Disable omoa */ omoa_disable: tool({ description: "Disable oh-my-openagent (delete state file, restart server)", args: {}, async execute() { try { if (existsSync(STATE_FILE)) { unlinkSync(STATE_FILE); } execSync("systemctl --user restart opencode-serve.service"); return "oh-my-openagent DISABLED. Server restarting..."; } catch (err) { return `Error: ${err.message}`; } }, }), /** * Toggle omoa on/off */ omoa_toggle: tool({ description: "Toggle oh-my-openagent on/off", args: {}, async execute() { try { if (existsSync(STATE_FILE)) { unlinkSync(STATE_FILE); execSync("systemctl --user restart opencode-serve.service"); return "oh-my-openagent DISABLED. Server restarting..."; } else { writeFileSync(STATE_FILE, new Date().toISOString()); execSync("systemctl --user restart opencode-serve.service"); return "oh-my-openagent ENABLED. Server restarting..."; } } catch (err) { return `Error: ${err.message}`; } }, }), /** * Post-upgrade cleanup */ omoa_post_upgrade: tool({ description: "Remove oh-my-openagent plugin from opencode.json after upstream install", args: {}, async execute() { try { const config = JSON.parse(readFileSync(CONFIG_FILE, "utf-8")); if (!config.plugin || !Array.isArray(config.plugin)) { return "No plugin array in opencode.json — no changes needed"; } const original = [...config.plugin]; config.plugin = config.plugin.filter(p => !p.includes("oh-my-openagent")); if (original.length === config.plugin.length) { return "oh-my-openagent not found in opencode.json — no changes needed"; } writeSync(CONFIG_FILE, JSON.stringify(config, null, 2)); return `Removed oh-my-openagent from opencode.json (${original.length} → ${config.plugin.length} plugins)`; } catch (err) { return `Error: ${err.message}`; } }, }), }, }; };