← 團隊介紹← Team Intro AIS 系列 · 2 / 3 · 導覽之旅AIS Series · 2 / 3 · Guided Tour 架構稽核 →Arch Audit →
實戰指南 · 2026 年 4 月 A FIELD GUIDE · APRIL 2026

不肯聽話的插件 The Plugin That Wouldn't Listen

一份完整記錄:為什麼 Claude Code 插件的斜線命令一直「消失」— 以及一個閉環修復長什麼樣,從頭說起。 A complete account of why a Claude Code plugin's slash commands kept disappearing — and what a closed-loop fix actually looks like, told from the very beginning.

auto-claude-ideation-suite v1.0.0 → v1.0.1 commit f9e187c 約 12 分鐘閱讀~12 min read

偶爾你寫了一段軟體、出貨了,然後悄悄成了唯一知道讓它運作的魔法咒語的人。使用者輸入 /something,沒反應,他們聳聳肩換個更長的短語,宇宙每二十次配合一次,所有人都說這工具「有點靈異」。這就是其中一個工具的故事 — 以及那個讓差異從 「偶爾有用」 變成 「每次都有用」 的、出人意料地微小的木工活。 Every now and then you write a piece of software, ship it, and quietly become the only person who knows the magic spell that makes it work. The user types /something, nothing happens, they shrug and try a longer phrase, the universe cooperates once in twenty tries, and everyone agrees the tool is "kind of finicky." This is the story of one such tool — and the surprisingly small piece of carpentry that makes the difference between "sometimes works" and "works every time."

如果你從未寫過 Claude Code 插件、從未用過、甚至從未聽說過 Claude Code — 更好。從使用者的起點開始,故事更有趣:一個沒有做到它宣稱能做的事的東西,以及一個固執地拒絕把這稱為「使用者錯誤」的態度。 If you have never written a Claude Code plugin, never used one, never even heard of Claude Code — good. The story is more interesting if you start where the user started: with a thing that wasn't doing what it claimed, and a stubborn refusal to call it "user error."

SECTION 01Claude Code 是什麼,為何有插件?What is Claude Code, and why does it have plugins?

Claude Code 是 Anthropic 製作的命令列程式,以一種刻意貼近軟體工程師工作方式的形式,在你的終端機裡執行 AI 助手 Claude。你可以讀檔、編輯、執行 shell 命令、查文件、瀏覽網站。AI 透過工具做這些事,人類負責監督。 Claude Code is a command-line program made by Anthropic that runs an AI assistant — Claude — inside your terminal, in a way that's intentionally close to how a software engineer actually works. You can read files, edit them, run shell commands, look up documentation, browse a website. The AI does these things through tools, and the human supervises.

開箱即用,Claude Code 懂得做一般程式開發。但它不了解你團隊的編碼規範、你喜歡的專案管理工作流,或是你一直在手動重複的那些特定多步驟儀式。這就是插件的用武之地。 Out of the box, Claude Code knows how to do general programming. It does not, however, know about your team's coding conventions, your favourite project-management workflows, or the specific multi-step rituals you keep performing by hand. That's where plugins come in.

一個插件是一個資料夾,安裝後教 Claude Code 新招。不同種類的招式:可以輸入的新斜線命令、Claude 可以決定呼叫的背景「技能」、Claude 可以呼叫來做專門工作的子代理,甚至你自己寫的全新工具 — 助手可以呼叫它們。 A plugin is a folder of files that, when installed, teaches Claude Code new tricks. Different kinds of tricks: new slash commands you can type, new background "skills" Claude can decide to invoke, new sub-agents Claude can spawn for specialised work, even brand-new tools — written by you, in code — that the assistant can call.

心智模型Mental model

把 Claude Code 想成剛踏進你辦公室的聰明、訓練有素的實習生。插件是一套標準作業程序、一個專家通訊錄、幾件客製化儀器 — 全部裝在一個資料夾裡 — 讓實習生不再問問題,直接開始做事。 Think of Claude Code as a clever, well-trained intern who just walked into your office. A plugin is a set of standard operating procedures, a Rolodex of specialists, and a few custom instruments — all delivered in one folder — so the intern stops asking and starts doing.

