Skip to content

feat: add Claude Code field compatibility to skills system#43

Merged
marcusrbrown merged 1 commit into
mainfrom
gray-arrogant-earthworm
Feb 1, 2026
Merged

feat: add Claude Code field compatibility to skills system#43
marcusrbrown merged 1 commit into
mainfrom
gray-arrogant-earthworm

Conversation

@marcusrbrown
Copy link
Copy Markdown
Owner

Extends skill frontmatter extraction to support Claude Code-specific fields alongside OpenCode SDK fields, enabling skills-as-commands functionality.

  • Add support for Claude Code converted fields in skill frontmatter:

    • disable-model-invocation: hide skills from tool list
    • user-invocable: control command exposure (skills-as-commands)
    • context: fork → subtask mapping for forked execution
    • agent/model routing for command delegation
    • argument-hint for CLI/autocomplete hints
    • allowed-tools for future permission system
  • Update skill-tool to filter skills based on disableModelInvocation flag

  • Add permission request and metadata emission in skill tool execution

  • Enhance config-handler to route agent/model/subtask fields when loading
    skills as commands

  • Move formatSkillsXml from skills.ts to skill-tool.ts (better cohesion)

  • Add validation helpers for extracting typed frontmatter fields

  • Document CC-to-OC field compatibility in CONVERSION-GUIDE.md

This enables bundled skills to preserve Claude Code semantics while working in OpenCode's native environment without breaking changes.

Extends skill frontmatter extraction to support Claude Code-specific fields
alongside OpenCode SDK fields, enabling skills-as-commands functionality.

- Add support for Claude Code converted fields in skill frontmatter:
  * disable-model-invocation: hide skills from tool list
  * user-invocable: control command exposure (skills-as-commands)
  * context: fork → subtask mapping for forked execution
  * agent/model routing for command delegation
  * argument-hint for CLI/autocomplete hints
  * allowed-tools for future permission system

- Update skill-tool to filter skills based on disableModelInvocation flag
- Add permission request and metadata emission in skill tool execution
- Enhance config-handler to route agent/model/subtask fields when loading
  skills as commands
- Move formatSkillsXml from skills.ts to skill-tool.ts (better cohesion)
- Add validation helpers for extracting typed frontmatter fields
- Document CC-to-OC field compatibility in CONVERSION-GUIDE.md

This enables bundled skills to preserve Claude Code semantics while
working in OpenCode's native environment without breaking changes.
@marcusrbrown marcusrbrown enabled auto-merge (squash) February 1, 2026 09:27
@marcusrbrown marcusrbrown self-assigned this Feb 1, 2026
@marcusrbrown marcusrbrown merged commit 5d892f3 into main Feb 1, 2026
8 checks passed
@marcusrbrown marcusrbrown deleted the gray-arrogant-earthworm branch February 1, 2026 09:29
marcusrbrown added a commit that referenced this pull request May 11, 2026
… ReDoS

The non-greedy regex /<SYSTEMATIC_WORKFLOWS>[\s\S]*?<\/SYSTEMATIC_WORKFLOWS>/
was flagged by CodeQL as polynomial-time on uncontrolled input — when the
opening tag repeats and the closing tag is absent, the engine backtracks
through every prefix. With per-load registration now letting any plugin
source contribute system prompt fragments, this regex sees content the
plugin itself didn't author.

Replaces the regex with a small indexOf/slice helper. Fixed literal
delimiters never needed regex; the linear scan is provably immune to ReDoS
and unchanged in behavior for the existing seven marker-replacement tests.
Adds a regression test that runs the helper against 10000 repeated opening
markers with no closing tag and asserts completion in well under 1s.

Closes CodeQL alerts #42 and #43.
marcusrbrown added a commit that referenced this pull request May 11, 2026
… bootstrap idempotency (#352)

* refactor(plugin): independent per-load registration with marker-based bootstrap idempotency

Each call to SystematicPlugin now runs initializePlugin independently and
returns its own hooks surface. With multiple OpenCode plugin sources
configured (project + user config), each source gets its own systematic_skill
tool, its own config handler, and its own chat.system.transform closure.
hasLoggedInit moves into per-init closure state, so the process emits N init
log lines for N registrations — honest signal that init ran N times.

Bootstrap content idempotency is now enforced at injection time, not init
time. applyBootstrapContent walks output.system for any prior
<SYSTEMATIC_WORKFLOWS>...</SYSTEMATIC_WORKFLOWS> block (non-greedy regex) and
replaces it in-place; missing-block falls through to append. Under OpenCode's
verified FIFO hook iteration, the last transform to run owns the final block
— most-recently-registered plugin wins, which matches the project-after-user
load order developers expect.

This reverts the plugInOnce singleton from PR #335, which turned out to be
over-correction. OpenCode registers tools per-source even with a shared hooks
reference, so the singleton's init-dedup had no visible effect on the TUI
tool catalog — what it did do in dev setups was silently collapse all loads
onto whichever ran first, shadowing later sources.

Also removes _resetPluginSingleton from the integration test setup; the
singleton itself is deleted in a follow-up commit.

12 new behavior tests cover marker-replacement in every slot, non-greedy
boundary, multi-block edge cases, per-invocation distinct references, and
the cross-registration integration scenario.

* refactor(plugin): delete plugin-singleton module after factory revert

The plugInOnce abstraction and its test file are no longer reachable —
src/index.ts stopped importing them in the prior commit, and the consumer
test files (plugin.test.ts and opencode.test.ts) dropped the
_resetPluginSingleton reset calls.

Deletes 227 lines of now-dead infrastructure: the singleton helper, its
five test cases, and the module-level exports. The architectural rationale
lives in docs/brainstorms/2026-05-10-multi-load-plugin-registration-requirements.md
and the implementation plan at docs/plans/2026-05-10-002-refactor-multi-load-plugin-registration-plan.md.

* docs: sync AGENTS hierarchy and PR #335 solution after singleton removal

Updates module count in AGENTS.md and src/lib/AGENTS.md from 16/14 to 15
(post-deletion of plugin-singleton.ts). Appends a 2026-05-10 follow-up
section to the PR #335 solution doc noting the singleton was removed and
documenting marker-based idempotency as the current correctness contract.

Also commits the implementation plan with all four units marked complete.
The plan was untracked locally during execution per project convention;
landing it here gives the architectural inversion a visible paper trail.

* fix(plugin): replace bootstrap marker regex with linear scan to close ReDoS

The non-greedy regex /<SYSTEMATIC_WORKFLOWS>[\s\S]*?<\/SYSTEMATIC_WORKFLOWS>/
was flagged by CodeQL as polynomial-time on uncontrolled input — when the
opening tag repeats and the closing tag is absent, the engine backtracks
through every prefix. With per-load registration now letting any plugin
source contribute system prompt fragments, this regex sees content the
plugin itself didn't author.

Replaces the regex with a small indexOf/slice helper. Fixed literal
delimiters never needed regex; the linear scan is provably immune to ReDoS
and unchanged in behavior for the existing seven marker-replacement tests.
Adds a regression test that runs the helper against 10000 repeated opening
markers with no closing tag and asserts completion in well under 1s.

Closes CodeQL alerts #42 and #43.
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