Offers slash command and skill completion for a leading /word even when text already follows the cursor.

##初期化 ####Mac OS X
cd mac ./initialize
####Windows
PowerShellで
cd windows ./initialize.ps1
##更新 ####Mac OS X
cd mac ./update
####Windows
PowerShellで
cd windows ./update.ps1
##エディタプラグインの更新 ####Neovim プラグインはlazy.nvimで自動管理されます。 手動更新が必要な場合はNeovimで
:Lazy update
hooks/register.ts 41 lines1import type { Register } from 'claude-code'
2
3const MAX_ROWS = 20
4
5export const register: Register = on => {
6 on('prompt.autocomplete', { token: /^\// }, async ($, e, next) => {
7 const base = await next(e)
8 const isLeading = e.start === 0
9 // Text anywhere after the cursor, on this line or a later one.
10 const hasTextAfter = /\S/.test(e.text.slice(e.cursor))
11
12 // The engine already completes a leading `/word` with nothing after it.
13 if (!isLeading || !hasTextAfter) return base
14
15 // Only a word glued to the cursor needs a space; whitespace already there stays.
16 const sep = /\S/.test(e.text[e.cursor] ?? '') ? ' ' : ''
17 const typed = e.token.slice(1).toLowerCase()
18 const seen = new Set<string>()
19 const rows = (await $.command.list())
20 .filter(c => {
21 // A plugin skill matches on its bare name too: `/deploy` finds `p:deploy`.
22 const bare = c.name.slice(c.name.lastIndexOf(':') + 1)
23 const isMatch =
24 c.name.toLowerCase().startsWith(typed) ||
25 bare.toLowerCase().startsWith(typed)
26
27 if (!isMatch || seen.has(c.name)) return false
28 seen.add(c.name)
29 return true
30 })
31 .slice(0, MAX_ROWS)
32 .map(c => ({
33 text: `/${c.name}${sep}`,
34 label: `/${c.name}`,
35 description: c.description,
36 }))
37
38 return { suggestions: [...base.suggestions, ...rows] }
39 })
40}
41