SECTION 02一個插件到底包含什麼?What does a plugin actually contain?

Claude Code 插件就是磁碟上的一個目錄。這個目錄有少數幾個 Claude Code 安裝插件時會查看的慣例位置。把檔案放在對的資料夾,Claude Code 就會讀取。放在錯的資料夾,或根本不放,就是隱形的。 A Claude Code plugin is just a directory on disk. The directory has a small number of conventional places that Claude Code looks at when the plugin is installed. Put files in the right folders and Claude Code will pick them up. Put them in the wrong folders, or in no folders at all, and they're invisible.

這是這個故事中真正重要的部分,所以讓我們直白地畫出來。 This is the part of the story that really matters, so let's draw it out plainly.

資料夾 1FOLDER 1
commands/
這裡的每個 .md 檔變成一個斜線命令。commands/foo.md 表示使用者可以輸入 /foo。檔案的前幾行(frontmatter)描述它。 Each .md file here becomes a slash command. commands/foo.md means the user can type /foo. The first lines of the file (the "frontmatter") describe it.
資料夾 2FOLDER 2
skills/
Skills 是更豐富的行為,Claude 可以在對話暗示相關時決定呼叫。它們透過描述和關鍵字配對,而非精確的斜線名稱。 Skills are richer behaviours that Claude can choose to invoke when the conversation suggests they're relevant. They're matched by description and keywords, not by exact slash names.
資料夾 3FOLDER 3
agents/
子代理是一個專門做一件工作的特化 Claude。插件可以附帶許多;主 Claude 呼叫它所需的任何一個。每個代理的 frontmatter 宣告它的名稱和工具。 A sub-agent is a specialised Claude that handles one job. The plugin can ship many; the main Claude spawns whichever it needs. Each agent file's frontmatter declares its name and tools.
資料夾 4FOLDER 4
.mcp.json + (your code)
插件可以附帶一整個本地伺服器 — 用 JavaScript、Python 或任何語言撰寫 — 公開新工具。Claude 像呼叫任何工具一樣呼叫它們。這是插件如何讓助手超越文字的方式。 The plugin can ship a whole local server — written in JavaScript, Python, anything — that exposes new tools. Claude calls them like any other tool. This is how plugins extend the assistant beyond text.
資料夾 5FOLDER 5
.claude-plugin/plugin.json
「護照。」一個小型 JSON 檔案,含有插件的名稱、版本、描述、作者。Claude Code 首先讀取它以知道正在載入什麼。 The "passport." A short JSON file with the plugin's name, version, description, author. Claude Code reads this first to know what it's loading.

就是整個骨架。五個慣例位置。每一個對應一種使用者(和 Claude)與插件內容互動的不同方式。漏掉一個,對應的能力就根本不存在 — 靜靜地。 That's the whole skeleton. Five conventional locations. Each one corresponds to a different way users (and Claude) can interact with the plugin's contents. Miss one, and a corresponding capability simply doesn't exist — silently.

漏掉一個資料夾,那個能力就根本不存在 — 靜靜地。 Miss a folder, and the capability simply doesn't exist — silently.

提前劇透的教訓The lesson, ahead of time

SECTION 03被放到顯微鏡下的插件The plugin under the microscope

被審視的插件叫做 auto-claude-ideation-suite。它的目標很有野心:在 Claude Code 裡複刻一個叫做 Aperant 的現有 macOS 應用程式,那個應用程式使用一小隊 AI 代理來分析程式碼庫並建議改進。 The plugin in question is called auto-claude-ideation-suite. Its purpose is ambitious: it tries to replicate, inside Claude Code, an existing macOS application called Aperant, which uses a small army of AI agents to analyse a codebase and suggest improvements.

