fix(opencode): register /impeccable slash command via commands/ bridge - #483
fix(opencode): register /impeccable slash command via commands/ bridge#4834nibhal wants to merge 17 commits into
Conversation
…ills AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
… guards AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
…rtcut AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
…titution row AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
Greptile SummaryThis change adds OpenCode command bridges across generation, installation, synchronization, and pinning. A real mixed-provider installation was exercised with Claude already present and OpenCode explicitly selected: the CLI reported success and installed the OpenCode skill, but did not create Confidence Score: 4/5Not safe to merge until mixed OpenCode installs also copy the command bridge. The reproduced installation path reports a successful OpenCode installation even though it omits the command file required for Files Needing Attention: cli/bin/commands/skills.mjs
What T-Rex did
|
…rent installs isUpToDate now treats bundle-shipped command artifacts (e.g. .opencode/commands/impeccable.md) as part of freshness, and the reinstall refresh path copies provider commands alongside skills and agents. Existing OpenCode installs (pbakaus#474) get /impeccable restored by a plain reinstall or update instead of staying bridge-less until --force. Pinned and user commands never affect freshness and are never touched. AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
impeccable link only symlinked skills, and linked providers are deliberately excluded from install/update refreshes (overwriting a symlink would destroy the link), so linked OpenCode installs had no path to /impeccable at all. link now copies the command bridge from the source bundle alongside the skill symlinks; it no-ops when the checkout has no built commands. Also adds user-scope coverage for the commands-aware freshness check (OPENCODE_CONFIG_DIR resolution). AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
Scope-less runs (skills check, or update from the home dir) match global OpenCode skills via HOME_SKILLS_DIR_OVERRIDES, but the commands-aware freshness check resolved the bridge via providerCommandsDir, which without an explicit scope always points at <root>/.opencode/commands. Global installs were perpetually stale: check falsely reported updates and update refreshed every run. The commands dir is a sibling of the matched skills dir in every layout copyProviderCommands writes, so derive it from localSkillsDir. The regression test runs through the CLI subprocess because Bun caches os.homedir() and cannot observe a runtime HOME override. AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
syncRootOutputs mirrored skills, agents, and hooks but not commands/, so the post-merge release sync would never commit .opencode/commands/impeccable.md and direct GitHub / npx-skills / submodule installs would keep shipping OpenCode without the slash command bridge. syncRootCommands mirrors generated command files per entry, preserving repo-local and pinned commands at the destination. Verified end to end: bun run build:release logs the sync and lands the bridge at the repo root (generated churn intentionally reverted per the source-first policy). AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
733cb4f to
78edf1e
Compare
|
@greptile-apps Both findings reproduce only against the OpenCode 1.3.10 runtime in the T-Rex sandbox, which predates OpenCode's skills and custom-commands support entirely. The captured run is self-defeating evidence: the server returned no installed skill from Verified against the current OpenCode release (1.18.10,
The emitted frontmatter ( Drafted with AI assistance (OpenCode + MiniMax M3), reviewed by me. |
pin/unpin only recognised project-local OpenCode installs, so a global install (OPENCODE_CONFIG_DIR / XDG / ~/.config/opencode, the pbakaus#406 layout) made pin exit 0 with 'No harness directories' and no pinned command. The OpenCode branch now resolves both scopes — project commands dir and user config commands dir, deduped — with the same marker guards, and the no-harness early return only fires when neither scope has an install. The user-scope precedence helper mirrors the CLI's opencodeGlobalConfigDir; duplicated because pin.mjs ships inside the installed skill. Tests sanitize OPENCODE_CONFIG_DIR/XDG_CONFIG_HOME so runs never touch the developer's real global config. AI-Assisted: OpenCode + MiniMax M3, reviewed by 4nibhal
|
Would be great if you could resolve conflicts. Also, I'm a bit unsure about this one...feels like a workaround with a lot of code to maintain specifically for a temporary issue with OpenCode. Have you validated that the command can reference and load other files in the skill folder etc? |
Resolve the single conflict in scripts/test-suites.mjs by keeping main's suite structure (plugin-e2e in DEFAULT_SUITES, plus the validate-plugin-manifest and release test entries) and re-adding this branch's three bridge tests to the bun runner list. Drafted with AI assistance (OpenCode + k3-256k); reviewed and approved by the human author.
- factory.js: the bridge body no longer re-implements the skill Setup flow; it delegates to OpenCode's skill tool in one line, and the '(slash command bridge)' suffix is gone from the description the TUI menu displays - skills.mjs: drop the identity PROVIDER_CONFIG_DIRS table; the fallback already computed the same result for every provider - tests: pin the exact delegating body and a quoting-agnostic description assertion Drafted with AI assistance (OpenCode + k3-256k); reviewed and approved by the human author.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 26ae983. Configure here.
|
Thanks for the review — fair point that the first version read like a workaround. I dug into what OpenCode actually does today (verified against a local OpenCode 1.18.10 install, not assumed) and reworked the PR around it. Facts first, then the changes in impeccable. What OpenCode already does (verified)
So on OpenCode today: Why impeccable ships a command file (and why this body)One detail from the same OpenCode thread is worth noting: rekram1-node also said "it's BAD that skill invocations reuse command logic and dont invoke the skill tool — we need to update that." The revised bridge in this PR does exactly what OpenCode's collaborator described — the entire body is one line: The file earns its place in impeccable's OpenCode install for three reasons, and only the first is contingent on OpenCode's current design:
What changed in this revision of the PR
Deliberately kept: the user-scope install migration, freshness check, and reinstall/update backfill in impeccable's CLI — those manage the installed artifact's lifecycle and earn their keep independently of OpenCode's menu gap. Validation: Drafted with AI assistance (OpenCode + k3-256k); reviewed and approved by the human author. |
findOpencodeCommandsDirs() only enumerated a commands dir while the matching skills/impeccable dir existed, so unpin after uninstalling the skill left the marker-bearing impeccable-<cmd>.md behind and wrongly reported that no pinned shortcut was found. unpin now enumerates both scopes with forCleanup: removal stays safe because removePinnedOpencodeCommand is marker-guarded, and pin keeps the skill-presence gate so pins are never written where the skill is not installed. Adds regression tests for project-scope and user-scope removal plus the non-pinned-command guard. Flagged by greptile-apps[bot] on pbakaus#483. Drafted with AI assistance (OpenCode + k3-256k); reviewed and approved by the human author.
The pinned OpenCode command body resolved reference/<cmd>.md without a base-dir prefix, leaving the lookup ambiguous for agents that do not infer it from the skill tool response. The path now matches the explicit <skill-base-dir> form already used for context.mjs. Flagged by cursor[bot] on pbakaus#483. Drafted with AI assistance (OpenCode + k3-256k); reviewed and approved by the human author.
The pinned command wrote <skill-base-dir> without ever defining it, so a weaker agent could take the placeholder literally (the concern behind the earlier review finding). The body now states that the placeholder is the base directory the skill tool reports and must be substituted with the real absolute path. Also corrects the comment above generatePinnedOpencodeCommand, which claimed the body routes through the parent /impeccable bridge when it actually loads the skill and the sub-command reference directly, and swaps an em dash in the fallback description string for house-style punctuation, since that string is written into user-facing command files. AI-assisted (Claude Code). Co-Authored-By: Claude <noreply@anthropic.com>
|
Want your agent to iterate on Greptile's feedback? Start a greploop in Codex and it will work through the open comments and keep going until this PR reviews clean. |
|
Thanks for the thorough rework here. The one-line bridge that delegates to the skill via OpenCode's skill tool is exactly the right shape, and your OpenCode citations checked out against their docs: To save you a round trip, we pushed two commits to your branch. The first resolves the merge conflict with main (just the import lines in One open question before merge: with (Posted with AI assistance via Claude Code.) |
|
Confirmed on OpenCode 1.18.11: the Setup interview does reach the user with In a real TUI session of Why it works: the TUI surfaces AI-assisted (OpenCode + deepseek-v4-flash). |

Before opening
This repo is issue-first for outside contributions. If you are not
pbakausorabdulwahabone, please link the issue where a maintainer approved or requested this PR. Unsolicited PRs may be closed without review.pbakausorabdulwahaboneSummary
npx impeccable install --providers=opencodeinstalls the skill but never registers a slash command: OpenCode (1.18.10) silently ignores the Claude-styleSKILL.mdfrontmatter extensions (user-invocable,argument-hint, etc.) and only surfaces.opencode/commands/*.mdin the TUI slash menu. The README, the site, and the skill's ownSetupsection all promise/impeccable init, so OpenCode users hit a silent dead end (repro in #474).This PR makes the install emit a parallel
commands/artifact for OpenCode:scripts/lib/transformers/factory.js): emitsdist/opencode/.opencode/commands/impeccable.md— a strict-schema bridge command (agent: build,subtask: true) that loads the skill via the skill tool, runs the mandatorycontext.mjssetup, and routes$ARGUMENTSto sub-commands. The body discovers<skill-base-dir>from the skill tool response, so project, global, and customOPENCODE_CONFIG_DIRinstalls all work (respects [Bug] Global OpenCode install uses the wrong directory #406).cli/bin/commands/skills.mjs): newcopyProviderCommandsstep installscommands/into.opencode/for project and global scopes, mirroring Install global OpenCode skills into the config dir OpenCode reads #417's symlink / realpath / dotfiles migration guards.skill/scripts/pin.mjs):impeccable pin <cmd>now writes.opencode/commands/impeccable-<cmd>.mdfor OpenCode instead of a skill-only shortcut.docs/HARNESSES.md): corrects the OpenCode frontmatter row (OpenCode only honours the Agent Skills spec subset) and adds the commands substitution row.scripts/test-suites.mjs): registers the two new test files in the core suite.Forward-compatible with a future OpenCode skill→command auto-bridge (anomalyco/opencode#35341, anomalyco/opencode#34410): explicit commands outrank the bridge, and nothing here depends on the bridge staying absent.
Closes #474
Type of change
Checklist
source/bun run buildran successfullybun testpassesValidation
bun run build✓ — 16 providers assembled, prose/version validators green.bun run test✓ — 415 pass (bun) + 326 pass (node--test), 0 fail, 8 skip (pre-existing).git init+install --providers=opencode --scope=project):.opencode/commands/impeccable.mdcreated with correct frontmatter; skill tree intact./impeccableappears in slash autocomplete;--command impeccableruns end-to-end.Generated provider output
Intentionally omitted.
bun run buildwas used for validation only; tracked root harness folders andplugin/are untouched per the source-first policy —.github/workflows/sync-generated-output.ymlregenerates them post-merge.AI assistance disclosure
Drafted and implemented with AI assistance (OpenCode + MiniMax M3), reviewed by me before opening. All commits carry an
AI-Assistedtrailer.Note
Medium Risk
Changes install/update/link file layout and freshness checks across scopes, but scope is limited to OpenCode command artifacts with migration guards and broad test coverage.
Overview
OpenCode ignores Claude-style
SKILL.mdfrontmatter for slash menus, so installs could ship the skill without a usable/impeccableentry (#474). This PR adds an OpenCodecommands/bridge end-to-end.The build now emits
.opencode/commands/impeccable.md(OpenCode-only frontmatter:description,agent: build,subtask: true) that delegates via the skill tool and$ARGUMENTS.syncRootCommandsmirrors those files into tracked harness folders on release sync so GitHub/submodule installs get the bridge too.The CLI gains
copyProviderCommands, wired into install, update, and link, with the same global config dir precedence and legacy~/.opencode/commandscleanup as skills (#417).isUpToDatetreats missing or drifted bundle command files as stale so reinstall/update backfills the bridge without falsely reporting “up to date.”pin.mjswritesimpeccable-<cmd>.mdcommand shortcuts for OpenCode (project and user scope) instead of useless.opencode/skills/<cmd>pins.docs/HARNESSES.mddocuments OpenCode’s real frontmatter and command substitution.Reviewed by Cursor Bugbot for commit 85f307d. Bugbot is set up for automated code reviews on this repo. Configure here.