feat: auto-discover skills/commands from Claude Code, Codex, and Gemini configs#405
feat: auto-discover skills/commands from Claude Code, Codex, and Gemini configs#405
Conversation
…ni configs Extends the MCP auto-discovery pattern to skills and commands. Discovers: - Claude Code commands (.claude/commands/*.md) - Codex CLI skills (.codex/skills/**/SKILL.md) - Gemini CLI skills (.gemini/skills/**/SKILL.md) - Gemini CLI commands (.gemini/commands/*.toml) Discovered skills are additive — existing skills always take precedence. Controlled by experimental.auto_skill_discovery config (default: true). Also fixes skill-backed commands to expose $ARGUMENTS hints. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review.
Tip: disable this comment in your organization's Code Review settings.
📝 WalkthroughWalkthroughThis change introduces auto-discovery of external AI tool skills from Claude Code, Codex, and Gemini configurations by adding discovery logic, configuration flags, and comprehensive test coverage. The feature scans well-known directories, parses multiple file formats (markdown with frontmatter, TOML), deduplicates by skill name, and conditionally integrates discovered skills into the loading pipeline. Changes
Sequence DiagramsequenceDiagram
participant Instance
participant Config
participant SkillLoader as Skill Loader
participant Discover as discover-external
participant FileSystem as File System
participant ParsedSkills as Skills Map
SkillLoader->>Config: Check auto_skill_discovery enabled<br/>& flag not set
Config-->>SkillLoader: true/false
alt Discovery Enabled
SkillLoader->>Discover: discoverExternalSkills(worktree)
Discover->>FileSystem: Walk home & project dirs<br/>to find .claude, .codex, .gemini
FileSystem-->>Discover: Directory listing
Discover->>FileSystem: Glob-match files<br/>(*.md, *.toml patterns)
FileSystem-->>Discover: File list
Discover->>Discover: Parse markdown frontmatter<br/>or TOML format
Discover->>Discover: Extract skill metadata<br/>(name, description, prompt)
Discover->>Discover: Deduplicate by skill.name<br/>(first discovered wins)
Discover-->>SkillLoader: { skills, sources }
SkillLoader->>ParsedSkills: Merge new skills<br/>(skip if name exists)
ParsedSkills-->>SkillLoader: Updated skills map
SkillLoader->>Discover: setSkillDiscoveryResult(added, sources)
else Discovery Disabled
SkillLoader->>ParsedSkills: Load only builtin skills
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/opencode/src/config/config.ts (1)
1546-1547:⚠️ Potential issue | 🟡 MinorRemove orphaned statements at end of file.
These two standalone
Filesystem.writeexpressions appear to be leftover artifacts from a refactoring or merge. They have no effect and should be removed.🐛 Proposed fix
-Filesystem.write -Filesystem.write🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/src/config/config.ts` around lines 1546 - 1547, Remove the two orphaned standalone expressions "Filesystem.write" found at the end of the file; these are no-op remnants and should be deleted so only real function definitions/exports remain (search for the symbol "Filesystem.write" near the file tail and remove those two lines).
🧹 Nitpick comments (1)
packages/opencode/test/skill/discover-external.test.ts (1)
8-16: Consider using thetmpdirfixture for consistency.The test uses manual
mkdtemp/rmwithbeforeEach/afterEachinstead of the project'stmpdirfixture. While functional, usingtmpdirfromfixture/fixture.tswithawait usingsyntax would align with project conventions and provide automatic cleanup. As per coding guidelines, use thetmpdirfunction fromfixture/fixture.tsto create temporary directories for tests with automatic cleanup.♻️ Example pattern using tmpdir
import { tmpdir } from "../fixture/fixture" describe("discoverExternalSkills", () => { test("discovers Claude Code command with frontmatter", async () => { await using tmp = await tmpdir({ init: async (dir) => { await mkdir(path.join(dir, ".claude", "commands"), { recursive: true }) await writeFile( path.join(dir, ".claude", "commands", "review.md"), `---\nname: review\ndescription: Review the code changes\n---\n\nPlease review the following code changes: $ARGUMENTS\n`, ) }, }) const { skills } = await Instance.provide({ directory: tmp.path, fn: () => discoverExternalSkills(tmp.path), }) // assertions... }) })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/test/skill/discover-external.test.ts` around lines 8 - 16, Replace the manual mkdtemp/rm setup in the test with the project's tmpdir fixture: import tmpdir from fixture/fixture.ts, remove beforeEach/afterEach and tempDir variable, and use "await using tmp = await tmpdir({ init: async (dir) => { ... } })" inside the test to create the directory and seed files; then call discoverExternalSkills(tmp.path) (or pass tmp.path into Instance.provide) so the fixture handles cleanup automatically.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@packages/opencode/src/config/config.ts`:
- Around line 1546-1547: Remove the two orphaned standalone expressions
"Filesystem.write" found at the end of the file; these are no-op remnants and
should be deleted so only real function definitions/exports remain (search for
the symbol "Filesystem.write" near the file tail and remove those two lines).
---
Nitpick comments:
In `@packages/opencode/test/skill/discover-external.test.ts`:
- Around line 8-16: Replace the manual mkdtemp/rm setup in the test with the
project's tmpdir fixture: import tmpdir from fixture/fixture.ts, remove
beforeEach/afterEach and tempDir variable, and use "await using tmp = await
tmpdir({ init: async (dir) => { ... } })" inside the test to create the
directory and seed files; then call discoverExternalSkills(tmp.path) (or pass
tmp.path into Instance.provide) so the fixture handles cleanup automatically.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1cc2ba19-9156-47a9-8323-9d6249fff3dd
📒 Files selected for processing (6)
packages/opencode/src/command/index.tspackages/opencode/src/config/config.tspackages/opencode/src/skill/discover-external.tspackages/opencode/src/skill/skill.tspackages/opencode/test/skill/discover-external.test.tspackages/opencode/test/tool/skill.test.ts
Summary
.claude/commands/*.md, Codex.codex/skills/**/SKILL.md, Gemini.gemini/skills/**/SKILL.mdand.gemini/commands/*.toml)experimental.auto_skill_discoveryconfig toggle (default:true)$ARGUMENTShints viahints(skill.content)Test plan
bun turbo typecheckpassestest/skill/discover-external.test.tspasstest/skill/skill.test.ts(13 tests) — no regressionstest/tool/skill.test.ts(5 tests) — no regressions~/.claude/commands/test-cmd.md→ verify/test-cmdappears~/.gemini/commands/deploy.toml→ verify/deploydiscoveredexperimental.auto_skill_discovery: false→ verify no discovery🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
auto_skill_discoveryto control this feature (enabled by default).Bug Fixes
Tests