作者的目標是把多代理設計做成插件:告訴它去看任何一個專案,它會產出效能、安全、程式品質、文件、UI/UX 的改進點子。然後把那些點子做成路線圖。然後驗證實作了什麼。然後從每個 session 學習。 The author's goal was to take that multi-agent design and make it available as a plugin: tell it to look at any project, and it will produce ideas for performance, security, code quality, documentation, UI/UX. Then build those ideas into a roadmap. Then verify what gets implemented. Then learn from each session.

具體來說,插件包含:Concretely, the plugin contained:

SECTION 04投訴The complaint

使用者的投訴聽起來很平凡:「命令一直消失。」有時輸入 /auto-claude-ideation-suite 會有反應。有時什麼都沒有。有時助手會有點理解,開始掃描專案,但要等很久、用很長的提示才行。沒有一致的方式呼叫插件。 The user's complaint sounded mundane: "the command keeps disappearing." Sometimes typing /auto-claude-ideation-suite would do something. Sometimes nothing. Sometimes the assistant would kind of understand and start scanning the project, but only after a long pause and a longer prompt. There was no consistent way to invoke the plugin.

這類 bug 很容易被輕易略過。肯定是使用者打錯了,或是 AI 今天運轉得比較慢。肯定只要用正確的魔法詞語試足夠多次就會再次起作用。 This is the type of bug that's tempting to dismiss. Surely the user is just typing it wrong, or the AI is having a slow day. Surely if you type the right magic words enough times it'll start working again.

⚐ 重要原則⚐ Important principle

「偶爾有用」不是一個軟性 bug。它是穿著偽裝的結構性 bug。如果相同的輸入產生不同的行為,系統有接線問題。使用者是金絲雀,不是嫌疑人。 "Sometimes works" is not a soft bug. It's a structural bug wearing camouflage. If the same input produces different behaviour, the system has a wiring problem. The user is the canary, not the suspect.

所以我們把投訴當作證據。如果 Claude Code 裡的斜線命令不可靠,要看的地方是插件的 commands 資料夾。我們打開目錄,立刻發現了有趣的東西。 So we treated the complaint as evidence. If a slash command is unreliable in Claude Code, the place to look is the plugin's commands folder. We popped open the directory and immediately found something interesting.

SECTION 05偵探工作:斜線命令從哪來?Detective work: where do slash commands come from?

回想第二節:斜線命令是由 commands/ 目錄中的 .md 檔定義的。就這樣。沒有其他方式。Claude Code 讀取檔案、從 frontmatter 提取 description:、把它們登記為命令,從那一刻起輸入對應的 /name 就啟動該檔案的指令。 Recall from Section 02: slash commands are defined by .md files in a commands/ directory. That's it. There is no other way. Claude Code reads the files, extracts the description: from the frontmatter, registers them as commands, and from that point onward typing the matching /name activates the file's instructions.

所以我們的第一個偵探動作是最簡單的 — 列出資料夾。 So our first investigative move was the simplest possible one — list the folders.

$ ls -la auto-claude-ideation-suite/

.claude-plugin/      # 護照 — 存在the passport — present
agents/              # 17 個代理檔案 — 存在17 agent files — present
mcp_tools/           # 工具文件 — 存在tool docs — present
skills/              # skill 協定 — 存在skill protocol — present
src/                 # TypeScript 原始碼 — 存在TypeScript source — present
.mcp.json            # MCP 伺服器設定 — 存在MCP server config — present
package.json         # node 相依 — 存在node deps — present

# 顯著缺席:conspicuously absent:
commands/            ← 不存在← does not exist

一份目錄清單,中間有個洞 A folder list, with a hole in it

這個插件有你會期待的所有其他成分 — 代理、skills、MCP 工具、護照 — 但就是沒有定義斜線命令的那個資料夾。根本沒有 commands/ 目錄存在過 The plugin had every other ingredient you'd expect — agents, skills, MCP tools, a passport — but not the one folder that defines slash commands. There was no commands/ directory at all.

SECTION 06殘酷的真相The unflattering truth

在插件的 skill 檔案(SKILL.md)裡,作者寫了這樣的使用範例: Inside the plugin's skill file (SKILL.md), the author had written usage examples like this:

