mcp-walkthrough 0.1.6 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,7 @@ Text in a terminal isn't enough when you want Claude to explain a solution. MCP
19
19
  - **Selection Reading** — Claude can see what you've highlighted to discuss it further
20
20
  - **Focus Preservation** — Opens files without stealing focus from your terminal
21
21
 
22
- > **Note:** This MCP server requires VS Code. It includes a companion VS Code extension that is automatically installed when you `npm install`.
22
+ > **Note:** This MCP server requires VS Code, VS Code Insiders, or Cursor. It includes a companion VS Code extension that is automatically installed when you `npm install`. The CLI is auto-discovered even if `code` is not in your PATH.
23
23
 
24
24
  ## Installation
25
25
 
@@ -144,15 +144,16 @@ Explanations render as markdown in VS Code comment bubbles. Tips:
144
144
  ## How It Works
145
145
 
146
146
  ```
147
- Claude Code → MCP Server (stdio) → HTTP localhost:7890 → VS Code Extension → Editor API
147
+ Claude Code → MCP Server (stdio) → Unix socket → VS Code Extension → Editor API
148
148
  ```
149
149
 
150
150
  1. Claude calls walkthrough tools via MCP
151
- 2. The MCP server forwards requests to a companion VS Code extension over HTTP
152
- 3. The extension uses the VS Code API to open files, select ranges, and create comment threads
153
- 4. Focus stays in your terminal code appears in the editor beside it
151
+ 2. The MCP server discovers a workspace-specific Unix socket (`/tmp/walkthrough-bridge-<hash>.sock`)
152
+ 3. The VS Code extension listens on a socket derived from the workspace folder path
153
+ 4. Each VS Code window gets its own socket multiple windows work independently
154
+ 5. Focus stays in your terminal — code appears in the editor beside it
154
155
 
155
- The VS Code extension is bundled with the npm package and automatically installed on first run.
156
+ The VS Code extension is bundled with the npm package and automatically installed on `npm install` and on first server start. The CLI is auto-discovered across VS Code, VS Code Insiders, and Cursor on all platforms.
156
157
 
157
158
  ## Development
158
159
 
@@ -162,15 +163,22 @@ The VS Code extension is bundled with the npm package and automatically installe
162
163
  mcp-walkthrough/
163
164
  ├── src/
164
165
  │ ├── index.ts # MCP server entry point, tool registration
165
- │ ├── bridge.ts # HTTP client to VS Code extension
166
+ │ ├── bridge.ts # Unix socket client to VS Code extension
167
+ │ ├── code-cli.ts # Cross-platform VS Code CLI discovery
168
+ │ ├── socket.ts # Socket path computation and discovery
166
169
  │ └── utils/
167
170
  │ └── logger.ts # Pino logger (stderr only)
171
+ ├── scripts/
172
+ │ └── postinstall.cjs # Auto-installs extension on npm install
168
173
  ├── vscode-extension/
169
174
  │ ├── src/
170
175
  │ │ └── extension.ts # VS Code extension (HTTP server, Comments API)
171
176
  │ └── package.json
172
177
  ├── tests/
173
- └── bridge.test.ts
178
+ ├── bridge.test.ts
179
+ │ ├── code-cli.test.ts
180
+ │ ├── postinstall.test.ts
181
+ │ └── socket.test.ts
174
182
  └── docs/
