diff --git a/README.md b/README.md index f4eb088..ba7386b 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Or search for **Patchloom** in the Extensions view (`Ctrl+Shift+X` / `Cmd+Shift+ scoop bucket add patchloom https://github.com/patchloom/scoop-bucket scoop install patchloom # Windows (Scoop; preferred PATH channel) ``` - On Windows, prefer the extension managed installer or Scoop. `npm install -g patchloom` is supported: it puts `patchloom.cmd` on `PATH`, and the extension launches that shim through `cmd.exe`. If Show Status says `spawn EINVAL`, the extension build is one that does not launch `.cmd` shims. Avoid winget and Chocolatey for install or upgrade: both lag GitHub Releases and often leave you on an old CLI. The extension activates when the window finishes starting, including in a folder that has no `AGENTS.md` yet. Hiding the status bar does not hide the command palette entries. + On Windows, prefer the extension managed installer or Scoop. `npm install -g patchloom` is supported: it puts `patchloom.cmd` on `PATH`, and the extension launches that shim through `cmd.exe`. A path that ends in a backslash is quoted so `cmd.exe` does not swallow the next argument. If Show Status says `spawn EINVAL`, the extension build is one that does not launch `.cmd` shims. Avoid winget and Chocolatey for install or upgrade: both lag GitHub Releases and often leave you on an old CLI. The extension activates when the window finishes starting, including in a folder that has no `AGENTS.md` yet. Hiding the status bar does not hide the command palette entries. 2. Open a project and run **Patchloom: Setup Workspace**
@@ -64,7 +64,7 @@ Run `Patchloom: Setup Workspace` to walk through everything your project needs:
- **Cursor** (`.cursor/mcp.json`)
- **Windsurf** (`~/.codeium/windsurf/mcp_config.json`)
-When configuring, pick **Full tool inventory** (default) or **Core pack**. Core sets `PATCHLOOM_MCP_SURFACE=core` on the server entry. Workspace files (VS Code, portable, and Cursor) store `command` as `patchloom`, not a machine path. A stale absolute path is rewritten. The Windsurf user file may still store the resolved binary path. VS Code also starts a native Patchloom server. Writing `.vscode/mcp.json` adds a second server next to that provider, and the command asks before it writes that file. The native server follows the `patchloom.mcpSurface` setting (`full` or `core`). Existing servers in JSON or JSONC (`//` comments, trailing commas) stay in the file. A config that is not an object is left unchanged and the command reports an error. If an existing file cannot be read, the command reports that error and does not replace it. A missing file is still created.
+When configuring, pick **Full tool inventory** (default) or **Core pack**. Core sets `PATCHLOOM_MCP_SURFACE=core` on the server entry. Workspace files (VS Code, portable, and Cursor) store `command` as `patchloom`, not a machine path. A stale absolute path is rewritten. The Windsurf user file may still store the resolved binary path. VS Code also starts a native Patchloom server. Writing `.vscode/mcp.json` adds a second server next to that provider, and the command asks before it writes that file. Skip that file continues with the other selected configs. Dismissing the question cancels the command and writes nothing. The native server follows the `patchloom.mcpSurface` setting (`full` or `core`). Existing servers in JSON or JSONC (`//` comments, trailing commas) stay in the file. A config that is not an object is left unchanged and the command reports an error. If an existing file cannot be read, the command reports that error and does not replace it. A missing file is still created.
CLI **0.37.5** exposes **66** MCP tools by default (including `explain_plan`, `tidy_check`, `list_files`, `apply_fragment`, `notebook_edit`, and `operation_schema`). The core pack is 12 tools on CLI 0.37+: `read_file`, `search_files`, `list_files`, `replace_text`, `batch_replace`, `doc_get`, `doc_set`, `doc_query`, `md_replace_section`, `execute_plan`, `operation_schema`, `server_info`. `doc` accepts `.jsonc` (comments stay on set), plus `.env`, `.ini`, and `.properties`. `doc_set` accepts `if_exists` to skip a missing file or selector. `apply_patch` accepts `apply=false` for a check-only preview. CLI `list-files` inventories ignore-aware paths the same way as MCP `list_files`. `search_files` accepts `files_without_match` (CLI 0.29+). `apply_patch` accepts unified diffs, Codex `*** Begin Patch`, and Aider SEARCH/REPLACE (CLI 0.30+). `doc_query` can list object keys and count array or object length (CLI 0.32+). Search, replace, and tidy dests accept cwd-only globs such as `*.txt` (CLI 0.33+; use `**/*.txt` or `--glob` for nested files). Absolute paths that resolve inside the MCP workspace root are allowed; empty paths, `../`, and outside paths still reject with stable `error_kind` peels.
@@ -122,7 +122,7 @@ Click it to run **Show Status**. That command writes the full report to the Outp
Content fields open a scratch file so newlines stay newlines. Pattern and anchor fields start with the current selection when it is a single line. Preview copies the file under the workspace and runs the CLI with the workspace as its working directory, so `.patchloom.toml` format commands and EditorConfig match Apply. The preview copy is removed afterward. The diff uses a `patchloom-preview` document, which is not an untitled buffer and is not saved. A preview that finds no pattern says so. A command that exits cleanly and changes nothing says the command made no edit. Search still writes its text to the Output channel, and then offers the hits in a list that opens the file at the matching line. Files without a match open at line 1.
-Workspace Quick Actions and Batch Apply pass `--contain` so CLI paths stay inside the workspace root (CLI 0.10+). Containment is relative to the effective working directory (the workspace folder). Patch apply and patch merge ask for a file or the clipboard, stage that text inside the workspace, show a dry run, and write only after a second confirmation. A dry run that would change files exits 2 with `ok: true` and `applied: false`. That result still reaches the write confirmation. A bad patch or a stale hunk stops before that confirmation. A three-way merge that conflicts, when conflict markers were not allowed, also stops. Nothing is written. Run it again and choose Allow conflict markers to write them. An empty clipboard is an error and does not write. Cancel leaves the files unchanged. A path inside that patch that leaves the workspace is rejected.
+Workspace Quick Actions and Batch Apply pass `--contain` so CLI paths stay inside the workspace root (CLI 0.10+). Containment is relative to the effective working directory (the workspace folder). Patch apply and patch merge ask for a file or the clipboard, copy that text under `.patchloom/` (already gitignored), show a dry run, and write only after a second confirmation. A dry run that would change files exits 2 with `ok: true` and `applied: false`. That result still reaches the write confirmation. A bad patch or a stale hunk stops before that confirmation. A three-way merge that conflicts, when conflict markers were not allowed, also stops. Nothing is written. Run it again and choose Allow conflict markers to write them. An empty clipboard is an error and does not write. Cancel leaves the files unchanged. A path inside that patch that leaves the workspace is rejected.
### Batch operations
diff --git a/src/binary/launch.ts b/src/binary/launch.ts
index 67ee238..378c05b 100644
--- a/src/binary/launch.ts
+++ b/src/binary/launch.ts
@@ -98,8 +98,11 @@ function quoteCmdArgument(value: string): string {
);
}
const escaped = value.replaceAll("%", "%%");
- if (escaped.length === 0 || /[\s"&|<>^()]/.test(escaped)) {
- return `"${escaped.replaceAll("\"", "\"\"")}"`;
+ // A trailing \ escapes the next character. Unquoted, that is the space
+ // before the next argument. Quoted, it escapes the closing quote.
+ if (escaped.length === 0 || /[\s"&|<>^()]/.test(escaped) || escaped.endsWith("\\")) {
+ const quoted = escaped.replaceAll("\"", "\"\"").replace(/\\+$/, (run) => run + run);
+ return `"${quoted}"`;
}
return escaped;
}
diff --git a/src/commands/configureMcp.ts b/src/commands/configureMcp.ts
index 013a567..cc9028b 100644
--- a/src/commands/configureMcp.ts
+++ b/src/commands/configureMcp.ts
@@ -7,6 +7,7 @@ import {
configureMcpTargets,
formatMcpConfigureFailureMessage,
inspectMcpTargets,
+ mcpKindsAfterSecondServerWarning,
McpConfigureError,
readMcpConfigText
} from "../mcp/config.js";
@@ -76,12 +77,15 @@ export async function configureMcp(preset?: vscode.WorkspaceFolder): Promise