# 從 skill 的文件中:From the skill's documentation:
| Command                                    | Effect              |
|--------------------------------------------|---------------------|
| /auto-claude-ideation-suite                | 所有 6 個 ideation 代理All 6 ideation agents
| /auto-claude-ideation-suite ideation       | 只跑 ideationIdeation only
| /auto-claude-ideation-suite roadmap        | 只跑 roadmapRoadmap only
| /auto-claude-ideation-suite qa <id>        | QA verification

再讀一遍。注意到什麼了嗎? Read it again. Notice anything?

這些斜線看起來像斜線命令。它們被寫在一個描述命令的文件表格裡。作者顯然打算讓使用者輸入這些。但 — 這就是接線交叉的地方 — 這些斜線從來就不是真正的斜線命令。它們是 skill 檔案裡的關鍵字觸發器,寄望於 Claude 的模糊匹配器在輸入時能正確解讀它們。 The slashes look like slash commands. They're written in a documentation table that describes commands. The author plainly intended for users to type these. But — and here's where the wires were crossed — the slashes were never actually slash commands. They were keyword triggers in a skill file, hoping Claude's fuzzy matcher would interpret them correctly when typed.

使用者以為自己在做什麼What the user thought they were doing
實際發生的事What was actually happening
輸入 /auto-claude-ideation-suite 呼叫一個已登記的斜線命令,有明確的效果,就像 /help/clear 一樣。 Typing /auto-claude-ideation-suite invokes a registered slash command, which has a defined effect, exactly like /help or /clear.
Claude 掃描訊息、查看所有已安裝的 skills、看到有一個叫做 "Auto Claude Ideation Suite" 的、憑直覺決定這是否夠接近,然後可能或可能不呼叫它。 Claude scans the message, looks at all installed skills, sees that one is called "Auto Claude Ideation Suite", decides on a hunch whether that's a close enough match, and may or may not invoke it.

斜線命令和 skill 關鍵字匹配是兩個完全不同的機制。斜線命令是確定性的 — 每次做同樣的事。Skill 匹配是機率性的:相同輸入、稍微不同的情境、可能有不同的結果。作者記錄了一種、建造了另一種。 Slash commands and skill-keyword matching are two completely different mechanisms. Slash commands are deterministic — they do the same thing every time. Skill matching is probabilistic: same input, slightly different context, possibly different outcome. The author had documented one and built the other.

這就是命令「消失」的原因。它從來就不是一個命令。 That's why the command was "disappearing." It had never been a command at all.

SECTION 07更深的架構The deeper architecture

為了理解為何這個區別重要,想像 Claude Code 如何透過它的各層將單一使用者訊息路由。當你輸入某些東西,Claude Code 依序問: To understand why this distinction matters, picture how Claude Code routes a single user message through its layers. When you type something, Claude Code asks, in order:

第 1 層 · 確定性LAYER 1 · DETERMINISTIC
這是否以已登記的斜線命令開頭?Does this start with a registered slash command?
如果是 — 逐字執行那個命令的指令。這是唯一的確定性入口點。 If yes — execute that command's instructions verbatim. This is the only deterministic entry point.
否則otherwise
第 2 層 · 機率性LAYER 2 · PROBABILISTIC
是否有任何已安裝的 skill 看起來相關?Does any installed skill seem relevant?
Claude 讀取 skill 描述、匹配關鍵字、可能呼叫一個 skill。這取決於模型的判斷 — 相同的提示可能匹配或未能匹配。 Claude reads the skill descriptions, matches keywords, and may invoke a skill. This depends on the model's judgement — same prompt may match or miss.
否則otherwise
第 3 層 · 對話式LAYER 3 · CONVERSATIONAL
視為普通指令。Treat as ordinary instruction.
Claude 按照訊息所說的做,使用它的一般訓練。子代理和 MCP 工具仍然可以呼叫,但只在 Claude 自行決定使用它們時。 Claude does what the message asks, using its general training. Sub-agents and MCP tools are still callable, but only if Claude decides on its own to use them.

