fix: Claude Code skills discoverable for the composer $ picker#4414
Conversation
The $ skill selector only ever worked for Codex because the Codex app-server is the sole source that populated the provider snapshot's skills array; the Claude provider always shipped an empty list, so the composer showed "No skills found". Scan the Claude config dir (CLAUDE_CONFIG_DIR or ~/.claude) and the workspace .claude/skills for SKILL.md entries, parse their YAML frontmatter for name/description, and surface them as ServerProviderSkill entries on the Claude provider snapshot. Project skills win name collisions, matching Claude Code's most-specific-wins resolution, and discovery is best-effort so malformed skills never degrade the snapshot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughClaude provider checks now discover skills from user and project filesystem roots, parse their metadata, resolve collisions, and include the results in provider drafts. Filesystem access and the YAML parser dependency are wired into the relevant effects. ChangesClaude Skills Provider Flow
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant checkClaudeProviderStatus
participant discoverClaudeSkills
participant FileSystem
participant ServerProviderDraft
checkClaudeProviderStatus->>discoverClaudeSkills: pass claudeSettings and cwd
discoverClaudeSkills->>FileSystem: read skill roots and SKILL.md files
FileSystem-->>discoverClaudeSkills: skill metadata
discoverClaudeSkills-->>checkClaudeProviderStatus: sorted skills
checkClaudeProviderStatus->>ServerProviderDraft: include skills in provider draft
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
ApprovabilityVerdict: Needs human review This PR introduces new functionality (skill discovery for the composer picker) rather than a simple fix. While well-tested and self-contained, new user-facing capabilities that change what users see in the UI warrant human review. You can customize Macroscope's approvability policy. Learn more. |
Skill discovery now matches the config-dir precedence the spawned CLI sees: instance homePath (which makeClaudeEnvironment exports as CLAUDE_CONFIG_DIR), then a CLAUDE_CONFIG_DIR already present in the process environment, then ~/.claude. Previously an exported CLAUDE_CONFIG_DIR was ignored, so the $ picker could list skills from a different directory than the Claude runtime would load. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/server/src/provider/Drivers/ClaudeSkills.ts`:
- Around line 27-53: The parseSkillFrontmatter flow must distinguish absent
frontmatter from malformed YAML: return an explicit parse-validity state,
preserve valid metadata, and have the discovery logic skip malformed entries
before applying the directory-name fallback. Update
apps/server/src/provider/Drivers/ClaudeSkills.ts lines 27-53 and 104-105
accordingly; update apps/server/src/provider/Drivers/ClaudeSkills.test.ts lines
96-119 so only the skill without frontmatter is discovered.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7a51c3b6-70f9-4d4d-bce6-032b4b4a23a3
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (5)
apps/server/package.jsonapps/server/src/provider/Drivers/ClaudeDriver.tsapps/server/src/provider/Drivers/ClaudeSkills.test.tsapps/server/src/provider/Drivers/ClaudeSkills.tsapps/server/src/provider/Layers/ClaudeProvider.ts
A SKILL.md whose frontmatter fails to parse won't load in Claude Code, so surfacing it in the picker under its directory name advertised a skill the runtime can't run. Distinguish missing frontmatter (directory name fallback still applies) from malformed frontmatter (entry skipped). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high 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 4e605f8. Configure here.
Env vars reach the spawned CLI unexpanded, so a literal `~` in CLAUDE_CONFIG_DIR stays literal for the runtime. Expanding it during skill discovery scanned a different directory than the CLI would use; resolve the value verbatim instead for parity. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The spawned CLI resolves a relative CLAUDE_CONFIG_DIR against its own cwd (the workspace), while discovery resolved it against the server process's cwd — scanning a different skills directory. Resolve against the workspace cwd for parity. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
yes! please merge! |
2 upstream commits (pingdotgg#4414, pingdotgg#4416). No conflicts.

Problem
The composer's
$skill selector only worked for Codex. The Codex driver populates the provider snapshot'sskillsarray via the app-server'sskills/listRPC, but the Claude provider never setskillsat all, sobuildServerProviderdefaulted it to[]and the composer always showed "No skills found. Try / to browse provider commands."Fix
Add filesystem skill discovery to the Claude provider, mirroring what the Codex app-server does for Codex:
ClaudeSkills.ts(new): scans<config dir>/skills(user scope —CLAUDE_CONFIG_DIRwhen the instance setshomePath, else~/.claude) and<cwd>/.claude/skills(project scope) for<skill-dir>/SKILL.md, parses YAML frontmatter forname/description, and maps entries intoServerProviderSkill[]. Project skills win name collisions (Claude Code's most-specific-wins resolution). Discovery is best-effort: unreadable roots, stray files, and malformed frontmatter are skipped rather than failing the snapshot; a frontmatter-less skill falls back to its directory name.ClaudeProvider.ts:checkClaudeProviderStatusnow accepts the workspacecwd, runs discovery, and attachesskillsto the ready/unverified-auth snapshots.ClaudeDriver.ts: passesServerConfig.cwdand providesFileSystemto the status check.The Agent SDK init handshake surfaces skills only as slash commands without filesystem paths, so scanning the same directories Claude Code loads from is the practical way to get paths + scopes for the picker.
No client changes needed — the web/mobile composers already render whatever
selectedProviderStatus.skillscontains.Testing
ClaudeSkills.test.tscovering user+project discovery, collision precedence, malformed-frontmatter/stray-file tolerance, and missing roots (4 tests).ProviderRegistry/ Claude probe suites pass (48 tests).typecheck,lint,fmtclean.🤖 Generated with Claude Code
Note
Low Risk
Read-only local filesystem discovery during provider status checks; failures are swallowed so snapshots stay available.
Overview
Claude provider snapshots now include filesystem-discovered skills so the composer
$picker can list them (previously only Codex populatedskills).Adds
discoverClaudeSkills, which scans user<configDir>/skillsand project<cwd>/.claude/skillsforSKILL.mdfiles, parses YAML frontmatter via the newyamldependency, and returnsServerProviderSkillentries with scope and paths. Config dir resolution matches the spawned CLI (homePath→CLAUDE_CONFIG_DIR→~/.claude, with relative env paths resolved against workspacecwd). Project skills override user skills on name collisions; bad roots, missing files, and invalid frontmatter are skipped without failing the status check.checkClaudeProviderStatustakes workspacecwd, runs discovery, and passesskillsintobuildServerProviderfor both ready and auth-unknown paths.ClaudeDriversuppliesFileSystemand passescwdinto the status check.Reviewed by Cursor Bugbot for commit 7be852b. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Make Claude Code skills discoverable via the composer
$pickerdiscoverClaudeSkillsinClaudeSkills.tsto enumerate skills from two roots:<configDir>/skills(user scope) and<cwd>/.claude/skills(project scope), parsing YAML frontmatter from eachSKILL.mdfile.config.homePath, thenCLAUDE_CONFIG_DIRenv var (resolved relative to workspace cwd), then~/.claude.checkClaudeProviderStatusinClaudeProvider.tsnow accepts an optionalcwdand requiresFileSystem, returning discovered skills in theServerProviderDraft.Macroscope summarized 7be852b.
Summary by CodeRabbit
New Features
$picker.SKILL.mdmetadata.Bug Fixes