Skip to content

feat: expose skills and $ autocomplete#92

Merged
tiann merged 1 commit intotiann:mainfrom
freespace8:feat/skills-autocomplete
Jan 21, 2026
Merged

feat: expose skills and $ autocomplete#92
tiann merged 1 commit intotiann:mainfrom
freespace8:feat/skills-autocomplete

Conversation

@freespace8
Copy link
Copy Markdown
Contributor

增加codex 支持 $ 显示技能

image

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • None.

Summary

  • No issues found in diff; residual risk: skills API + autocomplete path not covered by integration tests.

Testing

  • Not run (automation)

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • None.

Summary

  • No issues found in diff; residual risk: skills API + autocomplete path not covered by integration tests.

Testing

  • Not run (automation)

HAPI Bot

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for autocompleting Codex skills using the $ prefix in the chat input. Skills are loaded from the ~/.codex/skills directory (including .system subdirectories) by reading SKILL.md files with YAML frontmatter containing skill names and descriptions. The autocomplete UI has been updated to better display multi-line descriptions, and recently used skills are tracked in localStorage for improved suggestion ordering.

Changes:

  • Added backend API endpoint to list available skills from the filesystem
  • Implemented frontend autocomplete for skills triggered by $ prefix
  • Updated autocomplete UI to support longer descriptions with line clamping

Reviewed changes

Copilot reviewed 15 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
web/src/types/api.ts Added SkillSummary and SkillsResponse types
web/src/router.tsx Integrated skill autocomplete alongside slash commands
web/src/lib/recent-skills.ts New utility for tracking recently used skills in localStorage
web/src/lib/query-keys.ts Added query key for skills data caching
web/src/hooks/queries/useSkills.ts New hook for fetching and filtering skill suggestions
web/src/components/ChatInput/Autocomplete.tsx Updated layout to display descriptions on separate lines with clamping
web/src/components/AssistantChat/HappyComposer.tsx Added $ to autocomplete prefixes and skill usage tracking
web/src/api/client.ts Added getSkills API method
server/src/web/routes/sessions.ts Added GET /sessions/:id/skills endpoint
server/src/sync/syncEngine.ts Added listSkills method
server/src/sync/rpcGateway.ts Added RPC gateway method for listing skills
cli/src/modules/common/skills.ts Core logic for reading skills from filesystem with frontmatter parsing
cli/src/modules/common/skills.test.ts Comprehensive tests for skill listing functionality
cli/src/modules/common/handlers/skills.ts RPC handler for listSkills requests
cli/src/modules/common/registerCommonHandlers.ts Registered skills handler
bun.lock Added Windows x64 binary dependency
.gitignore Added cli/npm/main/ to ignore list

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

<span className="w-full font-medium">{suggestion.label}</span>
{suggestion.description && (
<span className={`truncate text-xs ${
<span className={`w-full min-h-[2.25rem] text-xs leading-snug line-clamp-2 ${
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The min-h-[2.25rem] class sets a minimum height of 2.25rem (36px) for description text with line-clamp-2. This creates excessive whitespace when descriptions are short (single line), as the element will still occupy 36px minimum. Consider removing min-h-[2.25rem] to allow the description to naturally size based on its content, or use a smaller minimum height if needed.

Suggested change
<span className={`w-full min-h-[2.25rem] text-xs leading-snug line-clamp-2 ${
<span className={`w-full text-xs leading-snug line-clamp-2 ${

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +99
const getSuggestions = useCallback(async (queryText: string): Promise<Suggestion[]> => {
const recent = getRecentSkills()
const getRecency = (name: string) => recent[name] ?? 0
const searchTerm = queryText.startsWith('$')
? queryText.slice(1).toLowerCase()
: queryText.toLowerCase()

if (!searchTerm) {
return [...skills]
.sort((a, b) => getRecency(b.name) - getRecency(a.name) || a.name.localeCompare(b.name))
.map((skill) => ({
key: `$${skill.name}`,
text: `$${skill.name}`,
label: `$${skill.name}`,
description: skill.description,
source: 'builtin'
}))
}

const maxDistance = Math.max(2, Math.floor(searchTerm.length / 2))
return skills
.map(skill => {
const name = skill.name.toLowerCase()
let score: number
if (name === searchTerm) score = 0
else if (name.startsWith(searchTerm)) score = 1
else if (name.includes(searchTerm)) score = 2
else {
const dist = levenshteinDistance(searchTerm, name)
score = dist <= maxDistance ? 3 + dist : Infinity
}
return { skill, score, recency: getRecency(skill.name) }
})
.filter(item => item.score < Infinity)
.sort((a, b) => a.score - b.score || b.recency - a.recency || a.skill.name.localeCompare(b.skill.name))
.map(({ skill }) => ({
key: `$${skill.name}`,
text: `$${skill.name}`,
label: `$${skill.name}`,
description: skill.description,
source: 'builtin'
}))
}, [skills])
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getSuggestions callback uses the skills array but doesn't include it in the useCallback dependency array. This means the callback will continue to use a stale version of the skills array from when the callback was first created. Add skills to the dependency array to ensure the callback always uses the latest skills data.

Copilot uses AI. Check for mistakes.
@tiann tiann merged commit 2cb8727 into tiann:main Jan 21, 2026
9 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.

3 participants