如果你建立確定性層,使用者就得到一個每次都會轉動的旋鈕。如果你跳過它,你把整個使用者體驗留給了第二層 — 那個有效時令人愉快、沒效時令人抓狂的層。 If you build the deterministic layer, your users get a knob that always turns. If you skip it, you've left the entire user experience to the second-floor layer — the one that's pleasant when it works and infuriating when it doesn't.

為何這很重要Why this matters

Skills 補充命令,不是替代品。一個建構良好的插件使用命令做常見的、具名的工作流程(「執行稽核」),使用 skills 做那些使用者可能不知道要要求的自發性工作(「嗯,這看起來像是一個安全審查」)。 Skills complement commands. They're not a substitute. A well-built plugin uses commands for the common, named workflows ("run the audit") and uses skills for the spontaneous ones that the user might not know to ask for ("hmm, this looks like a security review").

SECTION 08還有什麼壞了What else was broken

一旦我們知道要找什麼,我們繼續找。缺失的 commands/ 資料夾是頭條問題,但它有同伴。總共 12 個問題,按嚴重性排序。分類如下: Once we knew where to look, we kept looking. The missing commands/ folder turned out to be the headline issue, but it had company. Twelve issues in total, sorted by severity. The triage went like this:

# 等級Tier 問題What was wrong
01P0commands/ 目錄不存在 — 每個有文件記錄的斜線命令都是虛構的。The commands/ directory didn't exist — every documented slash command was fictional.
02P0MCP 伺服器設定為用 npx tsx 啟動,這需要完整安裝的 node_modules — 對開發者沒問題,對其他任何安裝插件的人都壞了。The MCP server was configured to start with npx tsx, which requires a fully-installed node_modules — fine for the developer, broken for anyone else who just installed the plugin.
03P0插件的伺服器有兩個競爭設定 — 一個在 .mcp.json,一個藏在 package.json 裡。Claude Code 只讀第一個;第二個是靜默的幽靈。The plugin had two competing configurations for its server — one in .mcp.json, one buried inside package.json. Claude Code reads only the first; the second was a silent ghost.
04P0TypeScript imports 用了 .ts 副檔名,開發時能用,但程式碼編譯成 JavaScript 後就壞了。TypeScript imports used the .ts file extension, which works at development time but breaks once the code is compiled to JavaScript.
05P0一個路徑解析 helper 使用了在 Windows 上有隱性缺陷的 Node API。跨平台紙割傷。A path-resolution helper used a Node API that's subtly broken on Windows. Cross-platform paper cut.
06P0程式碼使用了必需的執行時函式庫(zod),但沒在 package.json 的 dependencies 中宣告 — 它只是碰巧透過傳遞依賴存在。A required runtime library (zod) was used by the code but not declared in package.json's dependencies — it just happened to be present transitively.
07P1插件的 manifest 聲稱附帶 16 個代理。實際上有 17 個。The plugin's manifest claimed it shipped 16 agents. There were 17.
08P1manifest 缺少所有其他 Claude Code 插件都有的 homepagerepository 欄位。The manifest was missing the homepage and repository fields that every other Claude Code plugin includes.
09P1skill 的名稱用 TitleCase 加空格(Auto Claude Ideation Suite),而非其他人都用的慣例:kebab-case。The skill's name was written in TitleCase with spaces (Auto Claude Ideation Suite) instead of the convention everyone else uses: kebab-case.
10P117 個代理檔案都沒有把它們登記為正式子代理所需的 YAML frontmatter。在結構上它們只是文字。None of the 17 agent files had the YAML frontmatter required to register them as proper sub-agents. They were structurally just text.
11P2編譯後的 dist/ 資料夾在 .gitignore 裡,意味著安裝插件的任何人在運行之前都必須自己編譯 TypeScript。The compiled dist/ folder was in .gitignore, meaning anyone installing the plugin had to compile the TypeScript themselves before it would run.
12P2沒有持續整合 — 沒有任何東西在每次更改時檢查插件是否仍然能建置、結構是否仍然有效。There was no continuous integration — nothing checking, on every change, that the plugin still built and the structure was still valid.