175
183
  ```
176
184
 
@@ -194,19 +202,26 @@ The build script syncs the version from root `package.json` into the extension b
194
202
 
195
203
  ## Troubleshooting
196
204
 
197
- ### Tools return "This MCP server only works from VS Code."
205
+ ### Tools return "No walkthrough bridge socket found"
198
206
 
199
- The MCP server pings the VS Code extension on startup. If the extension isn't running:
207
+ The MCP server discovers the VS Code extension via a Unix socket. If the socket isn't found:
200
208
 
201
209
  1. Make sure you're running Claude Code inside VS Code (not a standalone terminal)
202
210
  2. The extension activates on VS Code startup — try reloading the window (`Cmd+Shift+P` → "Reload Window")
211
+ 3. The socket is workspace-specific — make sure the VS Code window has a folder open
203
212
 
204
213
  ### Extension not installed
205
214
 
206
- The MCP server auto-installs the extension on first run via `code --install-extension`. If this fails:
215
+ The MCP server auto-discovers VS Code, VS Code Insiders, and Cursor CLIs — even when `code` isn't in your PATH. It searches:
207
216
 
208
- 1. Verify the `code` CLI is available in your terminal
209
- 2. Manually install: `code --install-extension path/to/walkthrough-bridge.vsix`
217
+ - **macOS**: `/Applications/*.app/Contents/Resources/app/bin/`
218
+ - **Linux**: `/usr/bin/`, `/usr/local/bin/`, `/snap/bin/`, `/opt/*/bin/`
219
+ - **Windows**: `%LOCALAPPDATA%\Programs\*\bin\`
220
+
221
+ The extension is installed into **all** found editors. If auto-install still fails:
222
+
223
+ 1. Manually install: `code --install-extension path/to/walkthrough-bridge.vsix`
224
+ 2. Or reload the VS Code window after installing the npm package
210
225
 
211
226
  ## Contributing
212
227
 
package/dist/bridge.d.ts CHANGED
@@ -2,6 +2,7 @@ export declare function ensureExtensionInstalled(): void;
2
2
  type BridgeResult = Record<string, unknown>;
3
3
  export declare let bridgeAvailable: boolean | null;
4
4
  export declare function resetBridgeState(): void;
5
+ export declare function _setSocketPath(path: string): void;
5
6
  export declare function checkBridge(): Promise<boolean>;
6
7
  export declare function isBridgeAvailable(): boolean;
7
8
  export declare function openFile(file: string, line: number, endLine?: number, startChar?: number, endChar?: number): Promise<BridgeResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAgBA,wBAAgB,wBAAwB,IAAI,IAAI,CAsB/C;AAED,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5C,eAAO,IAAI,eAAe,EAAE,OAAO,GAAG,IAAW,CAAC;AAElD,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAcpD;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAuBD,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAUvB;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,YAAY,CAAC,CAE/D;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,CAAC,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,YAAY,CAAC,CAElE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC,CAE1D"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAkBA,wBAAgB,wBAAwB,IAAI,IAAI,CAoC/C;AAED,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5C,eAAO,IAAI,eAAe,EAAE,OAAO,GAAG,IAAW,CAAC;AAGlD,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAGD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEjD;AA+DD,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAKpD;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAUvB;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,YAAY,CAAC,CAE/D;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,CAAC,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAEvB;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,YAAY,CAAC,CAElE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC,CAE1D"}
package/dist/bridge.js CHANGED
@@ -1,81 +1,122 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
+ import * as http from "node:http";
3
4
  import { dirname, join } from "node:path";
4
5
  import { fileURLToPath } from "node:url";
6
+ import { resolveAllCodeClis } from "./code-cli.js";
7
+ import { discoverSocket } from "./socket.js";
5
8
  import { logger } from "./utils/logger.js";
6
9
  const __filename = fileURLToPath(import.meta.url);
7
10
  const __dirname = dirname(__filename);
8
11
  const EXTENSION_ID = "undefined_publisher.walkthrough-bridge";
9
12
  const VSIX_PATH = join(__dirname, "../vscode-extension/walkthrough-bridge.vsix");
10
- const BRIDGE_URL = "http://127.0.0.1:7890";
11
13
  export function ensureExtensionInstalled() {
12
- try {
13
- const installed = execSync("code --list-extensions", { encoding: "utf-8" });
14
- if (installed.includes(EXTENSION_ID)) {
15
- logger.info("Walkthrough bridge extension already installed");
16
- return;
17
- }
18
- }
19
- catch {
20
- logger.warn("Could not check installed extensions");
14
+ const clis = resolveAllCodeClis();
15
+ if (clis.length === 0) {
16
+ logger.warn("Could not find VS Code CLI (code, code-insiders, or cursor). Install one or add it to PATH.");
17
+ return;
21
18
  }
22
19
  if (!existsSync(VSIX_PATH)) {
23
20
  logger.error({ path: VSIX_PATH }, "Extension .vsix not found");
24
21
  return;
25
22
  }
26
- try {
27
- execSync(`code --install-extension "${VSIX_PATH}"`, { encoding: "utf-8" });
28
- logger.info("Installed walkthrough bridge extension");
29
- }
30
- catch (error) {
31
- logger.error({ err: error }, "Failed to install extension");
23
+ for (const cli of clis) {
24
+ try {
25
+ const installed = execSync(`"${cli}" --list-extensions`, {
26
+ encoding: "utf-8",
27
+ });
28
+ if (installed.includes(EXTENSION_ID)) {
29
+ logger.info({ cli }, "Walkthrough bridge extension already installed");
30
+ continue;
31
+ }
32
+ }
33
+ catch {
34
+ logger.warn({ cli }, "Could not check installed extensions");
35
+ }
36
+ try {
37
+ execSync(`"${cli}" --install-extension "${VSIX_PATH}"`, {
38
+ encoding: "utf-8",
39
+ });
40
+ logger.info({ cli }, "Installed walkthrough bridge extension");
41
+ }
42
+ catch (error) {
43
+ logger.error({ cli, err: error }, "Failed to install extension");
44
+ }
32
45
  }
33
46
  }
34
47
  export let bridgeAvailable = null;
48
+ let socketPath = null;
35
49
  export function resetBridgeState() {
36
50
  bridgeAvailable = null;
51
+ socketPath = null;
37
52
  }
38
- export async function checkBridge() {
39
- try {
40
- const res = await fetch(`${BRIDGE_URL}/ping`, {
41
- method: "POST",
42
- headers: { "Content-Type": "application/json" },
43
- body: "{}",
44
- });
45
- const data = (await res.json());
46
- bridgeAvailable = data.ok === true;
53
+ // For testing: override socket path discovery
54
+ export function _setSocketPath(path) {
55
+ socketPath = path;
56
+ }
57
+ function resolveSocketPath() {
58
+ if (!socketPath) {
59
+ socketPath = discoverSocket();
47
60
  }
48
- catch {
49
- bridgeAvailable = false;
61
+ return socketPath;
62
+ }
63
+ function socketRequest(endpoint, data = {}) {
64
+ const resolved = resolveSocketPath();
65
+ if (!resolved) {
66
+ return Promise.resolve({
67
+ ok: false,
68
+ error: "No walkthrough bridge socket found. Make sure VS Code is open with a workspace.",
69
+ });
50
70
  }
71
+ return new Promise((resolve) => {
72
+ const body = JSON.stringify(data);
73
+ const req = http.request({
74
+ socketPath: resolved,
75
+ path: endpoint,
76
+ method: "POST",
77
+ headers: {
78
+ "Content-Type": "application/json",
79
+ "Content-Length": Buffer.byteLength(body),
80
+ },
81
+ }, (res) => {
82
+ let responseData = "";
83
+ res.on("data", (chunk) => {
84
+ responseData += chunk.toString();
85
+ });
86
+ res.on("end", () => {
87
+ try {
88
+ bridgeAvailable = true;
89
+ resolve(JSON.parse(responseData));
90
+ }
91
+ catch {
92
+ resolve({ ok: false, error: "Invalid response from bridge" });
93
+ }
94
+ });
95
+ });
96
+ req.on("error", () => {
97
+ resolve({
98
+ ok: false,
99
+ error: "Could not reach VS Code. Make sure VS Code is open and reload the window if you just installed mcp-walkthrough.",
100
+ });
101
+ });
102
+ req.write(body);
103
+ req.end();
104
+ });
105
+ }
106
+ export async function checkBridge() {
107
+ const result = await socketRequest("/ping");
108
+ bridgeAvailable = result.ok === true;
51
109
  logger.info({ bridgeAvailable }, "Bridge status");
52
110
  return bridgeAvailable;
53
111
  }
54
112
  export function isBridgeAvailable() {
55
113
  return bridgeAvailable === true;
56
114
  }
57
- async function bridgeRequest(endpoint, data = {}) {
58
- try {
59
- const res = await fetch(`${BRIDGE_URL}${endpoint}`, {
60
- method: "POST",
61
- headers: { "Content-Type": "application/json" },
62
- body: JSON.stringify(data),
63
- });
64
- bridgeAvailable = true;
65
- return (await res.json());
66
- }
67
- catch {
68
- return {
69
- ok: false,
70
- error: "Could not reach VS Code. Make sure VS Code is open and reload the window if you just installed mcp-walkthrough.",
71
- };
72
- }
73
- }
74
115
  export async function openFile(file, line, endLine, startChar, endChar) {
75
- return bridgeRequest("/open", { file, line, endLine, startChar, endChar });
116
+ return socketRequest("/open", { file, line, endLine, startChar, endChar });
76
117
  }
77
118
  export async function showExplanation(file, line, endLine, explanation, title, startChar, endChar) {
78
- return bridgeRequest("/explain", {
119
+ return socketRequest("/explain", {
79
120
  file,
80
121
  line,
81
122
  endLine,
@@ -86,18 +127,18 @@ export async function showExplanation(file, line, endLine, explanation, title, s
86
127
  });
87
128
  }
88
129
  export async function clearExplanations() {
89
- return bridgeRequest("/clear");
130
+ return socketRequest("/clear");
90
131
  }
91
132
  export async function startWalkthrough(steps, autoplay, delayMs) {
92
- return bridgeRequest("/walkthrough", { steps, autoplay, delayMs });
133
+ return socketRequest("/walkthrough", { steps, autoplay, delayMs });
93
134
  }
94
135
  export async function navigateWalkthrough(action, step) {
95
- return bridgeRequest("/walkthrough/navigate", { action, step });
136
+ return socketRequest("/walkthrough/navigate", { action, step });
96
137
  }
97
138
  export async function getWalkthroughStatus() {
98
- return bridgeRequest("/walkthrough/status");
139
+ return socketRequest("/walkthrough/status");
99
140
  }
100
141
  export async function getSelection() {
101
- return bridgeRequest("/selection");
142
+ return socketRequest("/selection");
102
143
  }
103
144
  //# sourceMappingURL=bridge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function _findAllCodeClis(platform: NodeJS.Platform, findInPath: (name: string) => string | null, fileExists: (path: string) => boolean, listDir: (path: string) => string[], localAppData?: string): string[];
2
+ export declare function resolveAllCodeClis(): string[];
3
+ export declare function resetCodeCliCache(): void;
4
+ //# sourceMappingURL=code-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-cli.d.ts","sourceRoot":"","sources":["../src/code-cli.ts"],"names":[],"mappings":"AAkBA,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,EAC3C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,EACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,EACnC,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,EAAE,CAiEV;AAgBD,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAS7C;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -0,0 +1,86 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync, readdirSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ const CLI_NAMES = ["code", "code-insiders", "cursor"];
6
+ function safeListDir(listDir, path) {
7
+ try {
8
+ return listDir(path);
9
+ }
10
+ catch {
11
+ return [];
12
+ }
13
+ }
14
+ export function _findAllCodeClis(platform, findInPath, fileExists, listDir, localAppData) {
15
+ const found = [];
16
+ for (const name of CLI_NAMES) {
17
+ const p = findInPath(name);
18
+ if (p)
19
+ found.push(p);
20
+ }
21
+ if (platform === "darwin") {
22
+ for (const entry of safeListDir(listDir, "/Applications")) {
23
+ if (!entry.endsWith(".app"))
24
+ continue;
25
+ for (const name of CLI_NAMES) {
26
+ const bin = join("/Applications", entry, "Contents", "Resources", "app", "bin", name);
27
+ if (fileExists(bin))
28
+ found.push(bin);
29
+ }
30
+ }
31
+ }
32
+ if (platform === "linux") {
33
+ for (const dir of ["/usr/bin", "/usr/local/bin", "/snap/bin"]) {
34
+ for (const name of CLI_NAMES) {
35
+ const bin = join(dir, name);
36
+ if (fileExists(bin))
37
+ found.push(bin);
38
+ }
39
+ }
40
+ for (const entry of safeListDir(listDir, "/opt")) {
41
+ for (const name of CLI_NAMES) {
42
+ const bin = join("/opt", entry, "bin", name);
43
+ if (fileExists(bin))
44
+ found.push(bin);
45
+ }
46
+ }
47
+ }
48
+ if (platform === "win32") {
49
+ const appData = localAppData ||
50
+ process.env.LOCALAPPDATA ||
51
+ join(homedir(), "AppData", "Local");
52
+ const programsDir = join(appData, "Programs");
53
+ for (const entry of safeListDir(listDir, programsDir)) {
54
+ for (const name of CLI_NAMES) {
55
+ const std = join(programsDir, entry, "bin", `${name}.cmd`);
56
+ if (fileExists(std))
57
+ found.push(std);
58
+ const electron = join(programsDir, entry, "resources", "app", "bin", `${name}.cmd`);
59
+ if (fileExists(electron))
60
+ found.push(electron);
61
+ }
62
+ }
63
+ }
64
+ return [...new Set(found)];
65
+ }
66
+ function defaultFindInPath(name) {
67
+ try {
68
+ const cmd = process.platform === "win32" ? "where" : "which";
69
+ return (execSync(`${cmd} ${name}`, { encoding: "utf-8", stdio: "pipe" }).trim() ||
70
+ null);
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ let cached;
77
+ export function resolveAllCodeClis() {
78
+ if (cached !== undefined)
79
+ return cached;
80
+ cached = _findAllCodeClis(process.platform, defaultFindInPath, existsSync, (p) => readdirSync(p));
81
+ return cached;
82
+ }
83
+ export function resetCodeCliCache() {
84
+ cached = undefined;
85
+ }
86
+ //# sourceMappingURL=code-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-cli.js","sourceRoot":"","sources":["../src/code-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function socketPathForDir(dir: string): string;
2
+ export declare function discoverSocket(cwd?: string): string | null;
3
+ //# sourceMappingURL=socket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../src/socket.ts"],"names":[],"mappings":"AAOA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOpD;AAED,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAYzE"}
package/dist/socket.js ADDED
@@ -0,0 +1,28 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ const SOCKET_DIR = "/tmp";
5
+ const SOCKET_PREFIX = "walkthrough-bridge-";
6
+ export function socketPathForDir(dir) {
7
+ const normalized = dir.replace(/\/+$/, "");
8
+ const hash = createHash("sha256")
9
+ .update(normalized)
10
+ .digest("hex")
11
+ .slice(0, 16);
12
+ return join(SOCKET_DIR, `${SOCKET_PREFIX}${hash}.sock`);
13
+ }
14
+ export function discoverSocket(cwd = process.cwd()) {
15
+ let dir = cwd;
16
+ while (true) {
17
+ const socketPath = socketPathForDir(dir);
18
+ if (existsSync(socketPath)) {
19
+ return socketPath;
20
+ }
21
+ const parent = dirname(dir);
22
+ if (parent === dir)
23
+ break;
24
+ dir = parent;
25
+ }
26
+ return null;
27
+ }
28
+ //# sourceMappingURL=socket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.js","sourceRoot":"","sources":["../src/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,UAAU,GAAG,MAAM,CAAC;AAC1B,MAAM,aAAa,GAAG,qBAAqB,CAAC;AAE5C,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC;SAC9B,MAAM,CAAC,UAAU,CAAC;SAClB,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,OAAO,IAAI,CAAC,UAAU,EAAE,GAAG,aAAa,GAAG,IAAI,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACxD,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-walkthrough",
3
- "version": "0.1.6",
3
+ "version": "0.2.1",
4
4
  "description": "MCP server for interactive code walkthroughs - Claude-driven code tours",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "files": [
11
11
  "dist",
12
+ "scripts/postinstall.cjs",
12
13
  "vscode-extension/walkthrough-bridge.vsix",
13
14
  "README.md",
14
15
  "LICENSE"
@@ -29,7 +30,7 @@
29
30
  "scripts": {
30
31
  "build": "npm run build:extension && tsc -p tsconfig.build.json",
31
32
  "build:extension": "node -e \"const fs=require('fs');const v=require('./package.json').version;const p=JSON.parse(fs.readFileSync('vscode-extension/package.json','utf-8'));p.version=v;fs.writeFileSync('vscode-extension/package.json',JSON.stringify(p,null,2)+'\\n')\" && cd vscode-extension && npm install && npx tsc -p ./ && npx @vscode/vsce package --allow-missing-repository -o walkthrough-bridge.vsix",
32
- "postinstall": "node -e \"try{require('child_process').execSync('code --install-extension '+require('path').join(__dirname,'vscode-extension','walkthrough-bridge.vsix')+' --force',{stdio:'ignore'})}catch{}\"",
33
+ "postinstall": "node scripts/postinstall.cjs",
33
34
  "dev": "bun --watch src/index.ts",
34
35
  "start": "node dist/index.js",
35
36
  "test": "bun test",
@@ -0,0 +1,98 @@
1
+ const { execSync } = require("node:child_process");
2
+ const { existsSync, readdirSync } = require("node:fs");
3
+ const { join } = require("node:path");
4
+
5
+ const vsixPath = join(
6
+ __dirname,
7
+ "..",
8
+ "vscode-extension",
9
+ "walkthrough-bridge.vsix",
10
+ );
11
+ if (!existsSync(vsixPath)) process.exit(0);
12
+
13
+ const cliNames = ["code", "code-insiders", "cursor"];
14
+ const whichCmd = process.platform === "win32" ? "where" : "which";
15
+
16
+ function safeReaddir(dir) {
17
+ try {
18
+ return readdirSync(dir);
19
+ } catch {
20
+ return [];
21
+ }
22
+ }
23
+
24
+ const found = [];
25
+
26
+ for (const name of cliNames) {
27
+ try {
28
+ const p = execSync(`${whichCmd} ${name}`, {
29
+ encoding: "utf-8",
30
+ stdio: "pipe",
31
+ }).trim();
32
+ if (p) found.push(p);
33
+ } catch {}
34
+ }
35
+
36
+ if (process.platform === "darwin") {
37
+ for (const entry of safeReaddir("/Applications")) {
38
+ if (!entry.endsWith(".app")) continue;
39
+ for (const name of cliNames) {
40
+ const bin = join(
41
+ "/Applications",
42
+ entry,
43
+ "Contents",
44
+ "Resources",
45
+ "app",
46
+ "bin",
47
+ name,
48
+ );
49
+ if (existsSync(bin)) found.push(bin);
50
+ }
51
+ }
52
+ }
53
+
54
+ if (process.platform === "linux") {
55
+ for (const dir of ["/usr/bin", "/usr/local/bin", "/snap/bin"]) {
56
+ for (const name of cliNames) {
57
+ const bin = join(dir, name);
58
+ if (existsSync(bin)) found.push(bin);
59
+ }
60
+ }
61
+ for (const entry of safeReaddir("/opt")) {
62
+ for (const name of cliNames) {
63
+ const bin = join("/opt", entry, "bin", name);
64
+ if (existsSync(bin)) found.push(bin);
65
+ }
66
+ }
67
+ }
68
+
69
+ if (process.platform === "win32") {
70
+ const appData =
71
+ process.env.LOCALAPPDATA ||
72
+ join(require("node:os").homedir(), "AppData", "Local");
73
+ const programsDir = join(appData, "Programs");
74
+ for (const entry of safeReaddir(programsDir)) {
75
+ for (const name of cliNames) {
76
+ const std = join(programsDir, entry, "bin", `${name}.cmd`);
77
+ if (existsSync(std)) found.push(std);
78
+ const electron = join(
79
+ programsDir,
80
+ entry,
81
+ "resources",
82
+ "app",
83
+ "bin",
84
+ `${name}.cmd`,
85
+ );
86
+ if (existsSync(electron)) found.push(electron);
87
+ }
88
+ }
89
+ }
90
+
91
+ const unique = [...new Set(found)];
92
+ for (const cli of unique) {
93
+ try {
94
+ execSync(`"${cli}" --install-extension "${vsixPath}" --force`, {
95
+ stdio: "ignore",
96
+ });
97
+ } catch {}
98
+ }