@wonderwhy-er/desktop-commander 0.2.18-alpha.9 → 0.2.21

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.
@@ -101,7 +101,15 @@ class ConfigManager {
101
101
  "cipher", // Encrypt/decrypt files or wipe data
102
102
  "takeown" // Take ownership of files
103
103
  ],
104
- defaultShell: os.platform() === 'win32' ? 'powershell.exe' : '/bin/sh',
104
+ defaultShell: (() => {
105
+ if (os.platform() === 'win32') {
106
+ return 'powershell.exe';
107
+ }
108
+ // Use user's actual shell from environment, or fall back to /bin/sh
109
+ const userShell = process.env.SHELL || '/bin/sh';
110
+ // Return just the shell path - we'll handle login shell flag elsewhere
111
+ return userShell;
112
+ })(),
105
113
  allowedDirectories: [],
106
114
  telemetryEnabled: true, // Default to opt-out approach (telemetry on by default)
107
115
  fileWriteLineLimit: 50, // Default line limit for file write operations (changed from 100)
@@ -8,11 +8,18 @@ export declare class FilteredStdioServerTransport extends StdioServerTransport {
8
8
  private originalStdoutWrite;
9
9
  private isInitialized;
10
10
  private messageBuffer;
11
+ private clientName;
12
+ private disableNotifications;
11
13
  constructor();
12
14
  /**
13
15
  * Call this method after MCP initialization is complete to enable JSON-RPC notifications
14
16
  */
15
17
  enableNotifications(): void;
18
+ /**
19
+ * Configure client-specific behavior
20
+ * Call this BEFORE enableNotifications()
21
+ */
22
+ configureForClient(clientName: string): void;
16
23
  /**
17
24
  * Check if notifications are enabled
18
25
  */
@@ -9,6 +9,8 @@ export class FilteredStdioServerTransport extends StdioServerTransport {
9
9
  super();
10
10
  this.isInitialized = false;
11
11
  this.messageBuffer = [];
12
+ this.clientName = 'unknown';
13
+ this.disableNotifications = false;
12
14
  // Store original methods
13
15
  this.originalConsole = {
14
16
  log: console.log,
@@ -30,6 +32,15 @@ export class FilteredStdioServerTransport extends StdioServerTransport {
30
32
  */
31
33
  enableNotifications() {
32
34
  this.isInitialized = true;
35
+ // Check if notifications should be disabled based on client
36
+ if (this.disableNotifications) {
37
+ // Clear buffer without sending - just log to stderr instead
38
+ if (this.messageBuffer.length > 0) {
39
+ process.stderr.write(`[INFO] ${this.messageBuffer.length} buffered messages suppressed for ${this.clientName}\n`);
40
+ }
41
+ this.messageBuffer = [];
42
+ return;
43
+ }
33
44
  // Send the deferred initialization notification first
34
45
  this.sendLogNotification('info', ['Enhanced FilteredStdioServerTransport initialized']);
35
46
  // Replay all buffered messages in chronological order
@@ -45,6 +56,20 @@ export class FilteredStdioServerTransport extends StdioServerTransport {
45
56
  }
46
57
  this.sendLogNotification('info', ['JSON-RPC notifications enabled']);
47
58
  }
59
+ /**
60
+ * Configure client-specific behavior
61
+ * Call this BEFORE enableNotifications()
62
+ */
63
+ configureForClient(clientName) {
64
+ this.clientName = clientName.toLowerCase();
65
+ // Detect Cline and disable notifications
66
+ if (this.clientName.includes('cline') ||
67
+ this.clientName.includes('vscode') ||
68
+ this.clientName === 'claude-dev') {
69
+ this.disableNotifications = true;
70
+ process.stderr.write(`[INFO] Desktop Commander: Notifications disabled for ${clientName}\n`);
71
+ }
72
+ }
48
73
  /**
49
74
  * Check if notifications are enabled
50
75
  */
@@ -155,6 +180,10 @@ export class FilteredStdioServerTransport extends StdioServerTransport {
155
180
  };
156
181
  }
157
182
  sendLogNotification(level, args) {
183
+ // Skip if notifications are disabled (e.g., for Cline)
184
+ if (this.disableNotifications) {
185
+ return;
186
+ }
158
187
  try {
159
188
  // For data, we can send structured data or string according to MCP spec
160
189
  let data;
@@ -206,6 +235,10 @@ export class FilteredStdioServerTransport extends StdioServerTransport {
206
235
  * Public method to send log notifications from anywhere in the application
207
236
  */
208
237
  sendLog(level, message, data) {
238
+ // Skip if notifications are disabled (e.g., for Cline)
239
+ if (this.disableNotifications) {
240
+ return;
241
+ }
209
242
  try {
210
243
  const notification = {
211
244
  jsonrpc: "2.0",
package/dist/server.js CHANGED
@@ -70,6 +70,11 @@ server.setRequestHandler(InitializeRequestSchema, async (request) => {
70
70
  name: clientInfo.name || 'unknown',
71
71
  version: clientInfo.version || 'unknown'
72
72
  };
73
+ // Configure transport for client-specific behavior
74
+ const transport = global.mcpTransport;
75
+ if (transport && typeof transport.configureForClient === 'function') {
76
+ transport.configureForClient(currentClient.name);
77
+ }
73
78
  // Defer client connection message until after initialization
74
79
  deferLog('info', `Client connected: ${currentClient.name} v${currentClient.version}`);
75
80
  }
@@ -207,74 +207,43 @@ function detectShell() {
207
207
  }
208
208
 
209
209
  // Function to get the package spec that was used to run this script
210
- function getPackageSpec() {
211
- // Use stderr for debug output so it's always visible
212
- const debug = (msg) => process.stderr.write(`${msg}\n`);
213
-
214
- debug('\n[DEBUG getPackageSpec] Starting detection...');
215
- debug(`[DEBUG getPackageSpec] process.argv: ${JSON.stringify(process.argv)}`);
216
- debug(`[DEBUG getPackageSpec] __dirname: ${__dirname}`);
217
- debug(`[DEBUG getPackageSpec] __filename: ${__filename}`);
218
-
219
- // Strategy: Check multiple sources to detect the version
220
- // 1. Check process.argv[1] which contains the actual script path
221
- // 2. Check package.json in the script's directory
222
- // 3. Fall back to @latest for stable, keep version for pre-release
223
-
224
- // Method 1: Check the script path (process.argv[1] or __dirname)
225
- // npx extracts packages to: ~/.npm/_npx/<hash>/node_modules/@scope/package-name/
226
- // The actual script path will contain this structure
227
- const scriptPath = __dirname;
228
- debug('[DEBUG getPackageSpec] Checking script path for version...');
229
-
230
- // Look for node_modules/@wonderwhy-er/desktop-commander in the path
231
- // This works because npx extracts to a predictable location
232
- const nodeModulesMatch = scriptPath.match(/node_modules\/@wonderwhy-er\/desktop-commander/);
233
- if (nodeModulesMatch) {
234
- debug('[DEBUG getPackageSpec] Script is in node_modules, reading package.json...');
210
+ function getPackageSpec(versionArg = null) {
211
+ // If explicit version/tag argument provided, use it
212
+ // Usage: npx @wonderwhy-er/desktop-commander setup alpha
213
+ if (versionArg) {
214
+ return `@wonderwhy-er/desktop-commander@${versionArg}`;
235
215
  }
236
216
 
237
- // Method 2: Read package.json to get the actual installed version
238
- try {
239
- const packageJsonPath = join(__dirname, 'package.json');
240
- debug(`[DEBUG getPackageSpec] Trying to read: ${packageJsonPath}`);
241
-
242
- if (existsSync(packageJsonPath)) {
243
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
244
- const version = packageJson.version;
245
- debug(`[DEBUG getPackageSpec] Found version in package.json: ${version}`);
246
-
247
- if (version) {
248
- // Always use the exact version if it's a pre-release
249
- if (version.includes('alpha') || version.includes('beta') || version.includes('rc')) {
250
- const spec = `@wonderwhy-er/desktop-commander@${version}`;
251
- debug(`[DEBUG getPackageSpec] ✓ Using pre-release version: ${spec}`);
252
- return spec;
253
- }
254
-
255
- // For stable versions, use @latest tag
256
- debug('[DEBUG getPackageSpec] ✓ Stable version, using @latest');
257
- return '@wonderwhy-er/desktop-commander@latest';
217
+ // Check if running via npx - look for the package spec in process.argv
218
+ // e.g., npx @wonderwhy-er/desktop-commander@0.2.18-alpha setup
219
+ const argv = process.argv;
220
+
221
+ // Look for the package name in argv
222
+ for (let i = 0; i < argv.length; i++) {
223
+ const arg = argv[i];
224
+ if (arg.includes('@wonderwhy-er/desktop-commander')) {
225
+ // Extract just the package spec (e.g., @wonderwhy-er/desktop-commander@0.2.18-alpha)
226
+ const match = arg.match(/(@wonderwhy-er\/desktop-commander(@[^\/\s]+)?)/);
227
+ if (match) {
228
+ return match[1];
258
229
  }
259
- } else {
260
- debug('[DEBUG getPackageSpec] ✗ package.json not found');
261
230
  }
262
- } catch (error) {
263
- debug(`[DEBUG getPackageSpec] ✗ Error reading package.json: ${error.message}`);
264
231
  }
265
232
 
266
- // Fallback
267
- debug('[DEBUG getPackageSpec] ⚠ Falling back to @latest');
233
+ // Fallback to @latest if we can't detect
268
234
  return '@wonderwhy-er/desktop-commander@latest';
269
235
  }
270
236
 
237
+ function isNPX() {
238
+ return process.env.npm_lifecycle_event === 'npx' ||
239
+ process.env.npm_execpath?.includes('npx') ||
240
+ process.env._?.includes('npx') ||
241
+ import.meta.url.includes('node_modules');
242
+ }
271
243
  // Function to determine execution context
272
244
  function getExecutionContext() {
273
245
  // Check if running from npx
274
- const isNpx = process.env.npm_lifecycle_event === 'npx' ||
275
- process.env.npm_execpath?.includes('npx') ||
276
- process.env._?.includes('npx') ||
277
- import.meta.url.includes('node_modules');
246
+ const isNpx = isNPX();
278
247
 
279
248
  // Check if installed globally
280
249
  const isGlobal = process.env.npm_config_global === 'true' ||
@@ -674,13 +643,9 @@ async function restartClaude() {
674
643
 
675
644
  // Main function to export for ESM compatibility
676
645
  export default async function setup() {
677
- // VERY FIRST THING - test if stderr works AT ALL
678
- process.stderr.write('\n\n========== SETUP FUNCTION STARTED ==========\n');
679
- process.stderr.write(`__dirname: ${__dirname}\n`);
680
- process.stderr.write(`__filename: ${__filename}\n`);
681
- process.stderr.write(`process.argv: ${JSON.stringify(process.argv)}\n`);
682
- process.stderr.write('=============================================\n\n');
683
-
646
+ // Parse command line arguments for version/tag
647
+ const versionArg = process.argv[3]; // argv[0]=node, argv[1]=script, argv[2]=version/tag
648
+
684
649
  // Add tracking for setup function entry
685
650
  await trackEvent('npx_setup_function_started');
686
651
 
@@ -779,9 +744,7 @@ export default async function setup() {
779
744
  const configPrepStep = addSetupStep('prepare_server_config');
780
745
 
781
746
  // Determine if running through npx or locally
782
- const isNpx = import.meta.url.includes('node_modules');
783
- process.stderr.write(`\n[SETUP] import.meta.url: ${import.meta.url}\n`);
784
- process.stderr.write(`[SETUP] isNpx: ${isNpx}\n`);
747
+ const isNpx = isNPX();
785
748
  await trackEvent('npx_setup_execution_mode', { isNpx });
786
749
 
787
750
  // Fix Windows path handling for npx execution
@@ -799,7 +762,7 @@ export default async function setup() {
799
762
  "DEBUG": "*"
800
763
  };
801
764
 
802
- const packageSpec = getPackageSpec();
765
+ const packageSpec = getPackageSpec(versionArg);
803
766
  serverConfig = {
804
767
  "command": isWindows ? "node.exe" : "node",
805
768
  "args": [
@@ -835,15 +798,13 @@ export default async function setup() {
835
798
  } else {
836
799
  // Standard configuration without debug
837
800
  if (isNpx) {
838
- const packageSpec = getPackageSpec();
839
- process.stderr.write(`\n[SETUP] Creating config with package spec: ${packageSpec}\n`);
801
+ const packageSpec = getPackageSpec(versionArg);
840
802
  serverConfig = {
841
803
  "command": isWindows ? "npx.cmd" : "npx",
842
804
  "args": [
843
805
  packageSpec
844
806
  ]
845
807
  };
846
- process.stderr.write(`[SETUP] serverConfig.args: ${JSON.stringify(serverConfig.args)}\n`);
847
808
  await trackEvent('npx_setup_config_standard_npx', { packageSpec });
848
809
  } else {
849
810
  // For local installation, use absolute path to handle Windows properly
@@ -881,16 +842,8 @@ export default async function setup() {
881
842
  // Add or update the terminal server config with the proper name "desktop-commander"
882
843
  config.mcpServers["desktop-commander"] = serverConfig;
883
844
 
884
- process.stderr.write('\n[SETUP] Writing config to Claude:\n');
885
- process.stderr.write(`[SETUP] desktop-commander args: ${JSON.stringify(config.mcpServers["desktop-commander"].args)}\n`);
886
-
887
845
  // Write the updated config back
888
846
  writeFileSync(claudeConfigPath, JSON.stringify(config, null, 2), 'utf8');
889
-
890
- // Verify what was written
891
- const writtenConfig = JSON.parse(readFileSync(claudeConfigPath, 'utf8'));
892
- process.stderr.write(`[SETUP] Verified written args: ${JSON.stringify(writtenConfig.mcpServers["desktop-commander"].args)}\n\n`);
893
-
894
847
  updateSetupStep(updateConfigStep, 'completed');
895
848
  await trackEvent('npx_setup_update_config');
896
849
  } catch (updateError) {
package/dist/setup.log CHANGED
@@ -82,3 +82,194 @@ The server is available as "desktop-commander" in Claude's MCP server list
82
82
  2025-10-22T15:22:46.665Z - or join our community: https://discord.com/invite/kQ27sNnZr7
83
83
 
84
84
 
85
+ 2025-10-23T10:10:37.029Z - ✅ Desktop Commander MCP v0.2.18-alpha.13 successfully added to Claude’s configuration.
86
+ 2025-10-23T10:10:37.030Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
87
+ 2025-10-23T10:10:40.163Z -
88
+ ✅ Claude has been restarted automatically!
89
+ 2025-10-23T10:10:40.184Z -
90
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
91
+
92
+ 2025-10-23T10:10:40.184Z -
93
+ The server is available as "desktop-commander" in Claude's MCP server list
94
+ 2025-10-23T10:10:40.184Z - Future updates will install automatically — no need to run this setup again.
95
+
96
+
97
+ 2025-10-23T10:10:40.184Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
98
+
99
+
100
+ 2025-10-23T10:10:40.184Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
101
+
102
+
103
+ 2025-10-23T10:10:40.184Z - or join our community: https://discord.com/invite/kQ27sNnZr7
104
+
105
+
106
+ 2025-10-23T10:11:28.520Z - ✅ Desktop Commander MCP v0.2.18-alpha.13 successfully added to Claude’s configuration.
107
+ 2025-10-23T10:11:28.520Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
108
+ 2025-10-23T10:11:31.626Z -
109
+ ✅ Claude has been restarted automatically!
110
+ 2025-10-23T10:11:31.645Z -
111
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
112
+
113
+ 2025-10-23T10:11:31.645Z -
114
+ The server is available as "desktop-commander" in Claude's MCP server list
115
+ 2025-10-23T10:11:31.645Z - Future updates will install automatically — no need to run this setup again.
116
+
117
+
118
+ 2025-10-23T10:11:31.645Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
119
+
120
+
121
+ 2025-10-23T10:11:31.645Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
122
+
123
+
124
+ 2025-10-23T10:11:31.645Z - or join our community: https://discord.com/invite/kQ27sNnZr7
125
+
126
+
127
+ 2025-10-23T10:19:51.580Z - ✅ Desktop Commander MCP v0.2.18-alpha.13 successfully added to Claude’s configuration.
128
+ 2025-10-23T10:19:51.580Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
129
+ 2025-10-23T10:19:54.733Z -
130
+ ✅ Claude has been restarted automatically!
131
+ 2025-10-23T10:19:54.755Z -
132
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
133
+
134
+ 2025-10-23T10:19:54.755Z -
135
+ The server is available as "desktop-commander" in Claude's MCP server list
136
+ 2025-10-23T10:19:54.756Z - Future updates will install automatically — no need to run this setup again.
137
+
138
+
139
+ 2025-10-23T10:19:54.756Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
140
+
141
+
142
+ 2025-10-23T10:19:54.756Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
143
+
144
+
145
+ 2025-10-23T10:19:54.756Z - or join our community: https://discord.com/invite/kQ27sNnZr7
146
+
147
+
148
+ 2025-10-23T10:20:46.785Z - ✅ Desktop Commander MCP v0.2.18-alpha.13 successfully added to Claude’s configuration.
149
+ 2025-10-23T10:20:46.785Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
150
+ 2025-10-23T10:20:49.891Z -
151
+ ✅ Claude has been restarted automatically!
152
+ 2025-10-23T10:20:49.913Z -
153
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
154
+
155
+ 2025-10-23T10:20:49.913Z -
156
+ The server is available as "desktop-commander" in Claude's MCP server list
157
+ 2025-10-23T10:20:49.913Z - Future updates will install automatically — no need to run this setup again.
158
+
159
+
160
+ 2025-10-23T10:20:49.913Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
161
+
162
+
163
+ 2025-10-23T10:20:49.913Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
164
+
165
+
166
+ 2025-10-23T10:20:49.913Z - or join our community: https://discord.com/invite/kQ27sNnZr7
167
+
168
+
169
+ 2025-10-23T10:23:37.739Z - ✅ Desktop Commander MCP v0.2.18-alpha.14 successfully added to Claude’s configuration.
170
+ 2025-10-23T10:23:37.739Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
171
+ 2025-10-23T10:23:40.846Z -
172
+ ✅ Claude has been restarted automatically!
173
+ 2025-10-23T10:23:40.867Z -
174
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
175
+
176
+ 2025-10-23T10:23:40.867Z -
177
+ The server is available as "desktop-commander" in Claude's MCP server list
178
+ 2025-10-23T10:23:40.867Z - Future updates will install automatically — no need to run this setup again.
179
+
180
+
181
+ 2025-10-23T10:23:40.867Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
182
+
183
+
184
+ 2025-10-23T10:23:40.867Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
185
+
186
+
187
+ 2025-10-23T10:23:40.867Z - or join our community: https://discord.com/invite/kQ27sNnZr7
188
+
189
+
190
+ 2025-10-23T10:39:56.359Z - ✅ Desktop Commander MCP v0.2.18-alpha.15 successfully added to Claude’s configuration.
191
+ 2025-10-23T10:39:56.360Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
192
+ 2025-10-23T10:39:59.526Z -
193
+ ✅ Claude has been restarted automatically!
194
+ 2025-10-23T10:39:59.567Z -
195
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
196
+
197
+ 2025-10-23T10:39:59.567Z -
198
+ The server is available as "desktop-commander" in Claude's MCP server list
199
+ 2025-10-23T10:39:59.567Z - Future updates will install automatically — no need to run this setup again.
200
+
201
+
202
+ 2025-10-23T10:39:59.567Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
203
+
204
+
205
+ 2025-10-23T10:39:59.567Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
206
+
207
+
208
+ 2025-10-23T10:39:59.567Z - or join our community: https://discord.com/invite/kQ27sNnZr7
209
+
210
+
211
+ 2025-10-23T10:57:55.850Z - ✅ Desktop Commander MCP v0.2.18-alpha.15 successfully added to Claude’s configuration.
212
+ 2025-10-23T10:57:55.851Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
213
+ 2025-10-23T10:57:59.008Z -
214
+ ✅ Claude has been restarted automatically!
215
+ 2025-10-23T10:57:59.051Z -
216
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
217
+
218
+ 2025-10-23T10:57:59.052Z -
219
+ The server is available as "desktop-commander" in Claude's MCP server list
220
+ 2025-10-23T10:57:59.052Z - Future updates will install automatically — no need to run this setup again.
221
+
222
+
223
+ 2025-10-23T10:57:59.052Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
224
+
225
+
226
+ 2025-10-23T10:57:59.052Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
227
+
228
+
229
+ 2025-10-23T10:57:59.052Z - or join our community: https://discord.com/invite/kQ27sNnZr7
230
+
231
+
232
+ 2025-10-23T11:06:27.679Z - ERROR: Command args:
233
+ 2025-10-23T11:06:32.852Z - ✅ Desktop Commander MCP v0.2.18-alpha.16 successfully added to Claude’s configuration.
234
+ 2025-10-23T11:06:32.852Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
235
+ 2025-10-23T11:06:36.008Z -
236
+ ✅ Claude has been restarted automatically!
237
+ 2025-10-23T11:06:36.050Z -
238
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
239
+
240
+ 2025-10-23T11:06:36.050Z -
241
+ The server is available as "desktop-commander" in Claude's MCP server list
242
+ 2025-10-23T11:06:36.050Z - Future updates will install automatically — no need to run this setup again.
243
+
244
+
245
+ 2025-10-23T11:06:36.050Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
246
+
247
+
248
+ 2025-10-23T11:06:36.050Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
249
+
250
+
251
+ 2025-10-23T11:06:36.050Z - or join our community: https://discord.com/invite/kQ27sNnZr7
252
+
253
+
254
+ 2025-10-23T11:17:02.302Z - ERROR: Command args:
255
+ 2025-10-23T11:17:02.385Z - ✅ Desktop Commander MCP v0.2.18-alpha.16 successfully added to Claude’s configuration.
256
+ 2025-10-23T11:17:02.385Z - Configuration location: /Users/fiberta/Library/Application Support/Claude/claude_desktop_config.json
257
+ 2025-10-23T11:17:05.568Z -
258
+ ✅ Claude has been restarted automatically!
259
+ 2025-10-23T11:17:05.612Z -
260
+ ✅ Installation successfully completed! Thank you for using Desktop Commander!
261
+
262
+ 2025-10-23T11:17:05.612Z -
263
+ The server is available as "desktop-commander" in Claude's MCP server list
264
+ 2025-10-23T11:17:05.612Z - Future updates will install automatically — no need to run this setup again.
265
+
266
+
267
+ 2025-10-23T11:17:05.612Z - 🤔 Need help or have feedback? Happy to jump on a quick call:
268
+
269
+
270
+ 2025-10-23T11:17:05.612Z - https://calendar.app.google/SHMNZN5MJznJWC5A7
271
+
272
+
273
+ 2025-10-23T11:17:05.613Z - or join our community: https://discord.com/invite/kQ27sNnZr7
274
+
275
+
@@ -1,8 +1,63 @@
1
1
  import { spawn } from 'child_process';
2
+ import path from 'path';
2
3
  import { DEFAULT_COMMAND_TIMEOUT } from './config.js';
3
4
  import { configManager } from './config-manager.js';
4
5
  import { capture } from "./utils/capture.js";
5
6
  import { analyzeProcessState } from './utils/process-detection.js';
7
+ /**
8
+ * Get the appropriate spawn configuration for a given shell
9
+ * This handles login shell flags for different shell types
10
+ */
11
+ function getShellSpawnArgs(shellPath, command) {
12
+ const shellName = path.basename(shellPath).toLowerCase();
13
+ // Unix shells with login flag support
14
+ if (shellName.includes('bash') || shellName.includes('zsh')) {
15
+ return {
16
+ executable: shellPath,
17
+ args: ['-l', '-c', command],
18
+ useShellOption: false
19
+ };
20
+ }
21
+ // PowerShell Core (cross-platform, supports -Login)
22
+ if (shellName === 'pwsh' || shellName === 'pwsh.exe') {
23
+ return {
24
+ executable: shellPath,
25
+ args: ['-Login', '-Command', command],
26
+ useShellOption: false
27
+ };
28
+ }
29
+ // Windows PowerShell 5.1 (no login flag support)
30
+ if (shellName === 'powershell' || shellName === 'powershell.exe') {
31
+ return {
32
+ executable: shellPath,
33
+ args: ['-Command', command],
34
+ useShellOption: false
35
+ };
36
+ }
37
+ // CMD
38
+ if (shellName === 'cmd' || shellName === 'cmd.exe') {
39
+ return {
40
+ executable: shellPath,
41
+ args: ['/c', command],
42
+ useShellOption: false
43
+ };
44
+ }
45
+ // Fish shell (uses -l for login, -c for command)
46
+ if (shellName.includes('fish')) {
47
+ return {
48
+ executable: shellPath,
49
+ args: ['-l', '-c', command],
50
+ useShellOption: false
51
+ };
52
+ }
53
+ // Unknown/other shells - use shell option for safety
54
+ // This provides a fallback for shells we don't explicitly handle
55
+ return {
56
+ executable: command,
57
+ args: [],
58
+ useShellOption: shellPath
59
+ };
60
+ }
6
61
  export class TerminalManager {
7
62
  constructor() {
8
63
  this.sessions = new Map();
@@ -54,15 +109,40 @@ export class TerminalManager {
54
109
  enhancedCommand = command.replace(/^ssh /, 'ssh -t ');
55
110
  console.log(`Enhanced SSH command: ${enhancedCommand}`);
56
111
  }
57
- const spawnOptions = {
58
- shell: shellToUse,
59
- env: {
60
- ...process.env,
61
- TERM: 'xterm-256color' // Better terminal compatibility
112
+ // Get the appropriate spawn configuration for the shell
113
+ let spawnConfig;
114
+ let spawnOptions;
115
+ if (typeof shellToUse === 'string') {
116
+ // Use shell-specific configuration with login flags where appropriate
117
+ spawnConfig = getShellSpawnArgs(shellToUse, enhancedCommand);
118
+ spawnOptions = {
119
+ env: {
120
+ ...process.env,
121
+ TERM: 'xterm-256color' // Better terminal compatibility
122
+ }
123
+ };
124
+ // Add shell option if needed (for unknown shells)
125
+ if (spawnConfig.useShellOption) {
126
+ spawnOptions.shell = spawnConfig.useShellOption;
62
127
  }
63
- };
64
- // Spawn the process with an empty array of arguments and our options
65
- const childProcess = spawn(enhancedCommand, [], spawnOptions);
128
+ }
129
+ else {
130
+ // Boolean or undefined shell - use default shell option behavior
131
+ spawnConfig = {
132
+ executable: enhancedCommand,
133
+ args: [],
134
+ useShellOption: shellToUse
135
+ };
136
+ spawnOptions = {
137
+ shell: shellToUse,
138
+ env: {
139
+ ...process.env,
140
+ TERM: 'xterm-256color'
141
+ }
142
+ };
143
+ }
144
+ // Spawn the process with appropriate arguments
145
+ const childProcess = spawn(spawnConfig.executable, spawnConfig.args, spawnOptions);
66
146
  let output = '';
67
147
  // Ensure childProcess.pid is defined before proceeding
68
148
  if (!childProcess.pid) {
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Test what argv looks like when called as a bin script
4
+ console.log('=== Test Script Argv ===');
5
+ console.log('process.argv:');
6
+ process.argv.forEach((arg, index) => {
7
+ console.log(` ${index}: "${arg}"`);
8
+ });
9
+
10
+ const versionArg2 = process.argv[2];
11
+ const versionArg3 = process.argv[3];
12
+
13
+ console.log('\nUsing argv[2]:', versionArg2);
14
+ console.log('Using argv[3]:', versionArg3);
@@ -7,7 +7,7 @@ class FeatureFlagManager {
7
7
  constructor() {
8
8
  this.flags = {};
9
9
  this.lastFetch = 0;
10
- this.cacheMaxAge = 30 * 60 * 1000; // 5 minutes - hardcoded refresh interval
10
+ this.cacheMaxAge = 30 * 60 * 1000;
11
11
  this.refreshInterval = null;
12
12
  const configDir = path.dirname(CONFIG_FILE);
13
13
  this.cachePath = path.join(configDir, 'feature-flags.json');
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.2.18-alpha.9";
1
+ export declare const VERSION = "0.2.21";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.2.18-alpha.9';
1
+ export const VERSION = '0.2.21';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wonderwhy-er/desktop-commander",
3
- "version": "0.2.18-alpha.9",
3
+ "version": "0.2.21",
4
4
  "description": "MCP server for terminal operations and file editing",
5
5
  "mcpName": "io.github.wonderwhy-er/desktop-commander",
6
6
  "license": "MIT",
@@ -39,6 +39,7 @@
39
39
  "clean": "shx rm -rf dist",
40
40
  "test": "npm run build && node test/run-all-tests.js",
41
41
  "test:debug": "node --inspect test/run-all-tests.js",
42
+ "validate:tools": "npm run build && node scripts/validate-tools-sync.js",
42
43
  "link:local": "npm run build && npm link",
43
44
  "unlink:local": "npm unlink",
44
45
  "inspector": "npx @modelcontextprotocol/inspector dist/index.js",
@@ -86,6 +87,7 @@
86
87
  "zod-to-json-schema": "^3.23.5"
87
88
  },
88
89
  "devDependencies": {
90
+ "@anthropic-ai/mcpb": "^1.2.0",
89
91
  "@types/node": "^20.17.24",
90
92
  "commander": "^13.1.0",
91
93
  "nexe": "^5.0.0-beta.4",