From 1fe04e59e5024b616087d4573dd3bc1a0b3147ad Mon Sep 17 00:00:00 2001 From: shui4 <1078185271@qq.com> Date: Sun, 14 Jun 2026 00:19:54 +0800 Subject: [PATCH 1/8] feat: optional tool registration via settings.json - Add ToolsConfig type with 24 individual tool toggles - index.ts now respects config before loading each tool - capy-tools-settings always loads (so users can re-enable) - Read config from settings.json capyTools.tools, fallback to capy-tools.json - Write back to both capy-tools.json and settings.json on change - CLI: /capy-tools-settings enable/disable - UI: /capy-tools-settings > Tools menu with toggle switches Closes #2 --- extensions/capy-tools-config.ts | 91 ++++++++++++++++++++++++++++++- extensions/capy-tools-settings.ts | 72 +++++++++++++++++++++++- extensions/index.ts | 56 +++++++++++-------- 3 files changed, 193 insertions(+), 26 deletions(-) diff --git a/extensions/capy-tools-config.ts b/extensions/capy-tools-config.ts index 16441d7..bd38625 100644 --- a/extensions/capy-tools-config.ts +++ b/extensions/capy-tools-config.ts @@ -47,10 +47,42 @@ export type CodexFastConfig = { enabled: boolean; }; +export const ALL_TOOL_IDS = [ + "fetch", + "enable-builtin-search", + "repo-map", + "read-block", + "symbol-outline", + "apply-patch", + "terminal-session", + "ask-user", + "ask-question", + "ask-questionnaire", + "sourcegraph", + "recap", + "message-shape-diagnostic", + "auto-compact", + "codex-fast", + "capy-tools-settings", + "command-history", + "efforts", + "codex-goal", + "rtk", + "thinking-steps", + "todo", + "showsignature", + "working-message", +] as const; + +export type ToolId = (typeof ALL_TOOL_IDS)[number]; + +export type ToolsConfig = Record; + export type CapyToolsSettings = { workingMessage: WorkingMessageSettings; autoCompact: AutoCompactConfig; codexFast: CodexFastConfig; + tools: ToolsConfig; }; export const DEFAULT_WORKING_MESSAGE_SETTINGS: WorkingMessageSettings = { @@ -68,10 +100,15 @@ export const DEFAULT_CODEX_FAST_CONFIG: CodexFastConfig = { enabled: false, }; +export const DEFAULT_TOOLS_CONFIG: ToolsConfig = Object.fromEntries( + ALL_TOOL_IDS.map((id) => [id, true]), +) as ToolsConfig; + export const DEFAULT_CAPY_TOOLS_SETTINGS: CapyToolsSettings = { workingMessage: DEFAULT_WORKING_MESSAGE_SETTINGS, autoCompact: DEFAULT_AUTO_COMPACT_CONFIG, codexFast: DEFAULT_CODEX_FAST_CONFIG, + tools: { ...DEFAULT_TOOLS_CONFIG }, }; export const AUTO_COMPACT_PRESETS = [80, 85, 90, 95] as const; @@ -140,15 +177,29 @@ export function normalizeCodexFastConfig(value: unknown): CodexFastConfig { }; } +export function normalizeToolsConfig(value: unknown): ToolsConfig { + const defaults = { ...DEFAULT_TOOLS_CONFIG }; + if (!value || typeof value !== "object") return defaults; + + const raw = value as Record; + for (const id of ALL_TOOL_IDS) { + if (typeof raw[id] === "boolean") { + (defaults as Record)[id] = raw[id] as boolean; + } + } + return defaults; +} + export function normalizeCapyToolsSettings(value: unknown): CapyToolsSettings { if (!value || typeof value !== "object") return structuredClone(DEFAULT_CAPY_TOOLS_SETTINGS); - const raw = value as { workingMessage?: unknown; autoCompact?: unknown; codexFast?: unknown }; + const raw = value as { workingMessage?: unknown; autoCompact?: unknown; codexFast?: unknown; tools?: unknown }; return { // Legacy cat-whimsical config stored `language` at the top level. workingMessage: normalizeWorkingMessageSettings(raw.workingMessage ?? value), autoCompact: normalizeAutoCompactConfig(raw.autoCompact), codexFast: normalizeCodexFastConfig(raw.codexFast), + tools: normalizeToolsConfig(raw.tools), }; } @@ -170,6 +221,25 @@ async function readJson(path: string): Promise { async function writeSettings(settings: CapyToolsSettings): Promise { await mkdir(dirname(CAPY_TOOLS_CONFIG_PATH), { recursive: true }); await writeFile(CAPY_TOOLS_CONFIG_PATH, `${JSON.stringify(settings, null, 2)}\n`, "utf8"); + // Also sync tools config back to settings.json for unified management + await syncToolsToPiSettings(settings.tools); +} + +async function syncToolsToPiSettings(tools: ToolsConfig): Promise { + try { + const raw = await readJson(LEGACY_PI_SETTINGS_PATH); + const piSettings: Record = (raw && typeof raw === "object") + ? { ...raw as Record } + : {}; + piSettings["capyTools"] = { + ...((piSettings["capyTools"] as Record) ?? {}), + tools, + }; + await mkdir(dirname(LEGACY_PI_SETTINGS_PATH), { recursive: true }); + await writeFile(LEGACY_PI_SETTINGS_PATH, `${JSON.stringify(piSettings, null, 2)}\n`, "utf8"); + } catch { + // Non-fatal: tools still saved to capy-tools.json + } } export async function restoreCapyToolsSettings(): Promise { @@ -214,6 +284,25 @@ export async function restoreCapyToolsSettings(): Promise { } } + currentSettings = next; + + if (!unifiedObject || unifiedObject.tools === undefined) { + const piSettings = await readJson(LEGACY_PI_SETTINGS_PATH); + if (piSettings && typeof piSettings === "object") { + const capyTools = (piSettings as Record)["capyTools"]; + if (capyTools && typeof capyTools === "object") { + const toolsFromSettings = (capyTools as Record)["tools"]; + if (toolsFromSettings) { + next = { + ...next, + tools: normalizeToolsConfig(toolsFromSettings), + }; + shouldWrite = true; + } + } + } + } + currentSettings = next; if (shouldWrite) await writeSettings(currentSettings); return structuredClone(currentSettings); diff --git a/extensions/capy-tools-settings.ts b/extensions/capy-tools-settings.ts index d3704bf..636a19b 100644 --- a/extensions/capy-tools-settings.ts +++ b/extensions/capy-tools-settings.ts @@ -1,6 +1,7 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; import { + ALL_TOOL_IDS, AUTO_COMPACT_PRESETS, DEFAULT_AUTO_COMPACT_CONFIG, KEEP_RECENT_PRESETS, @@ -17,12 +18,14 @@ import { formatCodexFastStatus, setCodexFastEnabled } from "./codex-fast.ts"; function formatSettingsSummary(): string { const settings = getCapyToolsSettings(); + const enabledCount = Object.values(settings.tools).filter(Boolean).length; return [ `Working message language: ${loadLanguageLabel(settings.workingMessage.language)}`, `Auto-compact threshold: ${settings.autoCompact.autoCompactPercent}%`, `Keep recent budget: ${settings.autoCompact.keepRecentPercent}%`, `Strategy: ${STRATEGY_LABELS[settings.autoCompact.strategy]}`, `Codex fast mode: ${settings.codexFast.enabled ? "enabled" : "disabled"}`, + `Tools enabled: ${enabledCount}/${ALL_TOOL_IDS.length}`, ].join("\n"); } @@ -38,6 +41,36 @@ async function setWorkingMessageLanguage(ctx: ExtensionContext, languageText: st return true; } +async function openToolsMenu(ctx: ExtensionContext): Promise { + while (true) { + const settings = getCapyToolsSettings(); + const lines: string[] = []; + for (const id of ALL_TOOL_IDS) { + const icon = settings.tools[id] ? "✅" : "❌"; + lines.push(`${icon} ${id}`); + } + + const choice = await ctx.ui.select( + `Tools\n\n${lines.join("\n")}\n\nSelect a tool to toggle, or Done.`, + [...ALL_TOOL_IDS.map((id) => `${settings.tools[id] ? "Disable" : "Enable"} ${id}`), "Done"], + ); + + if (!choice || choice === "Done") return; + + const match = choice.match(/^(Enable|Disable) (.+)$/); + if (!match) continue; + + const toolId = match[2]; + const enable = match[1] === "Enable"; + + await updateCapyToolsSettings((s) => ({ + ...s, + tools: { ...s.tools, [toolId]: enable }, + })); + ctx.ui.notify(`Tool "${toolId}" ${enable ? "enabled" : "disabled"}. Restart pi or /reload for changes.`, "info"); + } +} + async function openSettingsMenu(ctx: ExtensionContext): Promise { await restoreCapyToolsSettings(); @@ -51,6 +84,7 @@ async function openSettingsMenu(ctx: ExtensionContext): Promise { `Keep recent budget [${settings.autoCompact.keepRecentPercent}%]`, `Compaction strategy [${settings.autoCompact.strategy}]`, `Codex fast mode [${settings.codexFast.enabled ? "enabled" : "disabled"}]`, + "Tools (enable/disable individual tools)", "Auto-compact status", "Codex fast status", "Reset auto-compact defaults", @@ -123,6 +157,11 @@ async function openSettingsMenu(ctx: ExtensionContext): Promise { continue; } + if (choice.startsWith("Tools")) { + await openToolsMenu(ctx); + continue; + } + if (choice === "Auto-compact status") { ctx.ui.notify(formatAutoCompactStatus(ctx), "info"); continue; @@ -158,6 +197,8 @@ export default function capyToolsSettingsExtension(pi: ExtensionAPI): void { "codex-fast off", "codex-fast toggle", "codex-fast status", + "tools", + ...ALL_TOOL_IDS.flatMap((id) => [`enable ${id}`, `disable ${id}`]), "en", "zh", "ja", @@ -203,6 +244,35 @@ export default function capyToolsSettingsExtension(pi: ExtensionAPI): void { return; } + if (trimmed === "tools") { + await openToolsMenu(ctx); + return; + } + + const enableMatch = trimmed.match(/^enable (.+)$/i); + if (enableMatch) { + const toolId = enableMatch[1].trim(); + if (!ALL_TOOL_IDS.includes(toolId as typeof ALL_TOOL_IDS[number])) { + ctx.ui.notify(`Unknown tool: ${toolId}`, "warning"); + return; + } + await updateCapyToolsSettings((s) => ({ ...s, tools: { ...s.tools, [toolId]: true } })); + ctx.ui.notify(`Tool "${toolId}" enabled. Restart pi or /reload for changes.`, "info"); + return; + } + + const disableMatch = trimmed.match(/^disable (.+)$/i); + if (disableMatch) { + const toolId = disableMatch[1].trim(); + if (!ALL_TOOL_IDS.includes(toolId as typeof ALL_TOOL_IDS[number])) { + ctx.ui.notify(`Unknown tool: ${toolId}`, "warning"); + return; + } + await updateCapyToolsSettings((s) => ({ ...s, tools: { ...s.tools, [toolId]: false } })); + ctx.ui.notify(`Tool "${toolId}" disabled. Restart pi or /reload for changes.`, "info"); + return; + } + if (trimmed === "reset-auto-compact" || trimmed === "auto-compact reset") { await persistAutoCompactConfig({ ...DEFAULT_AUTO_COMPACT_CONFIG }); ctx.ui.notify("Auto-compact settings reset to defaults.", "info"); @@ -212,7 +282,7 @@ export default function capyToolsSettingsExtension(pi: ExtensionAPI): void { if (await setWorkingMessageLanguage(ctx, trimmed)) return; ctx.ui.notify( - "Usage: /capy-tools-settings [settings|status|reset-auto-compact|codex-fast on|codex-fast off|en|zh|ja|ko]", + "Usage: /capy-tools-settings [settings|status|tools|enable |disable |codex-fast on|off|en|zh|ja|ko]", "warning", ); }, diff --git a/extensions/index.ts b/extensions/index.ts index d10e27d..17843c0 100644 --- a/extensions/index.ts +++ b/extensions/index.ts @@ -1,4 +1,5 @@ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import { restoreCapyToolsSettings, getCapyToolsSettings } from "./capy-tools-config.ts"; import fetchExtension from "./fetch.ts"; import enableBuiltinSearchExtension from "./enable-builtin-search.ts"; import repoMapExtension from "./repo-map.ts"; @@ -25,34 +26,41 @@ import showsignatureExtension from "./showsignature.ts"; import workingMessageExtension from "./cat-whimsical/index.ts"; export default async function piBasicToolsExtension(pi: ExtensionAPI): Promise { - // Load all tools through one entrypoint so shared renderer state is truly shared. - enableBuiltinSearchExtension(pi); - fetchExtension(pi); - repoMapExtension(pi); - readBlockExtension(pi); - symbolOutlineExtension(pi); - applyPatchExtension(pi); - terminalSessionExtension(pi); - askUserExtension(pi); - askQuestionExtension(pi); - askQuestionnaireExtension(pi); - sourcegraphExtension(pi); - recapExtension(pi); + // Restore user config before deciding which tools to load. + await restoreCapyToolsSettings(); + const tools = getCapyToolsSettings().tools; + + const enabled = (id: string): boolean => tools[id as keyof typeof tools] !== false; + + // enable-builtin-search is always loaded (needed for settings UI tool toggles) + if (enabled("enable-builtin-search")) enableBuiltinSearchExtension(pi); + if (enabled("fetch")) fetchExtension(pi); + if (enabled("repo-map")) repoMapExtension(pi); + if (enabled("read-block")) readBlockExtension(pi); + if (enabled("symbol-outline")) symbolOutlineExtension(pi); + if (enabled("apply-patch")) applyPatchExtension(pi); + if (enabled("terminal-session")) terminalSessionExtension(pi); + if (enabled("ask-user")) askUserExtension(pi); + if (enabled("ask-question")) askQuestionExtension(pi); + if (enabled("ask-questionnaire")) askQuestionnaireExtension(pi); + if (enabled("sourcegraph")) sourcegraphExtension(pi); + if (enabled("recap")) recapExtension(pi); // Opt-in diagnostic: no-op unless PI_BASIC_TOOLS_DIAG_SHAPES is set. - messageShapeDiagnosticExtension(pi); - autoCompactExtension(pi); - codexFastExtension(pi); + if (enabled("message-shape-diagnostic")) messageShapeDiagnosticExtension(pi); + if (enabled("auto-compact")) autoCompactExtension(pi); + if (enabled("codex-fast")) codexFastExtension(pi); + // capy-tools-settings MUST always load — otherwise users can't re-enable tools capyToolsSettingsExtension(pi); - commandHistoryExtension(pi); - effortsExtension(pi); - codexGoalExtension(pi); - await rtkExtension(pi); - thinkingStepsExtension(pi); - todoExtension(pi); - showsignatureExtension(pi); + if (enabled("command-history")) commandHistoryExtension(pi); + if (enabled("efforts")) effortsExtension(pi); + if (enabled("codex-goal")) codexGoalExtension(pi); + if (enabled("rtk")) await rtkExtension(pi); + if (enabled("thinking-steps")) thinkingStepsExtension(pi); + if (enabled("todo")) todoExtension(pi); + if (enabled("showsignature")) showsignatureExtension(pi); // Registered AFTER todoExtension so the Capy Tools working message sits // below the todo overlay in pi's UI (forked from // https://github.com/lulucatdev/pi-cat-whimsical, MIT). See // extensions/cat-whimsical/index.ts header for full attribution. - workingMessageExtension(pi); + if (enabled("working-message")) workingMessageExtension(pi); } From 81ebaed093874c5c0b98b31f7c464cc066b5b655 Mon Sep 17 00:00:00 2001 From: shui4 <1078185271@qq.com> Date: Sun, 14 Jun 2026 00:24:32 +0800 Subject: [PATCH 2/8] fix: move typescript to dependencies (needed at runtime by showsignature) --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e0e1ee1..4c15583 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,9 @@ "./skills" ] }, + "dependencies": { + "typescript": "^6.0.3" + }, "peerDependencies": { "@earendil-works/pi-ai": "*", "@earendil-works/pi-coding-agent": "*", @@ -55,7 +58,6 @@ "@earendil-works/pi-ai": "^0.74.0", "@earendil-works/pi-coding-agent": "^0.74.0", "@earendil-works/pi-tui": "^0.74.0", - "@sinclair/typebox": "^0.34.49", - "typescript": "^6.0.3" + "@sinclair/typebox": "^0.34.49" } } From 28cb91bea7a11c89cacff2ea217b266de4adb7b1 Mon Sep 17 00:00:00 2001 From: shui4 <1078185271@qq.com> Date: Sun, 14 Jun 2026 00:34:26 +0800 Subject: [PATCH 3/8] fix: add postinstall to ensure deps when installed from git --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 4c15583..cb25295 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "access": "public" }, "scripts": { + "postinstall": "npm install --omit=dev 2>/dev/null || true", "test": "bun test", "test:build": "bun build extensions/index.ts extensions/fetch.ts extensions/enable-builtin-search.ts extensions/repo-map.ts extensions/read-block.ts extensions/symbol-outline.ts extensions/apply-patch.ts extensions/terminal-session.ts extensions/ask-user.ts extensions/ask-question.ts extensions/ask-questionnaire.ts extensions/sourcegraph.ts extensions/recap.ts extensions/message-shape-diagnostic.ts extensions/auto-compact.ts extensions/codex-fast.ts extensions/capy-tools-config.ts extensions/capy-tools-settings.ts extensions/command-history.ts extensions/efforts/index.ts extensions/codex-goal/index.ts extensions/rtk/index.ts extensions/thinking-steps/index.ts extensions/todo/index.ts extensions/cat-whimsical/index.ts extensions/showsignature.ts --target=node --external @earendil-works/pi-coding-agent --external @earendil-works/pi-ai --external @earendil-works/pi-tui --external @sinclair/typebox --outdir /tmp/capy-tools-build", "test:tui-capture": "python3 scripts/capture-pi-tui.py --expect 'Explored 3 targets' --expect Outline --expect Read --expect Search --expect-tools-block Outline --expect-tools-block Read --expect-tools-block Search --forbid 'grep grep'", From b434bc4a38b4bf4a7524bb56cf7be2ebe09a8702 Mon Sep 17 00:00:00 2001 From: shui4 <1078185271@qq.com> Date: Sun, 14 Jun 2026 00:41:16 +0800 Subject: [PATCH 4/8] revert: remove settings.json integration, use capy-tools.json only --- extensions/capy-tools-config.ts | 38 --------------------------------- 1 file changed, 38 deletions(-) diff --git a/extensions/capy-tools-config.ts b/extensions/capy-tools-config.ts index bd38625..2f4fe09 100644 --- a/extensions/capy-tools-config.ts +++ b/extensions/capy-tools-config.ts @@ -221,25 +221,6 @@ async function readJson(path: string): Promise { async function writeSettings(settings: CapyToolsSettings): Promise { await mkdir(dirname(CAPY_TOOLS_CONFIG_PATH), { recursive: true }); await writeFile(CAPY_TOOLS_CONFIG_PATH, `${JSON.stringify(settings, null, 2)}\n`, "utf8"); - // Also sync tools config back to settings.json for unified management - await syncToolsToPiSettings(settings.tools); -} - -async function syncToolsToPiSettings(tools: ToolsConfig): Promise { - try { - const raw = await readJson(LEGACY_PI_SETTINGS_PATH); - const piSettings: Record = (raw && typeof raw === "object") - ? { ...raw as Record } - : {}; - piSettings["capyTools"] = { - ...((piSettings["capyTools"] as Record) ?? {}), - tools, - }; - await mkdir(dirname(LEGACY_PI_SETTINGS_PATH), { recursive: true }); - await writeFile(LEGACY_PI_SETTINGS_PATH, `${JSON.stringify(piSettings, null, 2)}\n`, "utf8"); - } catch { - // Non-fatal: tools still saved to capy-tools.json - } } export async function restoreCapyToolsSettings(): Promise { @@ -284,25 +265,6 @@ export async function restoreCapyToolsSettings(): Promise { } } - currentSettings = next; - - if (!unifiedObject || unifiedObject.tools === undefined) { - const piSettings = await readJson(LEGACY_PI_SETTINGS_PATH); - if (piSettings && typeof piSettings === "object") { - const capyTools = (piSettings as Record)["capyTools"]; - if (capyTools && typeof capyTools === "object") { - const toolsFromSettings = (capyTools as Record)["tools"]; - if (toolsFromSettings) { - next = { - ...next, - tools: normalizeToolsConfig(toolsFromSettings), - }; - shouldWrite = true; - } - } - } - } - currentSettings = next; if (shouldWrite) await writeSettings(currentSettings); return structuredClone(currentSettings); From d58487c334f63873a795aafe7c7306597b00604d Mon Sep 17 00:00:00 2001 From: shui4 <1078185271@qq.com> Date: Sun, 14 Jun 2026 00:48:47 +0800 Subject: [PATCH 5/8] fix: command-history Windows path with backslash and colon --- extensions/command-history.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/command-history.ts b/extensions/command-history.ts index b6a0e82..559380f 100644 --- a/extensions/command-history.ts +++ b/extensions/command-history.ts @@ -15,7 +15,7 @@ const HISTORY_DIR = join(homedir(), ".pi", "folder-history"); const MAX_HISTORY = 500; function getHistoryFile(cwd: string): string { - const name = cwd.replace(/\//g, "-"); + const name = cwd.replace(/[\/:]/g, "-"); return join(HISTORY_DIR, `${name}.jsonl`); } From 0282a16e8e0a7fd76077e8a336bf4e7e4deb55d3 Mon Sep 17 00:00:00 2001 From: shui4 <1078185271@qq.com> Date: Sun, 14 Jun 2026 00:50:24 +0800 Subject: [PATCH 6/8] fix: command-history also replace backslash on Windows --- extensions/command-history.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/command-history.ts b/extensions/command-history.ts index 559380f..662bb16 100644 --- a/extensions/command-history.ts +++ b/extensions/command-history.ts @@ -15,7 +15,7 @@ const HISTORY_DIR = join(homedir(), ".pi", "folder-history"); const MAX_HISTORY = 500; function getHistoryFile(cwd: string): string { - const name = cwd.replace(/[\/:]/g, "-"); + const name = cwd.replace(/[\\\/:]/g, "-"); return join(HISTORY_DIR, `${name}.jsonl`); } From df59be1504a42292647450e241a1928eb8873f5d Mon Sep 17 00:00:00 2001 From: shui4 <1078185271@qq.com> Date: Sun, 14 Jun 2026 15:19:15 +0800 Subject: [PATCH 7/8] improve apply_patch description: highlight cross-file capability --- extensions/apply-patch.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extensions/apply-patch.ts b/extensions/apply-patch.ts index 2340579..5fa29fc 100644 --- a/extensions/apply-patch.ts +++ b/extensions/apply-patch.ts @@ -438,10 +438,11 @@ export default function applyPatchExtension(pi: ExtensionAPI): void { pi.registerTool({ name: "apply_patch", label: "apply_patch", - description: "Apply a Codex-style patch to files. Supports add, update, delete, and move operations; absolute paths are allowed and writes run with the extension process' filesystem permissions.", - promptSnippet: "Apply Codex-style patches to files with add/update/delete/move operations", + description: "Apply a patch across one or more files in a single call. Handles add, update, delete, and move across multiple files; absolute paths allowed. Best for cross-file changes where individual edits would be tedious.", + promptSnippet: "Apply patches across multiple files with add/update/delete/move in one call", promptGuidelines: [ - "Use apply_patch for precise multi-file edits when exact text replacement is too awkward.", + "Use apply_patch when a change spans multiple files — all hunks apply in one tool call instead of N separate edits.", + "For single-file edits, the patch tool with old_str/new_str is usually simpler; apply_patch shines for cross-file changes.", "Patch text must start with *** Begin Patch and end with *** End Patch.", "This tool can write absolute paths and delete or move files; inspect paths carefully before using it.", "This tool is a direct extension-process filesystem writer, not the built-in bash approval flow.", From a53905287c17bc86b7767b5dfe32d36047cc8ff1 Mon Sep 17 00:00:00 2001 From: shui4 <1078185271@qq.com> Date: Sun, 14 Jun 2026 15:20:32 +0800 Subject: [PATCH 8/8] remove reference to patch tool (not part of capy-tools) --- extensions/apply-patch.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/apply-patch.ts b/extensions/apply-patch.ts index 5fa29fc..92293ba 100644 --- a/extensions/apply-patch.ts +++ b/extensions/apply-patch.ts @@ -442,7 +442,6 @@ export default function applyPatchExtension(pi: ExtensionAPI): void { promptSnippet: "Apply patches across multiple files with add/update/delete/move in one call", promptGuidelines: [ "Use apply_patch when a change spans multiple files — all hunks apply in one tool call instead of N separate edits.", - "For single-file edits, the patch tool with old_str/new_str is usually simpler; apply_patch shines for cross-file changes.", "Patch text must start with *** Begin Patch and end with *** End Patch.", "This tool can write absolute paths and delete or move files; inspect paths carefully before using it.", "This tool is a direct extension-process filesystem writer, not the built-in bash approval flow.",