new-tool
Use when adding a new MCP tool to Claude in Safari — covers the full workflow from spec through implementation, tests, manifest updates, and PR creation.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when adding a new MCP tool to Claude in Safari — covers the full workflow from spec through implementation, tests, manifest updates, and PR creation.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when the Claude in Safari extension stops working after a code change, build, or Safari restart — specifically when the extension is missing from "Web Extension Background Pages", flashes and disappears, disappears from Safari Settings entirely, or make health fails with timeout.
Use when running the manual regression test suite before merging a PR — covers setup, which sections to always run, known pre-existing failures to skip, and the PR checklist.
| name | new-tool |
| description | Use when adding a new MCP tool to Claude in Safari — covers the full workflow from spec through implementation, tests, manifest updates, and PR creation. |
Follow every step in order. Do not skip pre-work or manifest steps — both are commonly missed.
git checkout -b feature/<tool-name>
docs/specs/NNN-<tool-name>.md before touching any codeClaudeInSafari Extension/Resources/tools/<tool-name>.js| What | Where |
|---|---|
| Tool handler | ClaudeInSafari Extension/Resources/tools/<tool-name>.js |
| JS tests | Tests/JS/<tool-name>.test.js |
| Swift tests | Update Tests/ if ToolRouter changes |
One tool per file. Kebab-case filenames. No shared utility files unless used by 2+ tools.
Two places must stay in sync — both must be updated together:
manifest.json → background.scripts array: add "tools/<tool-name>.js"background.js → load-order comment at top: add matching entryCode review checklist item: verify both are present before requesting review.
npm test # must be green before moving on
npm test passesmake test-swift if any Swift files changed// Bottom of tool file
globalThis.registerTool("tool_name", async (args) => {
const tab = await globalThis.resolveTab(args.virtual_tab_id);
// ...
});
globalThis.resolveTab(virtualTabId) — never re-implementglobalThis.classifyExecuteScriptError for executeScript errorsexecuteScriptWithTabGuard from tool-registry.jsAdd to docs/regression-tests.md:
Before opening PR, verify:
.cancel() method if the promise owns listeners or timersonRemoved listener: navigation settlement rejects immediately on tab closeresolveTab and registerTool used — not re-implementednpm test and make test-swift pass