6 6
7> 新增技能、hooks、MCP 伺服器及其他所有元件類型至 Claude Code 外掛程式,並提供每種元件的驗證範例。7> 新增技能、hooks、MCP 伺服器及其他所有元件類型至 Claude Code 外掛程式,並提供每種元件的驗證範例。
8 8
9export const Piece = ({id, children}) => <div className="pe-piece" data-piece={id}>{children}</div>;
10
11export const PluginExplorer = ({children}) => {
12 const PIECES = [{
13 id: 'manifest',
14 name: 'Manifest',
15 path: '.claude-plugin/plugin.json',
16 lines: [{
17 depth: 0,
18 kind: 'folder',
19 text: '.claude-plugin/'
20 }, {
21 depth: 1,
22 kind: 'file',
23 text: 'plugin.json'
24 }],
25 href: '/en/plugins/manifest-reference#manifest-file',
26 linkText: 'Go to the manifest reference'
27 }, {
28 id: 'skills',
29 name: 'Skills',
30 path: 'skills/review/SKILL.md',
31 lines: [{
32 depth: 0,
33 kind: 'folder',
34 text: 'skills/'
35 }, {
36 depth: 1,
37 kind: 'folder',
38 text: 'review/'
39 }, {
40 depth: 2,
41 kind: 'file',
42 text: 'SKILL.md'
43 }],
44 href: '/en/plugins/components#skills',
45 linkText: 'Go to the Skills section'
46 }, {
47 id: 'commands',
48 name: 'Commands',
49 path: 'commands/about.md',
50 lines: [{
51 depth: 0,
52 kind: 'folder',
53 text: 'commands/'
54 }, {
55 depth: 1,
56 kind: 'file',
57 text: 'about.md'
58 }],
59 href: '/en/plugins/components#commands',
60 linkText: 'Go to the Commands section'
61 }, {
62 id: 'agents',
63 name: 'Agents',
64 path: 'agents/security-reviewer.md',
65 lines: [{
66 depth: 0,
67 kind: 'folder',
68 text: 'agents/'
69 }, {
70 depth: 1,
71 kind: 'file',
72 text: 'security-reviewer.md'
73 }],
74 href: '/en/plugins/components#agents',
75 linkText: 'Go to the Agents section'
76 }, {
77 id: 'hooks',
78 name: 'Hooks',
79 path: 'hooks/hooks.json',
80 lines: [{
81 depth: 0,
82 kind: 'folder',
83 text: 'hooks/'
84 }, {
85 depth: 1,
86 kind: 'file',
87 text: 'hooks.json'
88 }],
89 href: '/en/plugins/components#hooks',
90 linkText: 'Go to the Hooks section'
91 }, {
92 id: 'monitors',
93 name: 'Monitors',
94 path: 'monitors/monitors.json',
95 lines: [{
96 depth: 0,
97 kind: 'folder',
98 text: 'monitors/'
99 }, {
100 depth: 1,
101 kind: 'file',
102 text: 'monitors.json'
103 }],
104 href: '/en/plugins/components#monitors',
105 linkText: 'Go to the Monitors section'
106 }, {
107 id: 'output-styles',
108 name: 'Output styles',
109 path: 'output-styles/terse.md',
110 lines: [{
111 depth: 0,
112 kind: 'folder',
113 text: 'output-styles/'
114 }, {
115 depth: 1,
116 kind: 'file',
117 text: 'terse.md'
118 }],
119 href: '/en/plugins/components#themes-and-output-styles',
120 linkText: 'Go to the Themes and output styles section'
121 }, {
122 id: 'themes',
123 name: 'Themes',
124 path: 'themes/dracula.json',
125 lines: [{
126 depth: 0,
127 kind: 'folder',
128 text: 'themes/'
129 }, {
130 depth: 1,
131 kind: 'file',
132 text: 'dracula.json'
133 }],
134 href: '/en/plugins/components#themes-and-output-styles',
135 linkText: 'Go to the Themes and output styles section'
136 }, {
137 id: 'workflows',
138 name: 'Workflows',
139 path: 'workflows/audit-routes.js',
140 lines: [{
141 depth: 0,
142 kind: 'folder',
143 text: 'workflows/'
144 }, {
145 depth: 1,
146 kind: 'file',
147 text: 'audit-routes.js'
148 }],
149 href: '/en/workflows#distribute-a-workflow-in-a-plugin',
150 linkText: 'Go to Distribute a workflow in a plugin'
151 }, {
152 id: 'bin',
153 name: 'Executables',
154 path: 'bin/hello-plugin',
155 lines: [{
156 depth: 0,
157 kind: 'folder',
158 text: 'bin/'
159 }, {
160 depth: 1,
161 kind: 'file',
162 text: 'hello-plugin'
163 }],
164 href: '/en/plugins/components#executables',
165 linkText: 'Go to the Executables section'
166 }, {
167 id: 'scripts',
168 name: 'Scripts',
169 path: 'scripts/format.sh',
170 lines: [{
171 depth: 0,
172 kind: 'folder',
173 text: 'scripts/'
174 }, {
175 depth: 1,
176 kind: 'file',
177 text: 'format.sh'
178 }],
179 href: '/en/plugins/components#hooks',
180 linkText: 'Go to the Hooks section'
181 }, {
182 id: 'settings',
183 name: 'Default settings',
184 path: 'settings.json',
185 lines: [{
186 depth: 0,
187 kind: 'file',
188 text: 'settings.json'
189 }],
190 href: '/en/plugins/components#default-settings',
191 linkText: 'Go to the Default settings section'
192 }, {
193 id: 'mcp',
194 name: 'MCP servers',
195 path: '.mcp.json',
196 lines: [{
197 depth: 0,
198 kind: 'file',
199 text: '.mcp.json'
200 }],
201 href: '/en/plugins/components#mcp-servers',
202 linkText: 'Go to the MCP servers section'
203 }, {
204 id: 'lsp',
205 name: 'LSP servers',
206 path: '.lsp.json',
207 lines: [{
208 depth: 0,
209 kind: 'file',
210 text: '.lsp.json'
211 }],
212 href: '/en/plugins/components#lsp-servers',
213 linkText: 'Go to the LSP servers section'
214 }];
215 const [selectedId, setSelectedId] = useState('manifest');
216 const [isFullscreen, setIsFullscreen] = useState(false);
217 const rootRef = useRef(null);
218 useEffect(() => {
219 const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);
220 document.addEventListener('fullscreenchange', onFsChange);
221 return () => document.removeEventListener('fullscreenchange', onFsChange);
222 }, []);
223 const toggleFullscreen = () => {
224 if (!rootRef.current) return;
225 if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {});
226 };
227 const selected = PIECES.find(p => p.id === selectedId) || PIECES[0];
228 const onTreeKeyDown = e => {
229 const keys = ['ArrowDown', 'ArrowUp', 'Home', 'End'];
230 if (keys.indexOf(e.key) === -1) return;
231 const i = PIECES.findIndex(p => p.id === selectedId);
232 let next = i;
233 if (e.key === 'ArrowDown') next = Math.min(PIECES.length - 1, i + 1);
234 if (e.key === 'ArrowUp') next = Math.max(0, i - 1);
235 if (e.key === 'Home') next = 0;
236 if (e.key === 'End') next = PIECES.length - 1;
237 e.preventDefault();
238 if (next === i) return;
239 const id = PIECES[next].id;
240 setSelectedId(id);
241 const el = document.getElementById('pe-node-' + id);
242 if (el) el.focus();
243 };
244 const FolderIcon = () => <svg className="pe-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" aria-hidden="true">
245 <path d="M1.5 4.5a1 1 0 0 1 1-1h3.2l1.3 1.5h6a1 1 0 0 1 1 1V12a1 1 0 0 1-1 1h-10.5a1 1 0 0 1-1-1z" />
246 </svg>;
247 const FileIcon = () => <svg className="pe-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" aria-hidden="true">
248 <path d="M4 1.5h5.5L13 5v9.5H4z" />
249 <path d="M9.5 1.5V5H13" />
250 </svg>;
251 return <div ref={rootRef} className={isFullscreen ? 'pe-root pe-fullscreen not-prose' : 'pe-root not-prose'} data-selected={selected.id}>
252 <style>{`
253 .pe-root {
254 --pe-mono: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
255 --pe-accent: #D97757;
256 --pe-accent-text: #A8502F;
257 --pe-accent-bg: rgba(217,119,87,0.10);
258 --pe-bg: #FFFFFF;
259 --pe-surface: #FAFAF7;
260 --pe-hover: #F0EEE6;
261 --pe-border: #E8E6DC;
262 --pe-text: #141413;
263 --pe-text-2: #3D3D3A;
264 --pe-text-3: #5E5D59;
265 font-family: inherit;
266 background: var(--pe-bg);
267 color: var(--pe-text);
268 border: 1px solid var(--pe-border);
269 border-radius: 12px;
270 margin: 1.5rem 0;
271 overflow: hidden;
272 box-sizing: border-box;
273 }
274 .dark .pe-root {
275 --pe-accent-text: #EBA98F;
276 --pe-accent-bg: rgba(217,119,87,0.18);
277 --pe-bg: #1A1918;
278 --pe-surface: #232221;
279 --pe-hover: #2E2D2B;
280 --pe-border: #3A3936;
281 --pe-text: #F1EFE9;
282 --pe-text-2: #D6D4CA;
283 --pe-text-3: #B8B5AD;
284 }
285 .pe-root *, .pe-root *::before, .pe-root *::after { box-sizing: border-box; }
286 .pe-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 24px 16px; border-bottom: 1px solid var(--pe-border); }
287 .pe-head-text { flex: 1; min-width: 0; }
288 .pe-fs-btn { flex-shrink: 0; width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--pe-border); border-radius: 6px; background: var(--pe-surface); color: var(--pe-text-2); font-size: 15px; line-height: 1; cursor: pointer; }
289 .pe-fs-btn:hover { background: var(--pe-hover); }
290 .pe-fs-btn:focus-visible { outline: 2px solid var(--pe-accent); outline-offset: 2px; }
291 .pe-fullscreen { border-radius: 0; height: 100vh; display: flex; flex-direction: column; overflow: auto; }
292 .pe-fullscreen .pe-body { flex: 1; }
293 .pe-title { font-size: 19px; font-weight: 600; line-height: 1.3; color: var(--pe-text); margin: 0; }
294 .pe-sub { font-size: 15px; line-height: 1.5; color: var(--pe-text-3); margin: 4px 0 0; }
295 .pe-sub code { font-family: var(--pe-mono); font-size: 0.88em; padding: 1px 5px; border-radius: 4px; background: var(--pe-surface); border: 1px solid var(--pe-border); }
296 .pe-body { display: flex; align-items: stretch; }
297 .pe-tree-pane { width: 270px; flex-shrink: 0; background: var(--pe-surface); border-right: 1px solid var(--pe-border); padding: 16px 0 12px; }
298 .pe-panel { flex: 1; min-width: 0; padding: 16px 24px 24px; }
299 .pe-caption { font-size: 13px; font-weight: 600; color: var(--pe-text-3); margin: 0 0 10px; }
300 .pe-tree-pane .pe-caption { padding: 0 16px; }
301 .pe-rootline { display: flex; align-items: center; gap: 7px; padding: 3px 16px; font-family: var(--pe-mono); font-size: 13.5px; color: var(--pe-text-3); }
302 .pe-node {
303 display: block; width: 100%; margin: 0; padding: 3px 16px 3px 30px; text-align: left; cursor: pointer;
304 background: transparent; color: var(--pe-text-2);
305 border: none; border-left: 3px solid transparent;
306 font-family: var(--pe-mono); font-size: 13.5px; line-height: 1.4;
307 }
308 .pe-node:hover { background: var(--pe-hover); }
309 .pe-node:focus-visible { outline: 2px solid var(--pe-accent); outline-offset: -2px; }
310 .pe-node[aria-pressed="true"] { background: var(--pe-accent-bg); border-left-color: var(--pe-accent); color: var(--pe-accent-text); font-weight: 600; }
311 .pe-line { display: flex; align-items: center; gap: 7px; padding: 2px 0; }
312 .pe-line-tree { flex-wrap: wrap; }
313 .pe-line-tree .pe-req { flex-basis: 100%; margin: 2px 0 0 22px; white-space: normal; width: fit-content; max-width: calc(100% - 22px); }
314 .pe-line span { overflow-wrap: anywhere; }
315 .pe-piece { display: none; font-size: 16px; line-height: 1.6; color: var(--pe-text-2); }
316 .pe-root[data-selected="manifest"] .pe-piece[data-piece="manifest"],
317 .pe-root[data-selected="skills"] .pe-piece[data-piece="skills"],
318 .pe-root[data-selected="commands"] .pe-piece[data-piece="commands"],
319 .pe-root[data-selected="agents"] .pe-piece[data-piece="agents"],
320 .pe-root[data-selected="hooks"] .pe-piece[data-piece="hooks"],
321 .pe-root[data-selected="monitors"] .pe-piece[data-piece="monitors"],
322 .pe-root[data-selected="output-styles"] .pe-piece[data-piece="output-styles"],
323 .pe-root[data-selected="themes"] .pe-piece[data-piece="themes"],
324 .pe-root[data-selected="workflows"] .pe-piece[data-piece="workflows"],
325 .pe-root[data-selected="bin"] .pe-piece[data-piece="bin"],
326 .pe-root[data-selected="scripts"] .pe-piece[data-piece="scripts"],
327 .pe-root[data-selected="settings"] .pe-piece[data-piece="settings"],
328 .pe-root[data-selected="mcp"] .pe-piece[data-piece="mcp"],
329 .pe-root[data-selected="lsp"] .pe-piece[data-piece="lsp"] { display: block; }
330 .pe-piece p { margin: 0 0 10px; }
331 .pe-piece p:last-child { margin-bottom: 0; }
332 .pe-piece code { font-family: var(--pe-mono); font-size: 0.88em; padding: 1px 5px; border-radius: 4px; background: var(--pe-surface); border: 1px solid var(--pe-border); }
333 .pe-piece .code-block { margin: 12px 0 0; }
334 .pe-piece pre code { padding: 0; border: none; background: none; }
335 .pe-piece a { color: var(--pe-accent-text); }
336 .pe-line-compact { display: none; }
337 .pe-icon { flex-shrink: 0; }
338 .pe-req { margin-left: 8px; padding: 0 6px; border-radius: 999px; font-size: 11px; line-height: 18px; letter-spacing: .02em; color: var(--pe-accent-text); border: 1px solid var(--pe-border); background: var(--pe-surface); white-space: nowrap; font-weight: 500; vertical-align: middle; }
339 .pe-name { font-size: 22px; font-weight: 600; line-height: 1.25; letter-spacing: -0.2px; color: var(--pe-text); margin: 0; }
340 .pe-path { font-family: var(--pe-mono); font-size: 13.5px; color: var(--pe-accent-text); margin: 4px 0 0; overflow-wrap: anywhere; }
341 .pe-block { margin: 20px 0 0; }
342 .pe-link {
343 display: inline-block; margin: 24px 0 0; padding: 8px 14px; border-radius: 8px;
344 font-size: 14.5px; font-weight: 600; text-decoration: none;
345 color: var(--pe-accent-text); background: var(--pe-accent-bg); border: 1px solid var(--pe-accent);
346 }
347 .pe-link:hover { filter: brightness(0.97); }
348 .pe-link:focus-visible { outline: 2px solid var(--pe-accent); outline-offset: 2px; }
349 @media (max-width: 700px) {
350 .pe-head { padding: 16px 16px 14px; }
351 .pe-body { flex-direction: column; }
352 .pe-tree-pane { width: 100%; border-right: none; border-bottom: 1px solid var(--pe-border); }
353 .pe-line-tree { display: none; }
354 .pe-line-compact { display: flex; }
355 .pe-panel { padding: 16px 16px 20px; }
356 }
357 `}</style>
358
359 <div className="pe-head">
360 <div className="pe-head-text">
361 <div className="pe-title">What goes in a plugin</div>
362 <div className="pe-sub">This example plugin, <code>my-plugin</code>, has one of every kind of component, each in its default location. Select a file or folder to read what it’s for and see what goes in it.</div>
363 </div>
364 <button type="button" className="pe-fs-btn" onClick={toggleFullscreen} aria-label={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}>
365 {isFullscreen ? '⤡' : '⛶'}
366 </button>
367 </div>
368
369 <div className="pe-body">
370 <div className="pe-tree-pane">
371 <div className="pe-caption" id="pe-tree-caption">Plugin directory</div>
372 <div role="group" aria-labelledby="pe-tree-caption" onKeyDown={onTreeKeyDown}>
373 <div className="pe-rootline"><FolderIcon /><span>my-plugin/</span></div>
374 {PIECES.map(p => <button key={p.id} id={'pe-node-' + p.id} type="button" className="pe-node" aria-pressed={p.id === selected.id} aria-label={p.name + ', ' + p.path} onClick={() => setSelectedId(p.id)}>
375 {p.lines.map((line, i) => <span key={i} className="pe-line pe-line-tree" style={{
376 paddingLeft: line.depth * 18 + 'px'
377 }}>
378 {line.kind === 'folder' ? <FolderIcon /> : <FileIcon />}
379 <span>{line.text}</span>
380 {p.required && i === p.lines.length - 1 ? <span className="pe-req">{p.required}</span> : null}
381 </span>)}
382 <span className="pe-line pe-line-compact">
383 <FileIcon />
384 <span>{p.path}</span>
385 {p.required ? <span className="pe-req">{p.required}</span> : null}
386 </span>
387 </button>)}
388 </div>
389 </div>
390
391 <div className="pe-panel" role="region" aria-labelledby="pe-panel-caption" aria-live="polite" aria-atomic="true">
392 <div className="pe-caption" id="pe-panel-caption">Selected piece</div>
393 <div className="pe-name">{selected.name}{selected.required ? <span className="pe-req">{selected.required}</span> : null}</div>
394 <div className="pe-path">{selected.path}</div>
395
396 <div className="pe-block">{children}</div>
397
398 <a className="pe-link" href={selected.href}>{selected.linkText}</a>
399 </div>
400 </div>
401 </div>;
402};
403
404Claude Code 外掛程式由多個元件組成,例如技能、代理、hooks 和 MCP 伺服器。每個元件在外掛程式中都有一個預設資料夾、`.claude-plugin/plugin.json` 中的選用資訊清單鍵(用於取代或新增至該資料夾),以及使用者看到的名稱。如需每個鍵的完整欄位表,請參閱[資訊清單參考](/docs/zh-TW/plugins/manifest-reference#fields)。9Claude Code 外掛程式由多個元件組成,例如技能、代理、hooks 和 MCP 伺服器。每個元件在外掛程式中都有一個預設資料夾、`.claude-plugin/plugin.json` 中的選用資訊清單鍵(用於取代或新增至該資料夾),以及使用者看到的名稱。如需每個鍵的完整欄位表,請參閱[資訊清單參考](/docs/zh-TW/plugins/manifest-reference#fields)。
405 10
406使用此頁面將元件新增至已載入的外掛程式。11使用此頁面將元件新增至已載入的外掛程式。
407 12
408新增元件後,在執行中的工作階段中執行 `/reload-plugins`,或啟動新的工作階段,以便 Claude Code 載入該元件。若要在載入前檢查元件的檔案,請從外掛程式目錄在您的殼層中執行 [`claude plugin validate .`](/docs/zh-TW/plugins/cli-reference#plugin-validate)。13新增元件後,在執行中的工作階段中執行 `/reload-plugins`,或啟動新的工作階段,以便 Claude Code 載入該元件。若要在載入前檢查元件的檔案,請從外掛程式目錄在您的殼層中執行 [`claude plugin validate .`](/docs/zh-TW/plugins/cli-reference#plugin-validate)。
409 14
410<Note>15> [!NOTE]
411 這些情況涵蓋在其他頁面上:16>
412 17> 這些情況涵蓋在其他頁面上:
413 * **建立您的第一個外掛程式**:從[建立外掛程式](/docs/zh-TW/plugins/create)開始18>
414 * **安裝他人的外掛程式**:請參閱[安裝外掛程式](/docs/zh-TW/plugins/install)19> * **建立您的第一個外掛程式**:從[建立外掛程式](/docs/zh-TW/plugins/create)開始
415 * **您的外掛程式使用者在 claude.ai 或 Cowork 上**:那裡會載入不同的元件集合。請參閱[外掛程式結構和測試](https://claude.com/docs/plugins/build)和[元件支援表](https://claude.com/docs/plugins/platform-support#compare-component-support-by-app)20> * **安裝他人的外掛程式**:請參閱[安裝外掛程式](/docs/zh-TW/plugins/install)
416</Note>21> * **您的外掛程式使用者在 claude.ai 或 Cowork 上**:那裡會載入不同的元件集合。請參閱[外掛程式結構和測試](https://claude.com/docs/plugins/build)和[元件支援表](https://claude.com/docs/plugins/platform-support#compare-component-support-by-app)
417 22
418<h2 id="explore-the-plugin-directory">23## 探索外掛程式目錄
419 探索外掛程式目錄
420</h2>
421 24
422探索器顯示一個範例外掛程式 `my-plugin`,在其預設位置中包含每種元件的一個:25探索器顯示一個範例外掛程式 `my-plugin`,在其預設位置中包含每種元件的一個:
423 26
433 36
434每個檔案都是其格式的最小有效範例,目的是展示形狀而不是實用性:真實的技能或代理包含完整的指示,通常還有支援檔案,真實的掛鉤或監視器執行真實的工作。探索器之後的章節使用相同的檔案作為範例,並連結到更完整的版本。選擇一個檔案或資料夾來閱讀它的用途、查看其中的內容,並找到涵蓋它的章節。37每個檔案都是其格式的最小有效範例,目的是展示形狀而不是實用性:真實的技能或代理包含完整的指示,通常還有支援檔案,真實的掛鉤或監視器執行真實的工作。探索器之後的章節使用相同的檔案作為範例,並連結到更完整的版本。選擇一個檔案或資料夾來閱讀它的用途、查看其中的內容,並找到涵蓋它的章節。
435 38
436<PluginExplorer>39What goes in a plugin
437 <Piece id="manifest">
438 [manifest](/docs/zh-TW/plugins/manifest-reference) 是外掛程式 `.claude-plugin/` 目錄中的 `plugin.json` 檔案。它包含外掛程式的中繼資料和 Claude Code 提示使用者輸入的 `userConfig` 值。即使沒有此檔案,Claude Code 也會載入外掛程式。在檔案中,只有 `name` 是必需的。在這個檔案中,`description` 是使用者在 `/plugin` 中看到的外掛程式文字,`version` 會讓使用者保持在該版本,直到您變更它:
439 40
440 ```json theme={null}41This example plugin, `my-plugin`, has one of every kind of component, each in its default location. Select a file or folder to read what it’s for and see what goes in it.
441 {42
43Plugin directory
44
45my-plugin/
46
47Selected piece
48
49[manifest](/docs/zh-TW/plugins/manifest-reference) 是外掛程式 `.claude-plugin/` 目錄中的 `plugin.json` 檔案。它包含外掛程式的中繼資料和 Claude Code 提示使用者輸入的 `userConfig` 值。即使沒有此檔案,Claude Code 也會載入外掛程式。在檔案中,只有 `name` 是必需的。在這個檔案中,`description` 是使用者在 `/plugin` 中看到的外掛程式文字,`version` 會讓使用者保持在該版本,直到您變更它:
50
51```json theme={null}
52{
442 "name": "my-plugin",53 "name": "my-plugin",
443 "version": "1.0.0",54 "version": "1.0.0",
444 "description": "Review, formatting, and database tools for this team"55 "description": "Review, formatting, and database tools for this team"
445 }56}
446 ```57```
447 </Piece>
448 58
449 <Piece id="skills">59[skill](/docs/zh-TW/skills) 是一個 `SKILL.md` 檔案。將每個技能儲存在 `skills/` 下的自己的目錄中。Claude 讀取每個技能的 `description`,當使用者要求的內容與其相符時,例如在此處要求 Claude 審查拉取請求,Claude 會載入技能的指示並遵循它們。使用者也可以直接執行它作為 `/my-plugin:review`:
450 [skill](/docs/zh-TW/skills) 是一個 `SKILL.md` 檔案。將每個技能儲存在 `skills/` 下的自己的目錄中。Claude 讀取每個技能的 `description`,當使用者要求的內容與其相符時,例如在此處要求 Claude 審查拉取請求,Claude 會載入技能的指示並遵循它們。使用者也可以直接執行它作為 `/my-plugin:review`:
451 60
452 ```markdown theme={null}61```markdown theme={null}
453 ---62---
454 description: Reviews a pull request for style and test coverage. Use when asked to review code.63description: Reviews a pull request for style and test coverage. Use when asked to review code.
455 ---64---
456 65
457 Review the changed files. Report style problems first, then missing tests.66Review the changed files. Report style problems first, then missing tests.
458 ```67```
459 </Piece>
460 68
461 <Piece id="commands">69命令是使用者按名稱執行的單一 Markdown 檔案。命令是較舊的格式:技能按名稱執行的方式相同,也可以在自己的目錄中攜帶支援檔案,因此將新的寫成技能,並為您已有的檔案保留 `commands/`。此檔案變成 `/my-plugin:about`,並採用與技能相同的前置事項:
462 命令是使用者按名稱執行的單一 Markdown 檔案。命令是較舊的格式:技能按名稱執行的方式相同,也可以在自己的目錄中攜帶支援檔案,因此將新的寫成技能,並為您已有的檔案保留 `commands/`。此檔案變成 `/my-plugin:about`,並採用與技能相同的前置事項:
463 70
464 ```markdown theme={null}71```markdown theme={null}
465 ---72---
466 description: Summarize the repository73description: Summarize the repository
467 ---74---
468 75
469 Summarize what this repository does in three sentences.76Summarize what this repository does in three sentences.
470 ```77```
471 </Piece>
472 78
473 <Piece id="agents">79[subagent](/docs/zh-TW/sub-agents) 是一個單獨的助手,具有自己的指示和自己的內容視窗,Claude 可以將任務委派給它並取回結果。`agents/` 下的每個 Markdown 檔案定義一個:前置事項命名它並說明何時使用它,正文是其系統提示。這個命名為 `my-plugin:security-reviewer`,使用者可以使用 `@agent-my-plugin:security-reviewer` 呼叫它:
474 [subagent](/docs/zh-TW/sub-agents) 是一個單獨的助手,具有自己的指示和自己的內容視窗,Claude 可以將任務委派給它並取回結果。`agents/` 下的每個 Markdown 檔案定義一個:前置事項命名它並說明何時使用它,正文是其系統提示。這個命名為 `my-plugin:security-reviewer`,使用者可以使用 `@agent-my-plugin:security-reviewer` 呼叫它:
475 80
476 ```markdown theme={null}81```markdown theme={null}
477 ---82---
478 name: security-reviewer83name: security-reviewer
479 description: Reviews code changes for security issues. Use after edits to authentication or input handling.84description: Reviews code changes for security issues. Use after edits to authentication or input handling.
480 model: sonnet85model: sonnet
481 ---86---
482 87
483 You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.88You are a security reviewer. Read the changed files and report injection, authentication, and secrets-handling risks.
484 ```89```
485 </Piece>
486 90
487 <Piece id="hooks">91[hook](/docs/zh-TW/hooks-guide) 在 Claude Code 生命週期中的某個點自動執行某些操作,例如在每次檔案編輯後:shell 命令、HTTP 請求、MCP 工具呼叫、對模型的提示或子代理。在外掛程式根目錄的 `hooks/hooks.json` 中儲存外掛程式的掛鉤。這個在 Claude 寫入或編輯檔案後執行外掛程式的 `scripts/format.sh`:
488 [hook](/docs/zh-TW/hooks-guide) 在 Claude Code 生命週期中的某個點自動執行某些操作,例如在每次檔案編輯後:shell 命令、HTTP 請求、MCP 工具呼叫、對模型的提示或子代理。在外掛程式根目錄的 `hooks/hooks.json` 中儲存外掛程式的掛鉤。這個在 Claude 寫入或編輯檔案後執行外掛程式的 `scripts/format.sh`:
489 92
490 ```json theme={null}93```json theme={null}
491 {94{
492 "hooks": {95 "hooks": {
493 "PostToolUse": [96 "PostToolUse": [
494 {97 {
502 }105 }
503 ]106 ]
504 }107 }
505 }108}
506 ```109```
507 </Piece>
508 110
509 <Piece id="monitors">111監視器是一個 shell 命令,Claude Code 在工作階段開始時在背景啟動,並保持執行直到工作階段結束。它列印的內容作為通知到達 Claude。`when` 欄位可以改為在指定的 skill 首次執行時啟動它。這個會持續追蹤錯誤日誌:
510 監視器是一個 shell 命令,Claude Code 在工作階段開始時在背景啟動,並保持執行直到工作階段結束。它列印的內容作為通知到達 Claude。`when` 欄位可以改為在指定的 skill 首次執行時啟動它。這個會持續追蹤錯誤日誌:
511 112
512 ```json theme={null}113```json theme={null}
513 [114[
514 {115 {
515 "name": "error-log",116 "name": "error-log",
516 "command": "tail -F ./logs/error.log",117 "command": "tail -F ./logs/error.log",
517 "description": "Application error log"118 "description": "Application error log"
518 }119 }
519 ]120]
520 ```121```
521 </Piece>
522 122
523 <Piece id="output-styles">123外掛程式可以包含 [output styles](/docs/zh-TW/output-styles),這會改變 Claude 格式化和措辭其回覆的方式。將每個輸出樣式儲存為 `output-styles/<name>.md`。這個在 `/output-style` 中顯示為 `my-plugin:terse`:
524 外掛程式可以包含 [output styles](/docs/zh-TW/output-styles),這會改變 Claude 格式化和措辭其回覆的方式。將每個輸出樣式儲存為 `output-styles/<name>.md`。這個在 `/output-style` 中顯示為 `my-plugin:terse`:
525 124
526 ```markdown theme={null}125```markdown theme={null}
527 ---126---
528 name: terse127name: terse
529 description: Answer in as few words as possible128description: Answer in as few words as possible
530 keep-coding-instructions: true129keep-coding-instructions: true
531 ---130---
532 131
533 Keep every reply short. Skip preambles and summaries.132Keep every reply short. Skip preambles and summaries.
534 ```133```
535 </Piece>
536 134
537 <Piece id="themes">135外掛程式可以為 Claude Code 介面包含 [color themes](/docs/zh-TW/terminal-config#create-a-custom-theme)。將每個主題儲存為 `themes/<slug>.json`。這個在 `/theme` 中顯示為 `Dracula`,標記為來自 `my-plugin`:
538 外掛程式可以為 Claude Code 介面包含 [color themes](/docs/zh-TW/terminal-config#create-a-custom-theme)。將每個主題儲存為 `themes/<slug>.json`。這個在 `/theme` 中顯示為 `Dracula`,標記為來自 `my-plugin`:
539 136
540 ```json theme={null}137```json theme={null}
541 {138{
542 "name": "Dracula",139 "name": "Dracula",
543 "base": "dark",140 "base": "dark",
544 "overrides": {141 "overrides": {
545 "claude": "#bd93f9",142 "claude": "#bd93f9",
546 "error": "#ff5555"143 "error": "#ff5555"
547 }144 }
548 }145}
549 ```146```
550 </Piece>
551 147
552 <Piece id="workflows">148`workflows/` 資料夾包含 [workflow](/docs/zh-TW/workflows) `.js` 檔案:一個 `meta` 區塊,然後是協調多個子代理的指令碼正文。這個執行為 `/my-plugin:audit-routes`:
553 `workflows/` 資料夾包含 [workflow](/docs/zh-TW/workflows) `.js` 檔案:一個 `meta` 區塊,然後是協調多個子代理的指令碼正文。這個執行為 `/my-plugin:audit-routes`:
554 149
555 ```javascript theme={null}150```javascript theme={null}
556 export const meta = {151export const meta = {
557 name: 'audit-routes',152 name: 'audit-routes',
558 description: 'Audit every route handler for missing auth checks',153 description: 'Audit every route handler for missing auth checks',
559 }154}
560 155
561 const found = await agent('List every .ts file under src/routes/.', {156const found = await agent('List every .ts file under src/routes/.', {
562 schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },157 schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
563 })158})
564 159
565 const audits = await pipeline(found.files, file =>160const audits = await pipeline(found.files, file =>
566 agent(`Audit ${file} for missing authentication checks.`, { label: file }),161 agent(`Audit ${file} for missing authentication checks.`, { label: file }),
567 )162)
568 163
569 return audits.filter(Boolean)164return audits.filter(Boolean)
570 ```165```
571 </Piece>
572 166
573 <Piece id="bin">167`bin/` 是外掛程式如何提供命令列工具的方式。當外掛程式啟用時,Claude Code 將此資料夾放在它執行命令的 shell 的 `PATH` 上,因此 Claude 或技能的指示可以按名稱執行工具,而無需使用者安裝任何東西。有了這個 [executable](#executables),`hello-plugin` 是 Claude 可以執行的命令:
574 `bin/` 是外掛程式如何提供命令列工具的方式。當外掛程式啟用時,Claude Code 將此資料夾放在它執行命令的 shell 的 `PATH` 上,因此 Claude 或技能的指示可以按名稱執行工具,而無需使用者安裝任何東西。有了這個 [executable](#executables),`hello-plugin` 是 Claude 可以執行的命令:
575 168
576 ```bash theme={null}169```bash theme={null}
577 #!/bin/bash170#!/bin/bash
578 echo "hello from my-plugin"171echo "hello from my-plugin"
579 ```172```
580 </Piece>
581 173
582 <Piece id="scripts">174`hooks/hooks.json` 中的掛鉤執行指令碼,此資料夾是範例保留它的位置。名稱 `scripts/` 是一個慣例,不是 Claude Code 尋找的東西:掛鉤按其路徑指向檔案,`${CLAUDE_PLUGIN_ROOT}/scripts/format.sh`。格式化指令碼可能看起來像這樣:
583 `hooks/hooks.json` 中的掛鉤執行指令碼,此資料夾是範例保留它的位置。名稱 `scripts/` 是一個慣例,不是 Claude Code 尋找的東西:掛鉤按其路徑指向檔案,`${CLAUDE_PLUGIN_ROOT}/scripts/format.sh`。格式化指令碼可能看起來像這樣:
584 175
585 ```bash theme={null}176```bash theme={null}
586 #!/bin/bash177#!/bin/bash
587 npx prettier --write .178npx prettier --write .
588 ```179```
589 </Piece>
590 180
591 <Piece id="settings">181外掛程式根目錄中的 `settings.json` 包含在外掛程式啟用時適用的 [settings](/docs/zh-TW/settings-reference),因此外掛程式可以改變工作階段的行為方式,而不僅僅是新增元件。只有兩個鍵從外掛程式生效,[`agent`](/docs/zh-TW/settings-reference#agent) 和 [`subagentStatusLine`](/docs/zh-TW/settings-reference#subagentstatusline);所有其他鍵都被丟棄。請參閱 [Default settings](#default-settings)。
592 外掛程式根目錄中的 `settings.json` 包含在外掛程式啟用時適用的 [settings](/docs/zh-TW/settings-reference),因此外掛程式可以改變工作階段的行為方式,而不僅僅是新增元件。只有兩個鍵從外掛程式生效,[`agent`](/docs/zh-TW/settings-reference#agent) 和 [`subagentStatusLine`](/docs/zh-TW/settings-reference#subagentstatusline);所有其他鍵都被丟棄。請參閱 [Default settings](#default-settings)。
593 182
594 這個設定 `agent`,它執行工作階段的主執行緒作為外掛程式自己的 `security-reviewer` 代理,因此該代理的系統提示、工具限制和模型適用於整個工作階段:183這個設定 `agent`,它執行工作階段的主執行緒作為外掛程式自己的 `security-reviewer` 代理,因此該代理的系統提示、工具限制和模型適用於整個工作階段:
595 184
596 ```json theme={null}185```json theme={null}
597 {186{
598 "agent": "security-reviewer"187 "agent": "security-reviewer"
599 }188}
600 ```189```
601 </Piece>
602 190
603 <Piece id="mcp">191[MCP server](/docs/zh-TW/mcp) 從外部系統為 Claude 提供工具。在外掛程式根目錄的 `.mcp.json` 中宣告它。這個從外掛程式內的指令碼啟動本機伺服器,並在 `/mcp` 中顯示為 `plugin:my-plugin:db`:
604 [MCP server](/docs/zh-TW/mcp) 從外部系統為 Claude 提供工具。在外掛程式根目錄的 `.mcp.json` 中宣告它。這個從外掛程式內的指令碼啟動本機伺服器,並在 `/mcp` 中顯示為 `plugin:my-plugin:db`:
605 192
606 ```json theme={null}193```json theme={null}
607 {194{
608 "mcpServers": {195 "mcpServers": {
609 "db": {196 "db": {
610 "command": "node",197 "command": "node",
611 "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]198 "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]
612 }199 }
613 }200 }
614 }201}
615 ```202```
616 </Piece>
617 203
618 <Piece id="lsp">204LSP 伺服器為 Claude 提供語言的 [diagnostics and code navigation](/docs/zh-TW/plugins/code-intelligence)。在外掛程式根目錄的 `.lsp.json` 中宣告伺服器。這個連接 Go 語言伺服器用於 `.go` 檔案:
619 LSP 伺服器為 Claude 提供語言的 [diagnostics and code navigation](/docs/zh-TW/plugins/code-intelligence)。在外掛程式根目錄的 `.lsp.json` 中宣告伺服器。這個連接 Go 語言伺服器用於 `.go` 檔案:
620 205
621 ```json theme={null}206```json theme={null}
622 {207{
623 "gopls": {208 "gopls": {
624 "command": "gopls",209 "command": "gopls",
625 "args": ["serve"],210 "args": ["serve"],
627 ".go": "go"212 ".go": "go"
628 }213 }
629 }214 }
630 }215}
631 ```216```
632 </Piece>
633</PluginExplorer>
634 217
635<h2 id="add-each-kind-of-component">218## 新增每種元件
636 新增每種元件
637</h2>
638 219
639下面的每個章節涵蓋一種元件:其檔案在外掛程式中的位置、驗證的範例、外掛程式載入後使用者看到的內容,以及改變預設位置的 manifest 鍵。新增您的外掛程式需要的;沒有任何是必需的。220下面的每個章節涵蓋一種元件:其檔案在外掛程式中的位置、驗證的範例、外掛程式載入後使用者看到的內容,以及改變預設位置的 manifest 鍵。新增您的外掛程式需要的;沒有任何是必需的。
640 221
641<h3 id="skills">222### Skills
642 Skills
643</h3>
644 223
645[skill](/docs/zh-TW/skills) 是一個 `SKILL.md` 檔案,當其描述與任務相符時 Claude 可以載入。使用者也可以將其作為命令執行。將每個 skill 儲存在 `skills/` 下的自己的目錄中:224[skill](/docs/zh-TW/skills) 是一個 `SKILL.md` 檔案,當其描述與任務相符時 Claude 可以載入。使用者也可以將其作為命令執行。將每個 skill 儲存在 `skills/` 下的自己的目錄中:
646 225
679 258
680如需 frontmatter 欄位和支援檔案,請參閱 [Skills](/docs/zh-TW/skills)。259如需 frontmatter 欄位和支援檔案,請參閱 [Skills](/docs/zh-TW/skills)。
681 260
682<h3 id="commands">261### 命令
683 命令
684</h3>
685 262
686命令是使用者按名稱執行的單一 Markdown 檔案,例如 `/my-plugin:about`。263命令是使用者按名稱執行的單一 Markdown 檔案,例如 `/my-plugin:about`。
687 264
688<Note>265> [!NOTE]
689 命令是較舊的格式,[skills](#skills) 對新工作已取代它們。skill 按名稱執行的方式相同,它也可以在其目錄中攜帶支援檔案。為您從 `.claude/commands/` 移動的檔案保留 `commands/`。266>
690</Note>267> 命令是較舊的格式,[skills](#skills) 對新工作已取代它們。skill 按名稱執行的方式相同,它也可以在其目錄中攜帶支援檔案。為您從 `.claude/commands/` 移動的檔案保留 `commands/`。
691 268
692將命令儲存在 `commands/<file>.md`,它變成 `/<plugin>:<file>`。子目錄新增一個區段,所以 `commands/db/migrate.md` 是 `/my-plugin:db:migrate`。269將命令儲存在 `commands/<file>.md`,它變成 `/<plugin>:<file>`。子目錄新增一個區段,所以 `commands/db/migrate.md` 是 `/my-plugin:db:migrate`。
693 270
694命令檔案採用與 skills 相同的 frontmatter。271命令檔案採用與 skills 相同的 frontmatter。
695 272
696<h4 id="define-commands-in-the-manifest">273#### 在 manifest 中定義命令
697 在 manifest 中定義命令
698</h4>
699 274
700只有當您想將命令檔案保留在 `commands/` 以外的地方,或在 `plugin.json` 中定義短命令而不需要單獨的 Markdown 檔案時,您才需要這個。設定 `commands` manifest 鍵,Claude Code 會讀取它而不是掃描 `commands/`。鍵採用路徑、路徑陣列或將每個命令名稱對應到 `source` 檔案或內嵌 `content` 的物件。275只有當您想將命令檔案保留在 `commands/` 以外的地方,或在 `plugin.json` 中定義短命令而不需要單獨的 Markdown 檔案時,您才需要這個。設定 `commands` manifest 鍵,Claude Code 會讀取它而不是掃描 `commands/`。鍵採用路徑、路徑陣列或將每個命令名稱對應到 `source` 檔案或內嵌 `content` 的物件。
701 276
717 292
718如需完整的鍵語法,請參閱 [`commands`](/docs/zh-TW/plugins/manifest-reference#commands)。293如需完整的鍵語法,請參閱 [`commands`](/docs/zh-TW/plugins/manifest-reference#commands)。
719 294
720<h3 id="agents">295### Agents
721 Agents
722</h3>
723 296
724[子代理](/docs/zh-TW/sub-agents) 是一個單獨的助手,具有自己的指示和內容視窗,Claude 可以將任務委派給它。`agents/` 下的每個 Markdown 檔案定義一個:297[子代理](/docs/zh-TW/sub-agents) 是一個單獨的助手,具有自己的指示和內容視窗,Claude 可以將任務委派給它。`agents/` 下的每個 Markdown 檔案定義一個:
725 298
737 310
738`agents` manifest 鍵取代 `agents/` 掃描。311`agents` manifest 鍵取代 `agents/` 掃描。
739 312
740<h4 id="organize-agents-in-subfolders">313#### 在子資料夾中組織 agents
741 在子資料夾中組織 agents
742</h4>
743 314
744您可以將外掛程式 agent 檔案放在 `agents/` 的子資料夾中。Claude Code [遞迴載入它們](/docs/zh-TW/sub-agents#choose-the-subagent-scope),並使用冒號連接外掛程式名稱、每個子資料夾名稱和檔案名稱以形成 agent 的範圍名稱。例如,`my-plugin` 中的 `agents/review/security.md` 載入為 `my-plugin:review:security`。兩個設定改變該名稱:315您可以將外掛程式 agent 檔案放在 `agents/` 的子資料夾中。Claude Code [遞迴載入它們](/docs/zh-TW/sub-agents#choose-the-subagent-scope),並使用冒號連接外掛程式名稱、每個子資料夾名稱和檔案名稱以形成 agent 的範圍名稱。例如,`my-plugin` 中的 `agents/review/security.md` 載入為 `my-plugin:review:security`。兩個設定改變該名稱:
745 316
746* Frontmatter `name`:它只取代檔案名稱,所以 `agents/review/security.md` 中的 `name: audit` 載入為 `my-plugin:review:audit`317* Frontmatter `name`:它只取代檔案名稱,所以 `agents/review/security.md` 中的 `name: audit` 載入為 `my-plugin:review:audit`
747* Manifest [`agents`](/docs/zh-TW/plugins/manifest-reference#fields) 欄位:您在那裡列出的檔案載入時沒有子資料夾名稱,所以 `"agents": "./custom/review/security.md"` 載入為 `my-plugin:security`318* Manifest [`agents`](/docs/zh-TW/plugins/manifest-reference#fields) 欄位:您在那裡列出的檔案載入時沒有子資料夾名稱,所以 `"agents": "./custom/review/security.md"` 載入為 `my-plugin:security`
748 319
749<h4 id="frontmatter-fields-in-plugin-agents">320#### 外掛程式 agents 中的 Frontmatter 欄位
750 外掛程式 agents 中的 Frontmatter 欄位
751</h4>
752 321
753外掛程式 agent 的 frontmatter 遵循這些規則:322外掛程式 agent 的 frontmatter 遵循這些規則:
754 323
758 327
759如需每個欄位的作用和優先順序規則,請參閱 [子代理](/docs/zh-TW/sub-agents#supported-frontmatter-fields)。328如需每個欄位的作用和優先順序規則,請參閱 [子代理](/docs/zh-TW/sub-agents#supported-frontmatter-fields)。
760 329
761<h3 id="hooks">330### Hooks
762 Hooks
763</h3>
764 331
765[hook](/docs/zh-TW/hooks-guide) 在 Claude Code 生命週期中的某個點自動執行某些操作,例如在每次檔案編輯後:shell 命令、HTTP 請求、MCP 工具呼叫、對模型的提示或子代理。將外掛程式的 hooks 儲存在外掛程式根目錄的 `hooks/hooks.json` 中,在頂層 `"hooks"` 鍵下,形狀與 `settings.json` 中的 `hooks` 物件相同。這讓您可以複製現有的設定 hook 而不變更。332[hook](/docs/zh-TW/hooks-guide) 在 Claude Code 生命週期中的某個點自動執行某些操作,例如在每次檔案編輯後:shell 命令、HTTP 請求、MCP 工具呼叫、對模型的提示或子代理。將外掛程式的 hooks 儲存在外掛程式根目錄的 `hooks/hooks.json` 中,在頂層 `"hooks"` 鍵下,形狀與 `settings.json` 中的 `hooks` 物件相同。這讓您可以複製現有的設定 hook 而不變更。
766 333
794 361
795若要將 hooks 寫成在 Claude Code 內執行且可以在其介面中繪製的 JavaScript 函式,在相同的 `hooks/hooks.json` 中的 `modules` 鍵下列出模組檔案。具有一個的外掛程式是 mod。請參閱 [建立 mod](/docs/zh-TW/plugins/mods/create)。362若要將 hooks 寫成在 Claude Code 內執行且可以在其介面中繪製的 JavaScript 函式,在相同的 `hooks/hooks.json` 中的 `modules` 鍵下列出模組檔案。具有一個的外掛程式是 mod。請參閱 [建立 mod](/docs/zh-TW/plugins/mods/create)。
796 363
797<h4 id="when-plugin-hooks-fire">364#### 外掛程式 hooks 何時觸發
798 外掛程式 hooks 何時觸發
799</h4>
800 365
801外掛程式的 hooks 不會等待使用外掛程式的 skills 或命令之一。Claude Code 在工作階段載入外掛程式時註冊它們,從那時起它們在其事件上觸發。若要限制 hook 執行的時間,縮小其 `matcher`。366外掛程式的 hooks 不會等待使用外掛程式的 skills 或命令之一。Claude Code 在工作階段載入外掛程式時註冊它們,從那時起它們在其事件上觸發。若要限制 hook 執行的時間,縮小其 `matcher`。
802 367
803如果 hook 從不觸發,請參閱 [不觸發的 hooks](/docs/zh-TW/plugins/troubleshooting#failed-to-load-hooks-from-and-hooks-that-dont-fire)。368如果 hook 從不觸發,請參閱 [不觸發的 hooks](/docs/zh-TW/plugins/troubleshooting#failed-to-load-hooks-from-and-hooks-that-dont-fire)。
804 369
805<h4 id="environment-quoting-and-matching-mcp-tools">370#### 環境、引號和匹配 MCP 工具
806 環境、引號和匹配 MCP 工具
807</h4>
808 371
809hook 的環境、`${CLAUDE_PLUGIN_ROOT}` 的引號和外掛程式自己的 MCP 工具的匹配器工作如下:372hook 的環境、`${CLAUDE_PLUGIN_ROOT}` 的引號和外掛程式自己的 MCP 工具的匹配器工作如下:
810 373
812* **引號**:當 `command` 沒有 `args` 時,它通過 shell 執行,因此將 `${CLAUDE_PLUGIN_ROOT}` 路徑包裝在雙引號中,如 [Hooks](#hooks) 下的 `hooks/hooks.json` 範例所做,以保持展開的路徑為一個 shell 單詞。當您改為傳遞 `args` 時,每個元素作為一個引數傳遞,沒有 shell,不需要引號。請參閱 [exec 形式和 shell 形式](/docs/zh-TW/hooks#exec-form-and-shell-form)375* **引號**:當 `command` 沒有 `args` 時,它通過 shell 執行,因此將 `${CLAUDE_PLUGIN_ROOT}` 路徑包裝在雙引號中,如 [Hooks](#hooks) 下的 `hooks/hooks.json` 範例所做,以保持展開的路徑為一個 shell 單詞。當您改為傳遞 `args` 時,每個元素作為一個引數傳遞,沒有 shell,不需要引號。請參閱 [exec 形式和 shell 形式](/docs/zh-TW/hooks#exec-form-and-shell-form)
813* **匹配外掛程式自己的 MCP 工具**:來自此外掛程式宣告的 [MCP 伺服器](#mcp-servers) 的工具命名為 `mcp__plugin_<plugin>_<server>__<tool>`,因此在匹配器中寫入該完整名稱。僅在伺服器名稱上的匹配器從不觸發。請參閱 [匹配 MCP 工具](/docs/zh-TW/hooks#match-mcp-tools)376* **匹配外掛程式自己的 MCP 工具**:來自此外掛程式宣告的 [MCP 伺服器](#mcp-servers) 的工具命名為 `mcp__plugin_<plugin>_<server>__<tool>`,因此在匹配器中寫入該完整名稱。僅在伺服器名稱上的匹配器從不觸發。請參閱 [匹配 MCP 工具](/docs/zh-TW/hooks#match-mcp-tools)
814 377
815<h3 id="mcp-servers">378### MCP 伺服器
816 MCP 伺服器
817</h3>
818 379
819MCP 伺服器從外部系統為 Claude 提供工具。在外掛程式根目錄的 `.mcp.json` 中宣告它,形狀與 [專案 `.mcp.json`](/docs/zh-TW/mcp#project-scope) 相同。此 `.mcp.json` 宣告一個命名為 `db` 的伺服器:380MCP 伺服器從外部系統為 Claude 提供工具。在外掛程式根目錄的 `.mcp.json` 中宣告它,形狀與 [專案 `.mcp.json`](/docs/zh-TW/mcp#project-scope) 相同。此 `.mcp.json` 宣告一個命名為 `db` 的伺服器:
820 381
839 400
840`mcpServers` manifest 鍵採用內嵌伺服器對應、JSON 檔案的路徑或這些的陣列。當 manifest 伺服器與 `.mcp.json` 中的伺服器同名時,manifest 伺服器取代它。401`mcpServers` manifest 鍵採用內嵌伺服器對應、JSON 檔案的路徑或這些的陣列。當 manifest 伺服器與 `.mcp.json` 中的伺服器同名時,manifest 伺服器取代它。
841 402
842<h4 id="reach-users-on-claude-ai-and-cowork">403#### 到達 claude.ai 和 Cowork 上的使用者
843 到達 claude.ai 和 Cowork 上的使用者
844</h4>
845 404
846本機 stdio 伺服器(例如 [MCP 伺服器](#mcp-servers) 下的 `db` 伺服器)在 Claude Code 和在 Claude Desktop 應用程式中在您的機器上執行的 Cowork 工作階段中執行,但不在 claude.ai 上。若要到達那裡的使用者,請透過其 `https://` URL 參考遠端伺服器,claude.ai 和 Cowork 將其作為連接器提供給使用者,如 [將 MCP 連接器與其 skill 捆綁](https://claude.com/docs/plugins/build#bundle-an-mcp-connector-with-its-skill) 所示。405本機 stdio 伺服器(例如 [MCP 伺服器](#mcp-servers) 下的 `db` 伺服器)在 Claude Code 和在 Claude Desktop 應用程式中在您的機器上執行的 Cowork 工作階段中執行,但不在 claude.ai 上。若要到達那裡的使用者,請透過其 `https://` URL 參考遠端伺服器,claude.ai 和 Cowork 將其作為連接器提供給使用者,如 [將 MCP 連接器與其 skill 捆綁](https://claude.com/docs/plugins/build#bundle-an-mcp-connector-with-its-skill) 所示。
847 406
848<h4 id="server-names-tool-names-and-reloads">407#### 伺服器名稱、工具名稱和重新載入
849 伺服器名稱、工具名稱和重新載入
850</h4>
851 408
852伺服器的名稱、變數替換和重新載入行為遵循這些規則:409伺服器的名稱、變數替換和重新載入行為遵循這些規則:
853 410
856* **替換**:`${CLAUDE_PLUGIN_ROOT}` 和其他 [路徑變數](#path-variables-and-persistent-data) 在 `command`、`args` 和 `env` 中被替換。`args` 中不需要引號,因為每個元素作為一個引數傳遞413* **替換**:`${CLAUDE_PLUGIN_ROOT}` 和其他 [路徑變數](#path-variables-and-persistent-data) 在 `command`、`args` 和 `env` 中被替換。`args` 中不需要引號,因為每個元素作為一個引數傳遞
857* **重新載入**:當使用者執行 `/reload-plugins` 且 [重新載入適用](/docs/zh-TW/plugins/cli-reference#reloads-that-change-mcp-tools) 時,配置未變更的伺服器保持其連接。配置已變更的伺服器重新連接,您移除的伺服器斷開連接414* **重新載入**:當使用者執行 `/reload-plugins` 且 [重新載入適用](/docs/zh-TW/plugins/cli-reference#reloads-that-change-mcp-tools) 時,配置未變更的伺服器保持其連接。配置已變更的伺服器重新連接,您移除的伺服器斷開連接
858 415
859<h4 id="include-a-packaged-mcpb-server">416#### 包含打包的 MCPB 伺服器
860 包含打包的 MCPB 伺服器
861</h4>
862 417
863`mcpServers` 鍵也接受打包的伺服器作為 [MCPB 檔案](https://github.com/modelcontextprotocol/mcpb),其副檔名為 `.mcpb` 或較舊的 `.dxt`。將鍵指向檔案,作為外掛程式內的路徑或 `https://` URL:418`mcpServers` 鍵也接受打包的伺服器作為 [MCPB 檔案](https://github.com/modelcontextprotocol/mcpb),其副檔名為 `.mcpb` 或較舊的 `.dxt`。將鍵指向檔案,作為外掛程式內的路徑或 `https://` URL:
864 419
880 435
881如需傳輸和驗證,請參閱 [MCP](/docs/zh-TW/mcp#plugin-provided-mcp-servers)。436如需傳輸和驗證,請參閱 [MCP](/docs/zh-TW/mcp#plugin-provided-mcp-servers)。
882 437
883<h3 id="lsp-servers">438### LSP 伺服器
884 LSP 伺服器
885</h3>
886 439
887LSP 伺服器為 Claude 提供語言的診斷和程式碼導航。如果 [官方程式碼智慧外掛程式](/docs/zh-TW/plugins/code-intelligence) 已涵蓋您的語言,請安裝該外掛程式而不是寫一個。否則在外掛程式根目錄的 `.lsp.json` 中宣告伺服器:440LSP 伺服器為 Claude 提供語言的診斷和程式碼導航。如果 [官方程式碼智慧外掛程式](/docs/zh-TW/plugins/code-intelligence) 已涵蓋您的語言,請安裝該外掛程式而不是寫一個。否則在外掛程式根目錄的 `.lsp.json` 中宣告伺服器:
888 441
915 468
916Claude Code 斷開超過任一限制或將非協議輸出寫入 stdout 的伺服器,並將斷開連接計為 `restartOnCrash` 和 `maxRestarts` 的當機。當您使用 `--debug` 執行時,Claude Code 將命名原因的錯誤寫入偵錯日誌。469Claude Code 斷開超過任一限制或將非協議輸出寫入 stdout 的伺服器,並將斷開連接計為 `restartOnCrash` 和 `maxRestarts` 的當機。當您使用 `--debug` 執行時,Claude Code 將命名原因的錯誤寫入偵錯日誌。
917 470
918<h3 id="executables">471### 可執行檔
919 可執行檔
920</h3>
921 472
922外掛程式根目錄的 `bin/` 中的檔案在啟用外掛程式時位於 Bash 工具的 shell 的 `PATH` 上,因此 Claude 可以將它們作為裸命令執行。新增可執行指令碼:473外掛程式根目錄的 `bin/` 中的檔案在啟用外掛程式時位於 Bash 工具的 shell 的 `PATH` 上,因此 Claude 可以將它們作為裸命令執行。Claude 在 [沙箱](/docs/zh-TW/sandboxing) 之外使用 [PowerShell 工具](/docs/zh-TW/tools-reference#powershell-tool) 執行的命令也能在其 `PATH` 上找到它們,而在沙箱中執行的 PowerShell 命令則不能。新增可執行指令碼:
923 474
924```bash bin/hello-plugin theme={null}475```bash bin/hello-plugin theme={null}
925#!/bin/bash476#!/bin/bash
932 483
933claude.ai 和 Cowork 不安裝具有頂層 `bin/` 目錄的外掛程式,包括您 [透過 claude.ai 組織設定分發](https://claude.com/docs/plugins/org-sync#keep-executables-out-of-the-top-level-bin-directory) 的外掛程式。484claude.ai 和 Cowork 不安裝具有頂層 `bin/` 目錄的外掛程式,包括您 [透過 claude.ai 組織設定分發](https://claude.com/docs/plugins/org-sync#keep-executables-out-of-the-top-level-bin-directory) 的外掛程式。
934 485
935<h3 id="default-settings">486### 預設設定
936 預設設定
937</h3>
938 487
939若要設定在啟用外掛程式時適用的預設值,在外掛程式根目錄新增 `settings.json`,或將相同的物件內嵌放在 `settings` manifest 鍵中。兩個鍵生效,`agent` 和 `subagentStatusLine`,所有其他鍵都被丟棄。488若要設定在啟用外掛程式時適用的預設值,在外掛程式根目錄新增 `settings.json`,或將相同的物件內嵌放在 `settings` manifest 鍵中。兩個鍵生效,`agent` 和 `subagentStatusLine`,所有其他鍵都被丟棄。
940 489
958 507
959如需 `subagentStatusLine` 形狀,請參閱 [子代理狀態行](/docs/zh-TW/statusline#subagent-status-lines)。508如需 `subagentStatusLine` 形狀,請參閱 [子代理狀態行](/docs/zh-TW/statusline#subagent-status-lines)。
960 509
961<h3 id="themes-and-output-styles">510### 主題和輸出樣式
962 主題和輸出樣式
963</h3>
964 511
965外掛程式可以包含色彩主題和輸出樣式。兩者都出現在與使用者自己相同的選擇器中。對於任一個,設定 manifest 鍵取代資料夾掃描。512外掛程式可以包含色彩主題和輸出樣式。兩者都出現在與使用者自己相同的選擇器中。對於任一個,設定 manifest 鍵取代資料夾掃描。
966 513
984}531}
985```532```
986 533
987<h3 id="channels">534### 頻道
988 頻道
989</h3>
990 535
991[頻道](/docs/zh-TW/channels) 讓外部系統(例如聊天應用程式)將訊息傳送到工作階段。在外掛程式中,頻道是 MCP 伺服器之一加上 `channels` 項目,該項目綁定到它並可以提示其自己的配置。此 manifest 將頻道綁定到 `telegram` 伺服器並要求機器人令牌:536[頻道](/docs/zh-TW/channels) 讓外部系統(例如聊天應用程式)將訊息傳送到工作階段。在外掛程式中,頻道是 MCP 伺服器之一加上 `channels` 項目,該項目綁定到它並可以提示其自己的配置。此 manifest 將頻道綁定到 `telegram` 伺服器並要求機器人令牌:
992 537
1020 565
1021如需伺服器必須實現的內容以及使用者如何啟用頻道外掛程式,請參閱頻道參考中的 [打包為外掛程式](/docs/zh-TW/channels-reference#package-as-a-plugin)。如需欄位表,請參閱 [`channels`](/docs/zh-TW/plugins/manifest-reference#channels)。566如需伺服器必須實現的內容以及使用者如何啟用頻道外掛程式,請參閱頻道參考中的 [打包為外掛程式](/docs/zh-TW/channels-reference#package-as-a-plugin)。如需欄位表,請參閱 [`channels`](/docs/zh-TW/plugins/manifest-reference#channels)。
1022 567
1023<h3 id="monitors">568### 監視器
1024 監視器
1025</h3>
1026 569
1027監視器是在整個工作階段的背景中執行的 shell 命令。它列印的內容作為通知到達 Claude,因此 Claude 可以對日誌或狀態變更做出反應,而無需被要求監視它。將項目儲存在 `monitors/monitors.json` 中:570監視器是在整個工作階段的背景中執行的 shell 命令。它列印的內容作為通知到達 Claude,因此 Claude 可以對日誌或狀態變更做出反應,而無需被要求監視它。將項目儲存在 `monitors/monitors.json` 中:
1028 571
1048 591
1049如需 `when` 觸發器和其他欄位,請參閱 [`monitors`](/docs/zh-TW/plugins/manifest-reference#monitors)。592如需 `when` 觸發器和其他欄位,請參閱 [`monitors`](/docs/zh-TW/plugins/manifest-reference#monitors)。
1050 593
1051<h2 id="user-configuration">594## 要求使用者提供設定值
1052 要求使用者提供設定值
1053</h2>
1054 595
1055在 `userConfig` manifest 鍵中宣告您的外掛程式需要的使用者值,以便使用者不會自行編輯 `settings.json`。每個選項在對話方塊中顯示,其 `title` 作為標籤,其 `description` 在下方。596在 `userConfig` manifest 鍵中宣告您的外掛程式需要的使用者值,以便使用者不會自行編輯 `settings.json`。每個選項在對話方塊中顯示,其 `title` 作為標籤,其 `description` 在下方。
1056 597
1077}618}
1078```619```
1079 620
1080<h3 id="when-the-configuration-dialog-appears">621### 設定對話方塊何時出現
1081 設定對話方塊何時出現
1082</h3>
1083 622
1084對話方塊是互動式 `/plugin` 介面的一部分。當使用者執行以下任何操作時,它會為任何尚未設定的選項開啟:623對話方塊是互動式 `/plugin` 介面的一部分。當使用者執行以下任何操作時,它會為任何尚未設定的選項開啟:
1085 624
1097 636
1098如需選項欄位、每個值儲存的位置、元件如何參考已儲存的值以及哪些欄位拒絕 `${user_config.*}`,請參閱 [使用者設定](/docs/zh-TW/plugins/manifest-reference#user-configuration)。637如需選項欄位、每個值儲存的位置、元件如何參考已儲存的值以及哪些欄位拒絕 `${user_config.*}`,請參閱 [使用者設定](/docs/zh-TW/plugins/manifest-reference#user-configuration)。
1099 638
1100<h2 id="path-variables-and-persistent-data">639## 參考外掛程式路徑和儲存資料
1101 參考外掛程式路徑和儲存資料
1102</h2>
1103 640
1104您不知道您的外掛程式將安裝在哪裡,因此透過這些變數而不是固定路徑參考其檔案和資料。它們在 skill、命令和 agent 內容、hook 和監視器命令以及 MCP 和 LSP 伺服器配置中被替換。它們也被匯出到 hook、MCP 和 LSP 程序:641您不知道您的外掛程式將安裝在哪裡,因此透過這些變數而不是固定路徑參考其檔案和資料。它們在 skill、命令和 agent 內容、hook 和監視器命令以及 MCP 和 LSP 伺服器配置中被替換。它們也被匯出到 hook、MCP 和 LSP 程序:
1105 642
1111 648
1112在 Windows 上,替換的路徑使用正斜杠,因此 shell 不會將反斜杠讀取為逸出。649在 Windows 上,替換的路徑使用正斜杠,因此 shell 不會將反斜杠讀取為逸出。
1113 650
1114<h3 id="install-dependencies-into-the-data-directory">651### 將相依性安裝到資料目錄
1115 將相依性安裝到資料目錄
1116</h3>
1117 652
1118對於市場安裝的外掛程式,Claude Code 在快取外掛程式時自動安裝符合條件的 [Node.js 套件相依性](/docs/zh-TW/plugins/loading#node-js-package-dependencies),因此您可能不需要自行安裝它們。當您執行時,此 `SessionStart` hook 在首次執行時將 `node_modules` 安裝到 `${CLAUDE_PLUGIN_DATA}` 中,並在更新變更 `package.json` 後再次安裝:653對於市場安裝的外掛程式,Claude Code 在快取外掛程式時自動安裝符合條件的 [Node.js 套件相依性](/docs/zh-TW/plugins/loading#node-js-package-dependencies),因此您可能不需要自行安裝它們。當您執行時,此 `SessionStart` hook 在首次執行時將 `node_modules` 安裝到 `${CLAUDE_PLUGIN_DATA}` 中,並在更新變更 `package.json` 後再次安裝:
1119 654
1136 671
1137在第一個工作階段後,`~/.claude/plugins/data/<id>/node_modules` 存在。MCP 伺服器然後可以在其 `env` 中設定 `NODE_PATH` 為 `${CLAUDE_PLUGIN_DATA}/node_modules`。如需哪些欄位替換哪個變數,請參閱 [環境變數](/docs/zh-TW/plugins/manifest-reference#environment-variables)。672在第一個工作階段後,`~/.claude/plugins/data/<id>/node_modules` 存在。MCP 伺服器然後可以在其 `env` 中設定 `NODE_PATH` 為 `${CLAUDE_PLUGIN_DATA}/node_modules`。如需哪些欄位替換哪個變數,請參閱 [環境變數](/docs/zh-TW/plugins/manifest-reference#environment-variables)。
1138 673
1139<h2 id="next-steps">674## 後續步驟
1140 後續步驟
1141</h2>
1142 675
1143* [外掛程式 manifest 參考](/docs/zh-TW/plugins/manifest-reference):`plugin.json` 欄位、路徑規則和標準配置676* [外掛程式 manifest 參考](/docs/zh-TW/plugins/manifest-reference):`plugin.json` 欄位、路徑規則和標準配置
1144* [使用 evals 測試外掛程式](/docs/zh-TW/plugin-evals):檢查您新增的元件以您的意圖改變 Claude 的行為677* [使用 evals 測試外掛程式](/docs/zh-TW/plugin-evals):檢查您新增的元件以您的意圖改變 Claude 的行為