這些都不是罪。它們是快速寫出的專案完全正常的積累物。但每一個單獨地,都會破壞使用者可能靜靜遇到的東西。合在一起,它們解釋了為何插件感覺不可靠:使用者每次都在不同的一個上絆倒。 None of these are sins. They're the entirely normal accretions of a project written quickly. But each one, individually, breaks something a user might quietly run into. Together, they explain why the plugin felt unreliable: the user was tripping over a different one each time.

SECTION 09修復,逐步說明The fix, step by step

修復清單對應稽核清單。我們分三批處理 — 先 P0,因為那些直接破壞插件;接著 P1,用於規範合規;最後 P2,用於衛生。 The repair list mirrors the audit list. We worked through it in three batches — P0 first because those break the plugin outright; P1 next for spec compliance; P2 last for hygiene.

批次 1 · P0 — 讓它真的能跑Batch 1 · P0 — Make it actually run

建立了缺失的 commands/ 資料夾,含四個入口點。每個是含一行描述的 .md 檔,讓 Claude Code 可以列出並確定性地路由到它們。 Created the missing commands/ folder with four entry points. Each is a .md file with a one-line description so Claude Code can list them and route to them deterministically.

commands/auto-claude-ideation-suite.md   # 主入口master entry
commands/ideation.md                      # /ideation
commands/roadmap.md                       # /roadmap
commands/qa.md                            # /qa <item-id>

將 MCP 伺服器的啟動命令從 npx tsx mcp-server.ts(需要開發環境)切換到 node dist/mcp-server.js(只需要 Node 本身)。然後提交編譯後的 dist/ 輸出,使它隨插件一起出貨。最終結果:全新安裝無需先執行 npm install 即可啟動。 Switched the MCP server's startup command from npx tsx mcp-server.ts (which needs the dev environment) to node dist/mcp-server.js (which only needs Node itself). Then committed the compiled dist/ output so it ships with the plugin. End result: a fresh install boots without running npm install first.

package.json 移除重複設定塊,所以現在伺服器如何啟動只有一個真相來源:.mcp.json Removed the duplicate configuration block from package.json so there is now exactly one source of truth for how the server starts: .mcp.json.

走過 TypeScript 原始碼,把每個 .ts import 後綴改為 .js。編譯後那些檔名是 JavaScript,執行時需要在編譯後的名稱下找到它們。在三個檔案中修復。 Walked through the TypeScript source and changed every .ts import suffix to .js. After compilation those filenames are JavaScript, and the runtime needs to find them under their compiled names. Fixed in three files.

批次 2 · P1 — 使它合規Batch 2 · P1 — Make it conform

更新 plugin.json:更正計數為 17、新增 homepagerepository 欄位、版本升至 1.0.1。 Updated plugin.json: corrected the count to 17, added homepage and repository fields, bumped the version to 1.0.1.

將 skill 從 "Auto Claude Ideation Suite" 重命名為 auto-claude-ideation-suite — kebab-case、機器可讀、匹配資料夾名稱。 Renamed the skill from "Auto Claude Ideation Suite" to auto-claude-ideation-suite — kebab-case, machine-readable, matching the folder name.

寫了一個短 Python 腳本為 17 個代理的每個前置 YAML frontmatter。每個 frontmatter 塊聲明代理的 name、一行 description,以及它可以使用的 tools 清單。此更改後,代理成為正式子代理 — Claude 可以透過 Task 工具按名稱呼叫它們中的任何一個。 Wrote a short Python script to prepend YAML frontmatter to each of the 17 agents. Each frontmatter block declares the agent's name, a one-line description, and the list of tools it can use. After this change, the agents become proper sub-agents — Claude can spawn any of them by name through the Task tool.

--- 修改前(第 1 行):Before (line 1):
# Performance Optimizations Ideation Agent

--- 修改後(現在是 6 行):After (now 6 lines):
---
name: performance
description: Identify performance bottlenecks across runtime, bundle size, ...
tools: Read, Grep, Glob, Bash, Edit, Write
---

