name: t3-skill-catalog-workflow
description: Use when adding, changing, debugging, or reviewing how T3 Code discovers, lists, inserts, parses, or displays agent skills, especially .claude/skills, SKILL.md, // skill suggestions, useSkillSuggestions, skillCatalog, skillReferences, skill prompt references, skill chips, or configured skills for an agent. Trigger on skill catalog, skill suggestions, agent skills, configured skills, .claude/skills, SKILL.md, skill mention, skill reference, skill chip, skill picker, or double-slash skills in ChatView.
T3 Skill Catalog Workflow
Use this skill when the app is dealing with agent skills as selectable references or rendered chips.
The current product behavior is:
- skills are discovered from the active project or worktree
.claude/skillsdirectory - only top-level directories under
.claude/skillsare selectable skills - selecting a skill inserts
@<absolute path to SKILL.md> - composer and message display render that absolute path as a compact skill-name chip
- copied/sent text preserves the original absolute
@.../SKILL.mdreference
Keep those transport and display concerns separate.
Primary Files
Skill catalog and references:
apps/web/src/lib/skillCatalog.tsapps/web/src/lib/skillReactQuery.tsapps/web/src/lib/skillReferences.tsapps/web/src/lib/skillReferenceDisplay.ts
Composer integration:
apps/web/src/components/ChatView.tsxapps/web/src/components/chat/composerSuggestionItems.tsapps/web/src/components/chat/ComposerCommandMenu.tsxapps/web/src/components/ComposerPromptEditor.tsx
Display integration:
apps/web/src/components/chat/SkillReferenceChip.tsxapps/web/src/components/chat/SkillIcon.tsxapps/web/src/components/chat/MessagesTimeline.tsx
Workspace search path:
apps/web/src/lib/projectReactQuery.tspackages/contracts/src/project.tsapps/server/src/workspace/Services/WorkspaceEntries.tsapps/server/src/workspace/Layers/WorkspaceEntries.tsapps/server/src/wsServer.ts
Tests:
apps/web/src/lib/skillCatalog.test.tsapps/web/src/lib/skillReferences.test.tsapps/web/src/lib/skillReactQuery.test.tsapps/web/src/components/chat/composerSuggestionItems.test.ts- skill-related cases in
apps/web/src/components/ChatView.browser.tsx - skill-reference cases in
apps/web/src/components/chat/MessagesTimeline.test.tsx
Catalog Boundary
Use skillCatalog.ts as the domain boundary.
It owns:
- resolving catalog roots from
SkillCatalogContext - mapping raw
ProjectEntryrows intoSkillCatalogEntry - building prompt references
- parsing prompt references back into skill metadata
Do not make components construct .claude/skills paths directly. Do not make ChatView or message rendering infer skill roots.
When adding a new skill source, extend SkillCatalogRoot and resolveSkillCatalogRoots() first. Examples of future sources might include provider/user/global skills, but do not invent those sources unless the task needs them.
Suggestion Data Flow
Current // flow:
detectComposerTrigger()
-> kind: "skill"
-> useSkillSuggestions()
-> projectSkillEntriesQueryOptions()
-> projects.searchEntries({ cwd: <root>/.claude/skills, includeIgnored: true })
-> toSkillCatalogEntry()
-> buildSkillComposerItems()
-> ComposerCommandMenu
-> buildSkillPromptReference()
useSkillSuggestions() should be the normal browser-facing API for reusable skill lists. Components should not call projects.searchEntries directly for skills.
Root And Worktree Semantics
For active chat threads, pass both:
projectCwd: activeProject?.cwd ?? nullworktreePath: activeThread?.worktreePath ?? null
The active root is worktreePath ?? projectCwd.
This preserves current behavior for worktree threads: skill discovery follows the cwd where the agent is operating.
The provider field exists in SkillCatalogContext for future provider-specific behavior. Do not branch on provider until the server/product has a real source of truth.
Missing Directory Behavior
Missing .claude/skills is not an error in the UI.
skillReactQuery.ts intentionally treats ENOENT / missing-path errors as an empty result set. Preserve this behavior so projects without local skills do not show noisy errors.
Do not hide unrelated errors like permission denied or server failures; those should still surface through the query error path.
Prompt Reference Rules
Use buildSkillPromptReference(entry) to insert a selected skill.
The inserted prompt reference should be:
@/absolute/project/or/worktree/.claude/skills/<skill-name>/SKILL.md[space]
The [space] suffix represents the literal trailing space that is part of the selection UX. Keep replacement range handling in ChatView responsible for avoiding double spaces.
Do not change the transport format to //skill-name unless the provider/runtime contract changes. The absolute @.../SKILL.md form is what sent messages and copy behavior preserve today.
Display Rules
Use shared display helpers:
resolveSkillReferenceDisplay()for path -> display metadataSkillReferenceChipfor React renderingcreateSkillReferenceChipDomElement()for Lexical DOM rendering
skillReferences.ts still owns splitting user-visible message text around skill references. Keep parsing behavior compatible with:
- Unix paths
- Windows-style paths
- trailing punctuation after
SKILL.md - references wrapped in punctuation
Do not show the absolute .claude/skills/.../SKILL.md path in normal message or composer display. Do preserve it for copying and sending.
Server Search Considerations
Skill search reuses workspace search. That means it inherits:
- fuzzy ranking
- cache TTL behavior
- symlink indexing
includeIgnored: true- top-level directory filtering in the web skill mapper
If skill discovery must include multiple roots or provider-level skills, prefer adding a server-facing skill list contract rather than making every component merge filesystem roots. Until then, keep the browser API small and catalog-shaped.
Tests To Add Or Update
For catalog root, mapping, and prompt reference changes:
cd apps/web
bun run test src/lib/skillCatalog.test.ts src/lib/skillReferences.test.ts
For query/missing directory behavior:
cd apps/web
bun run test src/lib/skillReactQuery.test.ts
For composer item mapping:
cd apps/web
bun run test src/components/chat/composerSuggestionItems.test.ts
For real browser behavior, update ChatView.browser.tsx skill cases when selection, sent text, or copy behavior changes.
Completion Standard
Run the repo-required checks:
bun fmt
bun lint
bun typecheck
If tests are relevant, use bun run test, never bun test.
Footguns
- Do not hand-build
.claude/skillspaths in components. - Do not call
projects.searchEntriesdirectly for skill suggestions from UI components. - Do not treat a missing
.claude/skillsdirectory as a user-facing error. - Do not include nested files like
references/foo.mdas selectable skills. - Do not drop
includeIgnored: true; configured skills may be symlinked or ignored. - Do not replace absolute
@.../SKILL.mdprompt references with display labels in sent/copied text. - Do not duplicate skill chip rendering between composer and timeline.
- Do not expand provider-specific behavior without a clear source of truth.