A bridge service that allows WSL environments to execute Windows scripts (.bat, .ps1) on the Windows host automatically with full logging and monitoring.
This tool solves the problem of running Windows-native scripts from WSL (Windows Subsystem for Linux). It monitors a queue folder for new scripts, automatically executes them on Windows, captures full output logs, and organizes completed scripts.
Perfect for: AI assistants (like Claude) running in WSL that need to execute Windows commands, automated workflows, testing, or any scenario where WSL needs to trigger Windows-side operations.
- Automatic Execution: Scripts placed in the queue folder are executed immediately
- Full Logging: Complete stdout/stderr capture with timestamps
- File Stability Detection: Waits for files to be fully written before execution
- Organized Output: Automatic sorting into completed/archive folders
- Exit Code Tracking: Success/failure detection with proper logging
- Multiple Script Types: Supports .ps1, .bat, and .cmd files
- WSL Integration: Easy-to-use bash helper script for submissions
- Service Mode: Runs as a Windows Scheduled Task (starts at boot)
- Error Recovery: Automatic restart on failure
- MCP Integration: Optional MCP server for native Claude Code integration
The MCP (Model Context Protocol) server provides native Claude integration with dedicated tools:
windows_execute- Execute PowerShell commands with one tool callwindows_get_status- Check runner statuswindows_list_logs- View recent logswindows_read_log- Read specific log files
Setup:
cd /mnt/d/Dev2/wsl-windows-script-runner/mcp-server
./setup.sh
./configure-claude.shSee mcp-server/README.md for full documentation.
Usage in Claude:
Use windows_execute to get the Windows computer name
Use windows_execute to list all running Chrome processes
Check the Windows script runner status
Use the wsl-submit.sh helper script directly:
/mnt/d/Dev2/wsl-windows-script-runner/wsl-submit.sh script.ps1This option requires more manual steps but works without MCP setup.
WSL Environment Windows Host
┌─────────────────┐ ┌──────────────────────┐
│ │ │ │
│ Claude/User │ │ Script Watcher │
│ ↓ │ │ (Scheduled Task) │
│ wsl-submit.sh │───────┐ │ ↓ │
│ ↓ │ │ │ FileSystemWatcher │
│ Copy to queue │ │ │ ↓ │
│ │ │ │ Execute Script │
└─────────────────┘ │ │ ↓ │
│ │ Capture Logs │
Shared Folder │ │ ↓ │
┌─────────────────────────┼───────┼──────────────────────┐
│ /mnt/d/Dev2/wsl-... │ │ D:\Dev2\wsl-... │
│ │ │ │
│ queue/ ←───────────────┘ │ ← Monitor │
│ logs/ │ → Write │
│ completed/ │ → Move (success) │
│ archive/ │ → Move (failure) │
└─────────────────────────────────┴──────────────────────┘
wsl-windows-script-runner/
├── queue/ # Drop scripts here (monitored)
├── logs/ # Execution logs with timestamps
├── completed/ # Successfully executed scripts
├── archive/ # Failed scripts
├── ScriptWatcher.ps1 # Main file watcher service
├── Install-ScriptWatcher.ps1 # Installation script
├── Uninstall-ScriptWatcher.ps1 # Removal script
├── Get-WatcherStatus.ps1 # Status checker
├── wsl-submit.sh # WSL helper script
└── README.md # This file
# Open PowerShell as Administrator
cd D:\Dev2\wsl-windows-script-runner
# Install the service
.\Install-ScriptWatcher.ps1This will:
- Create a scheduled task named "WSL-Windows-ScriptRunner"
- Configure it to run at system startup
- Run with SYSTEM privileges for maximum compatibility
- Set up automatic restart on failure
# Check status (Windows)
.\Get-WatcherStatus.ps1
# Or from WSL
/mnt/d/Dev2/wsl-windows-script-runner/wsl-submit.sh --status# Add to your ~/.bashrc or ~/.zshrc
echo 'alias wsl-run="/mnt/d/Dev2/wsl-windows-script-runner/wsl-submit.sh"' >> ~/.bashrc
source ~/.bashrc
# Now you can use:
wsl-run script.ps1
wsl-run --status
wsl-run --logs# Using the helper script
/mnt/d/Dev2/wsl-windows-script-runner/wsl-submit.sh myscript.ps1
# Or if you added the alias
wsl-run myscript.ps1
# Or copy directly
cp myscript.bat /mnt/d/Dev2/wsl-windows-script-runner/queue/wsl-run --status# List recent logs
wsl-run --logs
# Filter logs
wsl-run --logs backup
# Tail a specific log
wsl-run --tail backup_20250115_143022.logwsl-run --watch# Run the watcher manually (for testing)
.\ScriptWatcher.ps1
# Press Ctrl+C to stop.\Get-WatcherStatus.ps1
# Or check the scheduled task
Get-ScheduledTask -TaskName "WSL-Windows-ScriptRunner"# Start
Start-ScheduledTask -TaskName "WSL-Windows-ScriptRunner"
# Stop
Stop-ScheduledTask -TaskName "WSL-Windows-ScriptRunner"
# Restart
Stop-ScheduledTask -TaskName "WSL-Windows-ScriptRunner"
Start-ScheduledTask -TaskName "WSL-Windows-ScriptRunner"From WSL:
# Create a test script
cat > /tmp/test.ps1 << 'EOF'
Write-Host "Hello from Windows!"
Write-Host "Current User: $env:USERNAME"
Write-Host "Computer: $env:COMPUTERNAME"
Get-Date
EOF
# Submit it
wsl-run /tmp/test.ps1
# View the log
wsl-run --logs testLog Output: logs/test_20250115_143022.log
From WSL:
cat > /tmp/backup.bat << 'EOF'
@echo off
echo Starting backup...
echo Timestamp: %DATE% %TIME%
REM This will fail - demonstrates error logging
copy "C:\NonExistent\file.txt" "C:\Backup\" 2>&1
echo Backup process completed
EOF
wsl-run /tmp/backup.bat
# Check the archive (failed scripts)
ls /mnt/d/Dev2/wsl-windows-script-runner/archive/When Claude needs to run a Windows command from WSL:
# Claude creates a script
cat > /tmp/windows-task.ps1 << 'EOF'
# Install a Windows application
winget install --id Microsoft.PowerToys --silent
# Check if installation succeeded
if ($LASTEXITCODE -eq 0) {
Write-Host "Installation successful"
} else {
Write-Error "Installation failed with code: $LASTEXITCODE"
exit $LASTEXITCODE
}
EOF
# Submit for execution
/mnt/d/Dev2/wsl-windows-script-runner/wsl-submit.sh /tmp/windows-task.ps1
# Wait and check the log
sleep 5
latest_log=$(ls -t /mnt/d/Dev2/wsl-windows-script-runner/logs/*.log | head -1)
cat "$latest_log"Each execution creates a timestamped log file with:
========================================
Script Execution Log
========================================
Script: D:\Dev2\wsl-windows-script-runner\queue\test.ps1
Started: 2025-01-15 14:30:22
Host: DESKTOP-ABC123
User: SYSTEM
Working Directory: D:\Dev2\wsl-windows-script-runner
========================================
--- Standard Output ---
Hello from Windows!
Current User: SYSTEM
Computer: DESKTOP-ABC123
Wednesday, January 15, 2025 2:30:22 PM
--- Standard Error ---
========================================
Execution Summary
========================================
Exit Code: 0
Completed: 2025-01-15 14:30:23
Duration: 00:00:01.1234567
Status: SUCCESS
========================================
# Check task status
Get-ScheduledTask -TaskName "WSL-Windows-ScriptRunner" | Format-List *
# Check last run result
Get-ScheduledTaskInfo -TaskName "WSL-Windows-ScriptRunner"
# View task history in Event Viewer
# Event Viewer → Task Scheduler → Task Scheduler Library-
Check if task is running:
Get-ScheduledTask -TaskName "WSL-Windows-ScriptRunner" | Select State
-
Run watcher manually to see errors:
.\ScriptWatcher.ps1
-
Check file permissions:
ls -l /mnt/d/Dev2/wsl-windows-script-runner/queue/
- File may still be locked (writing in progress)
- Check watcher is running:
Get-WatcherStatus.ps1 - Check file extension is .ps1, .bat, or .cmd
- Try restarting the scheduled task
- Check logs directory exists and is writable
- Run
Get-WatcherStatus.ps1to verify paths - Check Task Scheduler for execution errors
- Verify SYSTEM account has write permissions
# Install with custom paths
.\Install-ScriptWatcher.ps1 -TaskName "MyScriptRunner"
# Run watcher with custom paths
.\ScriptWatcher.ps1 `
-QueuePath "C:\CustomQueue" `
-LogPath "C:\CustomLogs" `
-CompletedPath "C:\CustomCompleted" `
-ArchivePath "C:\CustomArchive"If scripts are large and take time to write:
.\ScriptWatcher.ps1 -FileStabilityDelayMs 5000 # Wait 5 secondsIf you encounter execution policy errors:
# Check current policy
Get-ExecutionPolicy
# Set to allow local scripts (as Administrator)
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned -Force- Runs as SYSTEM: The scheduled task runs with SYSTEM privileges for maximum compatibility
- No Authentication: Any file placed in the queue folder will be executed
- Code Execution: Scripts have full system access - only use in trusted environments
- Network Access: Scripts can access network resources
- File Permissions: Ensure queue folder has appropriate ACLs for your security requirements
Recommendation: Use this tool only in development/testing environments or on systems where you trust all users with access to the queue folder.
# Open PowerShell as Administrator
cd D:\Dev2\wsl-windows-script-runner
# Remove the scheduled task
.\Uninstall-ScriptWatcher.ps1
# Optionally, delete the entire directory
# cd ..
# Remove-Item -Recurse -Force wsl-windows-script-runnerInstall the MCP server for seamless integration:
cd /mnt/d/Dev2/wsl-windows-script-runner/mcp-server
./setup.sh
./configure-claude.shThen simply ask Claude:
- "Use windows_execute to check Windows disk space"
- "Get the Windows version using windows_execute"
- "Check the Windows script runner status"
See mcp-server/README.md for details.
Add to your ~/.claude/CLAUDE.md:
## WSL-Windows Script Runner
When you need to execute Windows-native commands from WSL:
1. Create a PowerShell or batch script with the required commands
2. Submit using: `/mnt/d/Dev2/wsl-windows-script-runner/wsl-submit.sh script.ps1`
3. Check logs in: `/mnt/d/Dev2/wsl-windows-script-runner/logs/`
Helper alias: `wsl-run <script>`- File Watcher: Uses .NET FileSystemWatcher for efficient monitoring
- Process Execution: Spawns separate processes to capture output
- Exit Codes: Properly captures and logs process exit codes
- File Locking: Implements retry logic to ensure files are fully written
- Encoding: UTF-8 encoding for log files
- Restart Policy: Automatic restart on failure (3 retries, 1-minute interval)
This is free and unencumbered software released into the public domain.
Feel free to submit issues, fork the repository, and create pull requests for any improvements.
For issues and questions:
- Check the troubleshooting section above
- Run
Get-WatcherStatus.ps1to diagnose - Review recent logs in the
logs/directory - Check Windows Event Viewer for Task Scheduler errors
Created for: Bridging WSL and Windows environments for seamless script execution Version: 1.0.0 Last Updated: January 2025