# Performance Optimizations Ideation Agent

批次 3 · P2 — 使它可持續Batch 3 · P2 — Make it sustainable

.gitignore 移除 dist/ 並提交編譯輸出。未來安裝插件無需建置步驟。 Removed dist/ from .gitignore and committed the compiled output. Future installs of the plugin work without a build step.

新增了針對自託 Mac Mini runner 的持續整合工作流。每次 push 和 pull request 現在依序驗證:相依性安裝乾淨、TypeScript 編譯無錯、所有六個預期的 JavaScript 產物存在於 dist/、MCP 伺服器可以啟動(冒煙啟動)、插件的結構文件存在(commands ≥ 4、agents = 17、manifest 存在)、每個代理的第一行是 frontmatter 分隔符。 Added a continuous-integration workflow targeting a self-hosted Mac Mini runner. Every push and pull request now verifies: dependencies install cleanly, TypeScript compiles without errors, all six expected JavaScript artifacts exist in dist/, the MCP server can start (smoke boot), the plugin's structural files are present (commands ≥ 4, agents = 17, manifest exists), every agent's first line is a frontmatter delimiter.

SECTION 10我們如何驗證How we verified

稽核在你能看到差異之前是不可信的。所以在每一步,我們執行實際命令並閱讀實際輸出,而不是推理應該發生了什麼。三個檢查點帶來了證明: An audit isn't trustworthy until you can see the difference. So at every step we ran the actual command and read the actual output rather than reasoning about what should have happened. Three checkpoints carried the proof:

檢查點 1 · 建置Checkpoint 1 · Build

執行 npm run build 產生退出碼 0,並在 dist/ 下發出六個 JavaScript 檔案 — 一個伺服器入口,五個 helper 模組。修復前,相同命令發出關於 .ts import 後綴的錯誤。 Running npm run build produced exit code 0 and emitted six JavaScript files under dist/ — one for the server entry, five for the helper modules. Before the fix, the same command emitted errors about .ts import suffixes.

檢查點 2 · 啟動Checkpoint 2 · Boot

node dist/mcp-server.js 啟動編譯後的伺服器沒有產生錯誤,並在 stdin 關閉時乾淨地退出 — 這是 stdio MCP 伺服器的預期行為。啟動路徑使用 Node,沒有 tsx、沒有 npx、沒有編譯。任何安裝插件的人都可以運行它。 Starting the compiled server with node dist/mcp-server.js produced no errors and exited cleanly when stdin closed — the expected behaviour for a stdio MCP server. The boot path uses only Node, no tsx, no npx, no compilation. Anyone who installs the plugin can run it.

檢查點 3 · 結構Checkpoint 3 · Structure

一個簡單的 shell 迴圈確認所有 17 個代理現在以 ---(YAML frontmatter 分隔符)開頭。commands/ 目錄包含四個預期的檔案。manifest 報告 17 個代理。CI 工作流對此全部進行編碼,使未來的回歸破壞建置。 A simple shell loop confirmed all 17 agents now begin with --- (the YAML frontmatter delimiter). The commands/ directory contains the four expected files. The manifest reports 17 agents. The CI workflow encodes all of this so future regressions break the build.

然後我們做了一個包含整個更改的單一 git commit。commit 訊息足夠描述性,六個月後任何閱讀歷史記錄的人都可以重建這個故事。 Then we made a single git commit with the entire change. The commit message is descriptive enough that anyone reading the history six months from now can reconstruct the story.

commit f9e187c
fix: align plugin to spec — slash commands, agent
     frontmatter, build pipeline

- Add commands/ with 4 slash command entry points
  (was missing — root cause of /auto-claude-
  ideation-suite invocations failing silently)
- Add YAML frontmatter to all 17 agents
- Switch MCP server to compiled dist/
- Update plugin.json: 16→17 agents, +homepage/repo
- Skill name → kebab-case
- Ship dist/ in repo (no npm install required)
- Add Mac Mini self-hosted CI

