Skip to content

feat: support local command files and OpenCode skill roots - #1911

Merged
limityan merged 2 commits into
GCWing:mainfrom
limityan:yanzhn/external-command-skill-compat
Jul 31, 2026
Merged

feat: support local command files and OpenCode skill roots#1911
limityan merged 2 commits into
GCWing:mainfrom
limityan:yanzhn/external-command-skill-compat

Conversation

@limityan

@limityan limityan commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Support safe workspace-relative UTF-8 @file references in imported OpenCode and Claude Code Prompt Commands.
  • Discover local OpenCode Skill roots from both V1 skills.paths and the current skills: string[] configuration forms.
  • Feed reviewed contributions through Product Assembly into the existing command coordinator and Skill Registry owners.
  • Consolidate bounded filesystem and workspace-text validation primitives so command and Skill loading share one security policy.

Recommended design and competitor comparison

The design was checked against the local OpenCode source at 3f239b3834e7ef30a454af6830053d2e82af009f, plus the local Codex and Claude Code implementations.

Ecosystem Useful behavior Deliberately not copied BitFun decision
OpenCode Additive config documents, configured local Skill roots, deterministic source ordering URL Skill fetching and implicit arbitrary runtime execution Parse both supported local config shapes in the OpenCode adapter, then project bounded facts through Product Assembly into the existing Skill Registry
Codex Extra roots feed the normal Skill loader instead of creating a second execution system A new Codex-specific importer when existing standard roots already cover it Reuse the single Registry owner and leave current Codex discovery unchanged
Claude Code Literal local file context in commands Home/absolute/dynamic references and broader ambient filesystem access Support only literal workspace-relative text files under the same bounded expansion contract as OpenCode

The recommended owner chain is:

ecosystem adapter -> ExternalSourceCoordinator/Product Assembly review -> existing Prompt Command or Skill Registry owner -> shared bounded filesystem services

This keeps protocol/config parsing in adapters, product policy in assembly, and loading/execution in existing owners. It does not introduce a generic extension runtime or a parallel Skill loader.

Behavior and safety boundaries

Prompt Command files

  • Extract references only from the original command template; references introduced through arguments are not rescanned.
  • Accept regular workspace files only; reject absolute, home-relative, parent-traversal, URL, dynamic, shell, symlink, and reparse-point paths.
  • Preserve first-seen ordering and deduplicate repeated references.
  • Read files atomically and render deterministic Markdown sections with collision-safe fences.
  • Enforce 8 references, 64 KiB per file, 128 KiB total file content, and 1 MiB final expansion limits.
  • Preflight repeated $ARGUMENTS expansion before allocating the rendered prompt.
  • Keep the existing remote-workspace policy unchanged; relative paths are never interpreted against an unrelated local working directory.

OpenCode Skill roots

  • Accept V1 object-form skills.paths and current array-form skills from additive OpenCode configuration documents.
  • Reject a malformed array as a whole field without hiding valid command contributions from the same document.
  • Resolve project paths inside the workspace; user paths may resolve inside the workspace or user home.
  • Never fetch skills.urls or HTTP(S) entries.
  • Preserve OpenCode-compatible config/source ordering while retaining the existing BitFun, Claude, Codex, and Cursor precedence bands.
  • Enforce 64 roots, depth 16, 4096 entries, 2048 directories, 512 SKILL.md candidates per root, 256 KiB per SKILL.md, and 64 KiB per optional policy file.
  • Revalidate root identity and canonical source slots at load time; reject child and root symlink/reparse substitutions.

The remaining same-user validate-to-open filesystem race is bounded by the read limits and documented in the design. Closing it completely would require platform-specific handle-relative filesystem APIs and is intentionally outside this compatibility PR.

Architecture impact

  • The OpenCode adapter emits ecosystem facts only.
  • bitfun-core/external_sources remains the only composition owner that imports and constructs the adapter.
  • The Skill Registry consumes an internal, reviewed LocalConfiguredSkillRootContribution; it does not import the adapter.
  • Public command results remain unchanged; prepared file references are an internal capability contract.
  • Boundary and public-API governance rules were updated and pass.

Verification

  • OpenCode Prompt Command tests: 24 passed.
  • Claude Code Prompt Command tests: 14 passed.
  • OpenCode configured Skill root adapter tests: 6 passed.
  • Configured Skill Registry tests: 9 passed.
  • Product-domain external-source contract tests: 42 passed.
  • External-source coordinator tests: 8 passed.
  • Shared workspace-text tests: 4 passed.
  • Shared Markdown owner tests: 10 passed.
  • Static hook support tests: 19 passed.
  • Core finalizer and composition-focused tests passed.
  • node --test scripts/check-core-boundaries.test.mjs passed (16/16).
  • node scripts/check-core-boundaries.mjs passed.
  • pnpm run check:repo-hygiene passed.
  • pnpm run fmt:rs passed.
  • git diff --check gcwing/main...HEAD passed.
  • cargo check --workspace --exclude bitfun-desktop passed with pre-existing CLI warnings only.

cargo check --workspace reached the desktop build script and stopped because the generated src/mobile-web/dist resource is absent in this worktree. No Rust compilation error was reported before that environment prerequisite.

Independent adversarial review

The combined change received an isolated final review after implementation. Issues found around source precedence, overlapping roots, malformed arrays, output-size bypasses, adapter/Registry ownership, unbounded reads, policy-file traversal, and whole-root replacement were corrected. The final review found no remaining P0 or P1 issue.

Non-goals

  • No Plugin Host Runtime changes.
  • No NodeScriptToolRuntime or JavaScript/TypeScript tool execution.
  • No OpenCode URL Skill loading.
  • No shell, dynamic, absolute, home-relative, or out-of-workspace command file references.
  • No new Codex importer, extension management UI, marketplace, installer, activation, update, permission, or health-state model.

Change size

28 files changed, 2,349 insertions and 252 deletions (2,601 lines of churn), within the requested 8k-line limit.

@limityan
limityan force-pushed the yanzhn/external-command-skill-compat branch from f79a5a7 to 5233394 Compare July 30, 2026 18:46
@limityan
limityan force-pushed the yanzhn/external-command-skill-compat branch from 5233394 to 2166d5c Compare July 30, 2026 23:42
@limityan
limityan marked this pull request as ready for review July 31, 2026 00:25
@limityan
limityan merged commit dee8364 into GCWing:main Jul 31, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant