How to Integrate Desktop Commander with Cursor and Windsurf: A Complete Plugin Guide
Desktop Commander integrates with AI clients like Cursor and Windsurf through a modular plugin system that maps client APIs to shared skill modules via a YAML manifest and TypeScript entry point.
Desktop Commander MCP is a plugin-first desktop automation framework that exposes system capabilities to AI-assisted coding environments. By leveraging the modular architecture found in the wonderwhy-er/DesktopCommanderMCP repository, you can extend support to any client that exposes a JavaScript API, including Cursor and Windsurf.
Understanding the Plugin Architecture
The core runtime discovers and loads plugins from the plugins/ directory at startup. Each plugin supplies a plugin.yaml (or plugin.json) manifest that declares the target client, required permissions, and entry points. According to the source code in src/remote-device/README.md, the core loader reads these manifests, resolves dependencies, and registers the plugin with the command dispatcher.
The architecture separates client-specific wrappers from reusable functionality:
- Client plugins (
plugins/cursor/,plugins/claude/) contain thin wrappers that translate client APIs (e.g.,window.aiorwindow.windsurf) into Desktop Commander commands - Skill modules (
skills/terminal/SKILL.md) implement actual functionality like shell execution or file browsing - Configuration files (
config.json) control which plugins are enabled without requiring code changes
Creating a Client Plugin for Windsurf
To integrate a new client such as Windsurf, create a directory at plugins/windsurf/ following the structure established in plugins/cursor/README.md and plugins/claude/README.md.
Step 1: Define the Plugin Manifest
Create plugin.yaml to declare the plugin metadata and permissions:
name: windsurf
displayName: Windsurf Integration
description: Enables Desktop Commander features inside the Windsurf AI client.
version: 0.1.0
entry: src/index.ts
permissions:
- filesystem
- network
This manifest tells the core loader in src/remote-device/README.md where to find the entry point and what capabilities to grant the plugin.
Step 2: Implement the Entry Point
Create src/index.ts to register the plugin with the Desktop Commander SDK and import required skills:
import { registerPlugin } from '@desktop-commander/sdk';
import { terminalSkill } from '../../skills/terminal/skill';
import { fileBrowserSkill } from '../../skills/file-browser/skill';
// Register the plugin with the Desktop Commander core
registerPlugin('windsurf', (api) => {
// Expose a "run command" method that Windsurf can call
api.expose('runShell', (command: string) => {
return terminalSkill.execute(command);
});
// Expose a "open file" method
api.expose('openFile', (path: string) => {
return fileBrowserSkill.open(path);
});
});
The registerPlugin function binds your client to the Desktop Commander runtime, while api.expose makes methods available on the window.desktopCommander object.
Step 3: Invoke Commands from the Client
Once loaded, the Windsurf client can access Desktop Commander capabilities through the global API:
// Inside a Windsurf extension script
window.desktopCommander.runShell('ls -la')
.then((output) => console.log(output));
window.desktopCommander.openFile('/home/user/project/README.md');
Enabling and Configuring the Integration
Add your new plugin to config.json (or plugin.json) to enable loading without modifying core code:
{
"enabledPlugins": ["cursor", "claude", "windsurf"]
}
The root plugin.yaml and plugin.json files serve as global registries that mirror this configuration for JSON-friendly consumers. The runtime automatically picks up new plugins on the next launch or during hot-reload cycles.
Leveraging Shared Skill Modules
Desktop Commander's modular design centralizes heavy lifting in reusable skill packages. The skills/terminal/SKILL.md file, for example, implements terminal execution logic used by all client plugins. When building a new integration, you import these pre-built skills rather than reimplementing functionality:
- Terminal operations:
skills/terminal/skill - File browsing:
skills/file-browser/skill - Knowledge base queries: Available through the skills directory structure
This approach ensures that bug fixes and feature enhancements to core capabilities propagate to all connected clients automatically.
Summary
- Desktop Commander uses a plugin architecture defined by manifests in
plugin.yamlfiles and entry points insrc/index.ts - New clients require only a lightweight wrapper in the
plugins/directory that maps client APIs to thewindow.desktopCommanderobject - Reusable capabilities are centralized in the
skills/directory (e.g.,skills/terminal/SKILL.md) and shared across all client integrations - Enable new integrations by adding the plugin name to
config.jsonwithout touching core loader code insrc/remote-device/README.md
Frequently Asked Questions
What file format does Desktop Commander use for plugin manifests?
Desktop Commander supports both plugin.yaml and plugin.json manifest files located in each plugin's root directory. These files declare the plugin name, entry point, version, and required permissions such as filesystem or network access.
Do I need to modify the core Desktop Commander code to add Windsurf support?
No. The modular architecture allows you to add new client support by creating a new folder under plugins/ (e.g., plugins/windsurf/) following the patterns in plugins/cursor/README.md and plugins/claude/README.md. The core loader automatically discovers and registers new plugins at startup.
Where are the terminal and file system capabilities defined?
Reusable capabilities are implemented as skill modules in the skills/ directory. For example, skills/terminal/SKILL.md contains the terminal execution logic imported by client plugins via import { terminalSkill } from '../../skills/terminal/skill'.
How does the plugin system handle security permissions?
Permissions are declared explicitly in each plugin's plugin.yaml manifest under the permissions key (e.g., filesystem, network). The core loader in src/remote-device/README.md reads these declarations and enforces capability restrictions when registering the plugin with the command dispatcher.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →