diff --git a/README.md b/README.md index 5cb386c..390297e 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,110 @@ npm run build:gitbash } ``` +## macOS and Unix/Linux Support + +While wcli0 is primarily designed for Windows, it also supports Unix-based systems (macOS, Linux) with Bash shell integration. + +### Building for Unix Systems + +To build wcli0 for Unix-based systems (macOS, Linux): + +```bash +# Unix-only build (Bash shell) +npm run build:unix + +# The output will be: dist/index.unix-only.js +``` + +### Starting the Server on macOS + +Start the server using npx: + +```bash +# Start with default settings +npx wcli0 --shell bash + +# Start with a configuration file +npx wcli0 --config ./config.mac.json + +# Start with specific allowed directories +npx wcli0 --shell bash \ + --allowedDir "/Users/$(whoami)" \ + --allowedDir "/tmp" +``` + +### macOS Configuration Example + +Here's a sample configuration for macOS: + +```json +{ + "global": { + "security": { + "commandTimeout": 30, + "enableInjectionProtection": true, + "restrictWorkingDirectory": true + }, + "restrictions": { + "blockedCommands": ["rm -rf /", "dd", "mkfs"], + "blockedArguments": ["--force", "-rf"], + "blockedOperators": ["&&", "||", ";", "|"] + }, + "paths": { + "allowedPaths": ["/Users/$(whoami)", "/tmp"], + "initialDir": "/Users/$(whoami)" + } + }, + "shells": { + "bash_auto": { + "type": "bash_auto", + "enabled": true + } + } +} +``` + +### Using with Claude Desktop on macOS + +Configure Claude Desktop to use wcli0 on macOS: + +```json +{ + "mcpServers": { + "macos-cli": { + "command": "npx", + "args": [ + "-y", + "wcli0", + "--config", + "/path/to/config.mac.json" + ] + } + } +} +``` + +### Important Notes for Unix Systems + +- **Path Formats**: Unix systems use forward slashes (`/`) and do not support Windows drive letters +- **Shell Type**: Use `bash` or `bash_auto` shell types on Unix systems +- **Home Directory**: Use `$(whoami)` or your actual username in paths +- **Security Commands**: Some blocked commands in the default configuration are Windows-specific (e.g., `regedit`, `format`) + +### CLI Options for macOS + +When running on Unix systems, use these CLI options: + +| Option | Type | Description | +|--------|------|-------------| +| `--shell` | string | Shell to use (use `bash` or `bash_auto` on Unix) | +| `--allowedDir` | string | Add an allowed directory (can be used multiple times) | +| `--config` | string | Path to configuration file | +| `--initialDir` | string | Initial working directory | +| `--allowAllDirs` | flag | Disable directory restrictions | +| `--unsafe` | flag | Disable all safety checks (not recommended) | +| `--yolo` | flag | Disable safety except directory restrictions | + ## Log Management wcli0 automatically stores command execution logs and provides MCP resources for querying historical output with advanced filtering capabilities. diff --git a/config.examples/macos.json b/config.examples/macos.json new file mode 100644 index 0000000..b848389 --- /dev/null +++ b/config.examples/macos.json @@ -0,0 +1,24 @@ +{ + "global": { + "security": { + "commandTimeout": 30, + "enableInjectionProtection": true, + "restrictWorkingDirectory": true + }, + "restrictions": { + "blockedCommands": ["rm -rf /", "dd", "mkfs"], + "blockedArguments": ["--force", "-rf"], + "blockedOperators": ["&&", "||", ";", "|"] + }, + "paths": { + "allowedPaths": ["/Users/$(whoami)", "/tmp"], + "initialDir": "/Users/$(whoami)" + } + }, + "shells": { + "bash_auto": { + "type": "bash_auto", + "enabled": true + } + } +} diff --git a/src/build/__tests__/shell-config.test.ts b/src/build/__tests__/shell-config.test.ts index e30f117..6d23d4e 100644 --- a/src/build/__tests__/shell-config.test.ts +++ b/src/build/__tests__/shell-config.test.ts @@ -18,19 +18,19 @@ describe('Build Configuration', () => { }); describe('default configuration', () => { - it('should return full build config by default', () => { + it('should return platform-aware build config by default', () => { const config = getBuildConfig(); + const isUnix = process.platform !== 'win32'; - expect(config.buildName).toBe('full'); - expect(config.includeAll).toBe(true); - expect(config.includedShells).toEqual([ - 'powershell', - 'cmd', - 'gitbash', - 'bash', - 'bash_auto', - 'wsl', - ]); + if (isUnix) { + expect(config.buildName).toBe('unix'); + expect(config.includeAll).toBeUndefined(); + expect(config.includedShells).toEqual(['bash', 'bash_auto']); + } else { + expect(config.buildName).toBe('windows'); + expect(config.includeAll).toBeUndefined(); + expect(config.includedShells).toEqual(['powershell', 'cmd', 'gitbash', 'bash_auto']); + } }); it('should not be verbose by default', () => { @@ -112,7 +112,14 @@ describe('Build Configuration', () => { expect(consoleSpy).toHaveBeenCalledWith( expect.stringContaining("Unknown preset 'unknown-preset'") ); - expect(config.buildName).toBe('full'); + + // Default is now platform-aware + const isUnix = process.platform !== 'win32'; + if (isUnix) { + expect(config.buildName).toBe('unix'); + } else { + expect(config.buildName).toBe('windows'); + } consoleSpy.mockRestore(); }); diff --git a/src/build/shell-config.ts b/src/build/shell-config.ts index 1f4a1ae..12c42ce 100644 --- a/src/build/shell-config.ts +++ b/src/build/shell-config.ts @@ -86,11 +86,13 @@ export function getBuildConfig(): BuildConfig { }; } - // Default: include all shells + // Default: platform-aware selection + const isUnix = process.platform !== 'win32'; return { - includedShells: ['powershell', 'cmd', 'gitbash', 'bash', 'bash_auto', 'wsl'], - buildName: 'full', - includeAll: true, + includedShells: isUnix + ? ['bash', 'bash_auto'] + : ['powershell', 'cmd', 'gitbash', 'bash_auto'], + buildName: isUnix ? 'unix' : 'windows', verbose, }; } diff --git a/src/utils/config.ts b/src/utils/config.ts index 191ac7a..f24f3c5 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -105,11 +105,7 @@ export const DEFAULT_CONFIG: ServerConfig = { command: 'bash', args: ['-c'] }, - validatePath: (dir: string) => /^(\/mnt\/[a-zA-Z]\/|\/)/.test(dir), - wslConfig: { - mountPoint: '/mnt/', - inheritGlobalPaths: true - } + validatePath: (dir: string) => /^\/|^\.\.?[/]/.test(dir) }, wsl: { type: 'wsl',