SECTION 11啟示Takeaways

如果你自己在建構 Claude Code 插件 — 或你剛安裝了一個,正盯著一個不觸發的斜線命令 — 這裡是從這個故事中提煉的教訓,大致按節省你時間的順序排列。 If you're building a Claude Code plugin yourself — or you've just installed one and you're staring at a slash command that doesn't fire — here are the lessons distilled from this story, in roughly the order they'll save you time.

1 · 斜線命令和 skill 關鍵字不是同一個機制。Slash commands and skill keywords are not the same mechanism.

如果你想讓使用者輸入 /foo每次都有反應,你需要 commands/foo.md。如果你也想讓 Claude 在看起來相關時主動提供同樣的工作流,你可以額外提供一個 skill。同時使用兩個層,知道每個做什麼。 If you want users to type /foo and have something happen every time, you need commands/foo.md. If you also want Claude to volunteer the same workflow when it seems relevant, you can additionally provide a skill. Use both layers, knowing what each one does.

2 · 出貨已編譯的產物。Ship the compiled artifact.

如果你的插件包含 TypeScript,在開發期間建置它並把 dist/ 輸出提交到倉庫。不要讓使用者執行建置步驟。他們沒有為此報名。 If your plugin contains TypeScript, build it during development and commit the dist/ output to the repository. Don't make the user run a build step. They didn't sign up for that.

3 · 設定有一個真相來源。Have one source of truth for configuration.

不要在兩個不同的檔案定義你的 MCP 伺服器。選一個(.mcp.json 是慣例)並刪除另一個。 Don't define your MCP server in two different files. Pick one (.mcp.json is the convention) and delete the other.

4 · 讓你的 manifest 匹配現實。Match your manifest to reality.

如果 plugin.json 說你有 16 個代理,數一下。如果文件描述了命令,確保那些命令是真實的。描述和現實之間的漂移是最便宜修復的 bug 和最尷尬的遺留。 If plugin.json says you have 16 agents, count them. If documentation describes commands, make sure those commands are real. Drift between description and reality is the cheapest bug to fix and the most embarrassing one to leave.

5 · 使用持續整合檢查,哪怕是小的。Use a continuous-integration check, even a small one.

你不需要完整的測試套件來捕捉我們在這裡發現的結構性 bug 類型。一個只執行 npm run build 並檢查 commands/ 不是空的工作流就能捕捉到大部分。 You don't need a full test suite to catch the kinds of structural bugs we found here. A workflow that just runs npm run build and checks that commands/ isn't empty would have caught most of this.

6 · 把「偶爾有用」當作結構診斷。Treat "sometimes works" as a structural diagnosis.

這幾乎永遠不意味著使用者用錯了工具。通常意味著工具有兩條通往同一結果的路徑,其中一條壞了。 It almost never means the user is using the tool wrong. It usually means the tool has two paths to the same outcome and one of them is broken.

✦ ✦ ✦

插件現在有效了。輸入 /auto-claude-ideation-suite 一致地呼叫主入口。/ideation/roadmap/qa 各自直接進入它們的階段。17 個專家代理可按名稱定址。MCP 伺服器只在 Node 上啟動,安裝時不需要建置步驟,執行時不涉及 tsx。持續整合在每次 push 上執行所有這些。 The plugin works now. Typing /auto-claude-ideation-suite consistently invokes the master entry. /ideation, /roadmap, and /qa each go directly to their phases. The 17 specialist agents are addressable by name. The MCP server starts on Node alone, no build step required at install time, no tsx involved at runtime. Continuous integration enforces all of it on every push.

關於這整個練習值得記住的東西不是任何單個修復。是「偶爾有用」「每次都有用」之間的差異,幾乎完全是一個從未建立的資料夾 — 以及一種查看資料夾清單而非責怪使用者的意願。 The thing that's worth remembering about this whole exercise isn't any individual fix. It's that the difference between "sometimes works" and "works every time" was, almost entirely, a folder that hadn't been created — and a willingness to look at the folder list rather than blame the user.