[GH-ISSUE #144] OpenCode plugin: install the toolkit as um_* tools + fal MCP — PR-worthy? #34

Closed
opened 2026-10-15 20:52:43 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @Selene0623 on GitHub (Oct 7, 2026).
Original GitHub issue: https://github.com/rehan-remade/universal-modder/issues/144

Follow-up to #43 / #54. Right now the OpenCode route is clone-and-run: opencode.json adds the skills and the fal MCP server, and the user has to be inside a checkout. Every other agent here already has a real plugin install (/plugin marketplace add for Claude Code, codex plugin add, gemini extensions install, VS Code "Install Plugin From Source", the Cursor marketplace). OpenCode has opencode plugin add, so I built the equivalent and I'd like to know whether you want it as a PR before I open one.

What I built

Branch: Selene0623:feat/opencode-plugin (commit e84c819, based on current main). Five files:

  • plugins/opencode/index.ts — a V2 plugin (Plugin.define({ id: "universal-modder", setup })) that:
    • registers one tool per CLI group, namespaced: um_scan, um_fal, um_comfy, um_sprite, um_render3d, um_video, um_win, um_backup, um_publish, um_kb. Each takes args (passed straight through, so ["--help"] documents the group) and an optional cwd; codemode is on so they stay scriptable.
    • resolves the launcher itself: bin/um next to the plugin, else um from PATH, with options.root / options.command overrides for a globally installed plugin.
    • registers fal's hosted MCP server (https://mcp.fal.ai/mcp, {env:FAL_KEY}, oauth: false) only when the session does not already configure one, so a user's own fal setup wins.
    • shells out to the same bin/um a human would run. The plugin does not reimplement any part of the toolkit, so the CLI stays the single source of truth and nothing needs keeping in sync.
  • plugins/opencode/package.json — @opencode/plugin as a peer dependency, version 0.2.0 to match the repo.
  • plugins/opencode/README.md — install line and options.
  • opencode.json — adds "plugins": ["./plugins/opencode"], so a clone gets the tools with no setup.
  • README.md — the OpenCode row becomes opencode plugin add 'github:rehan-remade/universal-modder#main::path:plugins/opencode', plus a sentence about the plugin next to the MCP-config paragraph.

I deliberately left alone: skills/ (skills still come from skills.paths, no double registration), .agents/skills / .claude/skills copies, AGENTS.md, and the hooks/ PATH script (that is a Claude Code SessionStart hook; V2 has no shell-env hook, which is why the tools call the launcher by absolute path instead of fighting PATH).

Verification (in the worktree)

  • uv run --with pytest pytest -q tests → 76 passed, 1 skipped
  • um kb check --index → PASS: 74 notes checked
  • um publish check . → 383 files, 0 failures, 2 warnings (both pre-existing absolute-path warnings, untouched by this branch)
  • Behavioural test with a stub @opencode/plugin and a fake plugin context: 10 tools registered under the um namespace, fal MCP set, and real runs through the CLI — um_scan {args:["--help"]} returned the real help screen, um_kb {args:["search","disrupt"]} returned real hits, and a bad flag surfaced as (exit 2).
  • The group list is asserted against GROUPS in um/cli.py, which is how I caught that I had missed comfy.

Questions before I open the PR

  1. Is a tracked plugins/opencode/ directory welcome at all, or would you rather this be a separately published package so the repo stays Python-only? (CONTRIBUTING only documents knowledge/ and skills/, so I did not want to assume.)
  2. Tool shape: ten tools, one per group, or one passthrough um tool with an args array? Ten costs more context; one is less discoverable. I can go either way.
  3. Want more than tools — a /mod-game command that kicks off skills/mod-any-game/SKILL.md, and/or the skills registered through ctx.skill.transform instead of skills.paths? I left those out to keep the first diff small.
  4. Anything to change before the PR? If you'd rather take the plugin into your own namespace or write it yourself, the branch is there to copy from — no strings attached.

Happy to adjust, or to leave it as an issue if you'd prefer OpenCode stay clone-only.

Originally created by @Selene0623 on GitHub (Oct 7, 2026). Original GitHub issue: https://github.com/rehan-remade/universal-modder/issues/144 Follow-up to #43 / #54. Right now the OpenCode route is clone-and-run: `opencode.json` adds the skills and the fal MCP server, and the user has to be inside a checkout. Every other agent here already has a real plugin install (`/plugin marketplace add` for Claude Code, `codex plugin add`, `gemini extensions install`, VS Code "Install Plugin From Source", the Cursor marketplace). OpenCode has `opencode plugin add`, so I built the equivalent and I'd like to know whether you want it as a PR before I open one. ## What I built Branch: [`Selene0623:feat/opencode-plugin`](https://github.com/Selene0623/universal-modder/tree/feat/opencode-plugin) (commit `e84c819`, based on current `main`). Five files: - **`plugins/opencode/index.ts`** — a V2 plugin (`Plugin.define({ id: "universal-modder", setup })`) that: - registers **one tool per CLI group**, namespaced: `um_scan`, `um_fal`, `um_comfy`, `um_sprite`, `um_render3d`, `um_video`, `um_win`, `um_backup`, `um_publish`, `um_kb`. Each takes `args` (passed straight through, so `["--help"]` documents the group) and an optional `cwd`; `codemode` is on so they stay scriptable. - resolves the launcher itself: `bin/um` next to the plugin, else `um` from `PATH`, with `options.root` / `options.command` overrides for a globally installed plugin. - registers fal's hosted MCP server (`https://mcp.fal.ai/mcp`, `{env:FAL_KEY}`, `oauth: false`) **only when the session does not already configure one**, so a user's own fal setup wins. - shells out to the same `bin/um` a human would run. The plugin does not reimplement any part of the toolkit, so the CLI stays the single source of truth and nothing needs keeping in sync. - **`plugins/opencode/package.json`** — `@opencode/plugin` as a peer dependency, version `0.2.0` to match the repo. - **`plugins/opencode/README.md`** — install line and options. - **`opencode.json`** — adds `"plugins": ["./plugins/opencode"]`, so a clone gets the tools with no setup. - **`README.md`** — the OpenCode row becomes `opencode plugin add 'github:rehan-remade/universal-modder#main::path:plugins/opencode'`, plus a sentence about the plugin next to the MCP-config paragraph. I deliberately left alone: `skills/` (skills still come from `skills.paths`, no double registration), `.agents/skills` / `.claude/skills` copies, `AGENTS.md`, and the `hooks/` PATH script (that is a Claude Code `SessionStart` hook; V2 has no shell-env hook, which is why the tools call the launcher by absolute path instead of fighting `PATH`). ## Verification (in the worktree) - `uv run --with pytest pytest -q tests` → **76 passed, 1 skipped** - `um kb check --index` → **PASS: 74 notes checked** - `um publish check .` → **383 files, 0 failures, 2 warnings** (both pre-existing absolute-path warnings, untouched by this branch) - Behavioural test with a stub `@opencode/plugin` and a fake plugin context: 10 tools registered under the `um` namespace, fal MCP set, and real runs through the CLI — `um_scan {args:["--help"]}` returned the real help screen, `um_kb {args:["search","disrupt"]}` returned real hits, and a bad flag surfaced as `(exit 2)`. - The group list is asserted against `GROUPS` in `um/cli.py`, which is how I caught that I had missed `comfy`. ## Questions before I open the PR 1. Is a tracked `plugins/opencode/` directory welcome at all, or would you rather this be a separately published package so the repo stays Python-only? (CONTRIBUTING only documents `knowledge/` and `skills/`, so I did not want to assume.) 2. Tool shape: ten tools, one per group, or one passthrough `um` tool with an `args` array? Ten costs more context; one is less discoverable. I can go either way. 3. Want more than tools — a `/mod-game` command that kicks off `skills/mod-any-game/SKILL.md`, and/or the skills registered through `ctx.skill.transform` instead of `skills.paths`? I left those out to keep the first diff small. 4. Anything to change before the PR? If you'd rather take the plugin into your own namespace or write it yourself, the branch is there to copy from — no strings attached. Happy to adjust, or to leave it as an issue if you'd prefer OpenCode stay clone-only.
Author
Owner

@rehan-remade commented on GitHub (Oct 10, 2026):

Thanks for asking first, and for the careful write-up. Yes, please open it. Every other agent already has a real install path, so OpenCode should too, and a tracked plugins/opencode/ is fine.

On your questions:

  1. In this repo, so it moves with the CLI and the README's install table.
  2. One passthrough um tool with an args array, rather than ten. um --help and um <group> --help already document the groups, and one tool costs less context in every session.
  3. Tools only for the first PR. Leave the /mod-game command and ctx.skill.transform out for now. Skills already load through skills.paths, and a smaller first diff is easier to review.
  4. Keep the check you described that asserts the group list against GROUPS in um/cli.py. CONTRIBUTING asks for a test with tool changes, and that one would catch the next missed group.
<!-- gh-comment-id:6094550611 --> @rehan-remade commented on GitHub (Oct 10, 2026): Thanks for asking first, and for the careful write-up. Yes, please open it. Every other agent already has a real install path, so OpenCode should too, and a tracked `plugins/opencode/` is fine. On your questions: 1. **In this repo**, so it moves with the CLI and the README's install table. 2. **One passthrough `um` tool** with an `args` array, rather than ten. `um --help` and `um <group> --help` already document the groups, and one tool costs less context in every session. 3. **Tools only for the first PR.** Leave the `/mod-game` command and `ctx.skill.transform` out for now. Skills already load through `skills.paths`, and a smaller first diff is easier to review. 4. **Keep the check** you described that asserts the group list against `GROUPS` in `um/cli.py`. CONTRIBUTING asks for a test with tool changes, and that one would catch the next missed group.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rehan-remade/universal-modder#34
No description provided.