desktop-control
by openclaw
Control desktop applications on Windows — launch, close, focus, resize, move windows, simulate keyboard/mouse input, manage processes, control VSCode, read clipboard, and capture screen info. Use when the user wants to interact with any running program, switch windows, type text, press shortcuts, open files in VSCode, manage running processes, or get system display information.
Discussion
Sign in to join the discussion.
Scan Report
Scanners4/5 ran
clawguard-rules▸52 findings4ms
View logs
1[2026-02-13T00:14:19.066Z] Running @yourclaw/clawguard-rules pattern matcher2Scanning: /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md3Content length: 14763 chars4Patterns matched: 525 [medium] MAL-008: Network reconnaissance activity6 [medium] MAL-008: Network reconnaissance activity7 [medium] MAL-008: Network reconnaissance activity8 [medium] MAL-008: Network reconnaissance activity9 [medium] MAL-008: Network reconnaissance activity10 [medium] MAL-008: Network reconnaissance activity11 [medium] MAL-008: Network reconnaissance activity12 [medium] MAL-008: Network reconnaissance activity13 [medium] MAL-008: Network reconnaissance activity14 [medium] MAL-008: Network reconnaissance activity15 [medium] MAL-008: Network reconnaissance activity16 [medium] MAL-008: Network reconnaissance activity17 [medium] MAL-008: Network reconnaissance activity18 [medium] MAL-008: Network reconnaissance activity19 [medium] MAL-008: Network reconnaissance activity20 [medium] MAL-008: Network reconnaissance activity21 [medium] MAL-008: Network reconnaissance activity22 [medium] MAL-008: Network reconnaissance activity23 [medium] MAL-008: Network reconnaissance activity24 [medium] MAL-008: Network reconnaissance activity25 [medium] MAL-008: Network reconnaissance activity26 [medium] MAL-008: Network reconnaissance activity27 [medium] MAL-008: Network reconnaissance activity28 [medium] MAL-008: Network reconnaissance activity29 [medium] MAL-008: Network reconnaissance activity30 [medium] MAL-008: Network reconnaissance activity31 [medium] MAL-008: Network reconnaissance activity32 [medium] MAL-008: Network reconnaissance activity33 [medium] MAL-008: Network reconnaissance activity34 [medium] MAL-008: Network reconnaissance activity35 [medium] MAL-008: Network reconnaissance activity36 [medium] MAL-008: Network reconnaissance activity37 [medium] MAL-008: Network reconnaissance activity38 [medium] MAL-008: Network reconnaissance activity39 [medium] MAL-008: Network reconnaissance activity40 [medium] MAL-008: Network reconnaissance activity41 [medium] MAL-008: Network reconnaissance activity42 [medium] MAL-008: Network reconnaissance activity43 [medium] MAL-008: Network reconnaissance activity44 [medium] MAL-008: Network reconnaissance activity45 [medium] MAL-008: Network reconnaissance activity46 [medium] MAL-008: Network reconnaissance activity47 [medium] MAL-008: Network reconnaissance activity48 [medium] MAL-008: Network reconnaissance activity49 [medium] MAL-008: Network reconnaissance activity50 [medium] MAL-008: Network reconnaissance activity51 [medium] MAL-008: Network reconnaissance activity52 [medium] MAL-008: Network reconnaissance activity53 [medium] MAL-008: Network reconnaissance activity54 [medium] MAL-008: Network reconnaissance activity55 [medium] MAL-008: Network reconnaissance activity56 [medium] MAL-008: Network reconnaissance activity57✓ Completed in 4ms
gitleaks▸0 findings126425ms
View logs
1[2026-02-13T00:16:25.491Z] $ gitleaks detect --source /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win --report-format json --report-path /dev/stdout --no-git23⚠ stderr output:4○5 │╲6 │ ○7 ○ ░8 ░ gitleaks910[90m12:16AM[0m [31mFTL[0m [1mReport path is not writable: /dev/stdout[0m [36merror=[0m[31m[1m"open /dev/stdout: no such device or address"[0m[0m1112Process exited with code 113✓ Completed in 126425ms
semgrep▸0 findings183123ms
View logs
1[2026-02-13T00:17:22.192Z] $ semgrep scan --json --quiet --config auto /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win2{"version":"1.151.0","results":[],"errors":[],"paths":{"scanned":["/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/_meta.json","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/app-control.ps1.txt","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/input-sim.ps1.txt","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/process-manager.ps1.txt","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/screen-info.ps1.txt","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/vscode-control.ps1.txt"]},"time":{"rules":[],"rules_parse_time":14.236198902130127,"profiling_times":{"config_time":20.608436346054077,"core_time":19.011754751205444,"ignores_time":0.020355224609375,"total_time":39.69200921058655},"parsing_time":{"total_time":0.0,"per_file_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_files":[]},"scanning_time":{"total_time":0.2938828468322754,"per_file_time":{"mean":0.01959218978881836,"std_dev":0.0009568232132763417},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_files":[]},"matching_time":{"total_time":0.0,"per_file_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_files":[]},"tainting_time":{"total_time":0.0,"per_def_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_defs":[]},"fixpoint_timeouts":[],"prefiltering":{"project_level_time":0.0,"file_level_time":0.0,"rules_with_project_prefilters_ratio":0.0,"rules_with_file_prefilters_ratio":0.9911764705882353,"rules_selected_ratio":0.008823529411764706,"rules_matched_ratio":0.008823529411764706},"targets":[],"total_bytes":0,"max_memory_bytes":1153514048},"engine_requested":"OSS","skipped_rules":[],"profiling_results":[]}34Process exited with code 05✓ Completed in 183123ms
mcp-scan▸1 finding137385ms
View logs
1[2026-02-13T00:16:36.456Z] $ mcp-scan --skills /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win --json2{3 "/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent": {4 "client": "not-available",5 "path": "/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent",6 "servers": [7 {8 "name": "desktop-control-win",9 "server": {10 "path": "/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win",11 "type": "skill"12 },13 "signature": {14 "metadata": {15 "meta": null,16 "protocolVersion": "built-in",17 "capabilities": {18 "experimental": null,19 "logging": null,20 "prompts": null,21 "resources": null,22 "tools": {23 "listChanged": false24 },25 "completions": null,26 "tasks": null27 },28 "serverInfo": {29 "name": "desktop-control",30 "title": null,31 "version": "skills",32 "websiteUrl": null,33 "icons": null34 },35 "instructions": "Control desktop applications on Windows \u2014 launch, close, focus, resize, move windows, simulate keyboard/mouse input, manage processes, control VSCode, read clipboard, and capture screen info. Use when the user wants to interact with any running program, switch windows, type text, press shortcuts, open files in VSCode, manage running processes, or get system display information.",36 "prompts": {37 "listChanged": false38 },39 "resources": {40 "subscribe": null,41 "listChanged": false42 }43 },44 "prompts": [45 {46 "name": "SKILL.md",47 "title": null,48 "description": "\n\n# Desktop Control \u2014 Full Windows Application Control\n\n## Publish-only note (ClawHub)\nThis Publish package includes scripts as `.ps1.txt` because Publish only accepts text files.\nAfter download, rename each `*.ps1.txt` to `*.ps1` and place them in a `scripts/` folder to use the skill.\n\nControl any desktop application on this Windows machine. Launch programs, manage windows, simulate input, control VSCode, and monitor processes \u2014 all via PowerShell scripts.\n\n## CRITICAL: Script Location\n\nAll scripts are located relative to this skill folder:\n\n```\nSKILL_DIR = ~/.openclaw/workspace/skills/desktop-control/scripts\n```\n\nWhen running scripts, always use the full path:\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/<script>.ps1\" -Action <action> [params]\n```\n\n## IMPORTANT: Safety Rules\n\n1. **Before closing windows** \u2014 Ask user for confirmation if the window might have unsaved work\n2. **Before killing processes** \u2014 Always confirm with user unless they explicitly asked to kill it\n3. **Before sending input** \u2014 Make sure the correct window is focused first\n4. **Clipboard** \u2014 Warn user if you are overwriting clipboard content\n\n---\n\n## Action Reference\n\n### 1. Window Management (`app-control.ps1`)\n\nManage application windows \u2014 launch, close, focus, resize, move, snap.\n\n#### List all visible windows\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action list-windows\n```\nReturns: PID, window title, position (X,Y), size (W\u00d7H), state (Normal/Minimized/Maximized)\n\n#### Launch an application\n```powershell\n# By name (searches PATH and common locations)\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action launch -Target \"notepad\"\n\n# By full path\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action launch -Target \"C:\\Program Files\\MyApp\\app.exe\"\n\n# With arguments\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action launch -Target \"code\" -Arguments \"C:\\Users\\ibach\\project\"\n```\n\n#### Focus (bring to foreground)\n```powershell\n# By window title (partial match)\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action focus -Target \"Visual Studio Code\"\n\n# By PID\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action focus -ProcId 12345\n```\n\n#### Close a window gracefully\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action close -Target \"Notepad\"\n```\n\n#### Minimize / Maximize / Restore\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action minimize -Target \"Visual Studio Code\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action maximize -Target \"Visual Studio Code\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action restore -Target \"Visual Studio Code\"\n```\n\n#### Move a window\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action move -Target \"Notepad\" -X 100 -Y 200\n```\n\n#### Resize a window\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action resize -Target \"Notepad\" -Width 800 -Height 600\n```\n\n#### Snap a window (half-screen)\n```powershell\n# Options: left, right, top, bottom, topleft, topright, bottomleft, bottomright\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action snap -Target \"Notepad\" -Position left\n```\n\n---\n\n### 2. Input Simulation (`input-sim.ps1`)\n\nSimulate keyboard and mouse input into any application.\n\n**IMPORTANT:** Always focus the target window FIRST using `app-control.ps1 -Action focus` before sending input.\n\n#### Type text\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action type-text -Text \"Hello, World!\"\n```\n\n#### Send keyboard shortcut\n```powershell\n# Common shortcuts: Ctrl+S, Ctrl+C, Ctrl+V, Ctrl+Z, Alt+F4, Ctrl+Shift+P, Win+D\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"Ctrl+S\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"Ctrl+Shift+P\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"Alt+Tab\"\n```\n\n#### Send special keys\n```powershell\n# Keys: Enter, Tab, Escape, Backspace, Delete, Up, Down, Left, Right, Home, End, PageUp, PageDown, F1-F12\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"Enter\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"F5\"\n```\n\n#### Mouse click at coordinates\n```powershell\n# Left click\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-click -X 500 -Y 300\n\n# Right click\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-click -X 500 -Y 300 -Button right\n\n# Double click\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-click -X 500 -Y 300 -DoubleClick\n```\n\n#### Move mouse\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-move -X 500 -Y 300\n```\n\n#### Scroll\n```powershell\n# Scroll up (positive) or down (negative)\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-scroll -Clicks 3\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-scroll -Clicks -3\n```\n\n---\n\n### 3. VSCode Control (`vscode-control.ps1`)\n\nControl Visual Studio Code through the `code` CLI and extensions.\n\n#### Open a file\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action open-file -Path \"C:\\Users\\ibach\\project\\main.py\"\n```\n\n#### Open a file at a specific line\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action goto -Path \"C:\\Users\\ibach\\project\\main.py\" -Line 42\n```\n\n#### Open a folder/workspace\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action open-folder -Path \"C:\\Users\\ibach\\project\"\n```\n\n#### Open diff view\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action open-diff -Path \"file1.py\" -Path2 \"file2.py\"\n```\n\n#### List installed extensions\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action list-extensions\n```\n\n#### Install an extension\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action install-extension -ExtensionId \"ms-python.python\"\n```\n\n#### Uninstall an extension\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action uninstall-extension -ExtensionId \"ms-python.python\"\n```\n\n#### Open a new terminal in VSCode\n```powershell\n# This focuses VSCode and sends Ctrl+` to toggle terminal\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action new-terminal\n```\n\n#### Open VSCode command palette\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action command-palette\n```\n\n#### Run a VSCode command by name\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action run-command -Command \"workbench.action.toggleSidebarVisibility\"\n```\n\n---\n\n### 4. Process Management (`process-manager.ps1`)\n\nMonitor and manage running processes.\n\n#### List running processes\n```powershell\n# All processes\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action list\n\n# Filter by name\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action list -Name \"code\"\n\n# Top N by memory\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action list -SortBy memory -Top 10\n```\n\n#### Get detailed process info\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action info -ProcId 12345\n```\n\n#### Start a new process\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action start -Path \"notepad.exe\" -Arguments \"C:\\file.txt\"\n```\n\n#### Kill a process (CONFIRM WITH USER FIRST)\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action kill -ProcId 12345\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action kill -Name \"notepad\"\n```\n\n#### Monitor process resource usage\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action monitor -ProcId 12345 -Duration 10\n```\n\n---\n\n### 5. Screen & System Info (`screen-info.ps1`)\n\nGet display information, window details, clipboard, and screenshots.\n\n#### List displays/monitors\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action displays\n```\n\n#### Get active (focused) window info\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action active-window\n```\n\n#### Get detailed window info\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action window-info -Target \"Visual Studio Code\"\n```\n\n#### Take a screenshot\n```powershell\n# Full screen\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action screenshot -OutputPath \"$HOME/screenshot.png\"\n\n# Specific window\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action screenshot -Target \"Notepad\" -OutputPath \"$HOME/notepad-screenshot.png\"\n```\n\n#### Read clipboard\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action clipboard-get\n```\n\n#### Set clipboard text\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action clipboard-set -Text \"Text to copy\"\n```\n\n#### Get system info (uptime, OS, resolution)\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action system-info\n```\n\n---\n\n## Common Workflows\n\n### Open a file in VSCode and navigate to a specific line\n```\n1. vscode-control.ps1 -Action goto -Path \"C:\\path\\to\\file.py\" -Line 42\n```\n\n### Type something into a specific application\n```\n1. app-control.ps1 -Action focus -Target \"Notepad\"\n2. input-sim.ps1 -Action type-text -Text \"Hello World\"\n```\n\n### Save the current document in any app\n```\n1. app-control.ps1 -Action focus -Target \"<app name>\"\n2. input-sim.ps1 -Action send-keys -Keys \"Ctrl+S\"\n```\n\n### Arrange two windows side-by-side\n```\n1. app-control.ps1 -Action snap -Target \"Visual Studio Code\" -Position left\n2. app-control.ps1 -Action snap -Target \"Chrome\" -Position right\n```\n\n### Kill a frozen application\n```\n1. process-manager.ps1 -Action list -Name \"frozen-app\"\n (note the PID)\n2. ASK USER FOR CONFIRMATION\n3. process-manager.ps1 -Action kill -ProcId <pid>\n```\n\n### Take a screenshot of a specific window\n```\n1. screen-info.ps1 -Action screenshot -Target \"Chrome\" -OutputPath \"$HOME/chrome.png\"\n```\n\n---\n\n## Error Handling\n\n- If a script returns exit code 0 \u2192 success\n- If a script returns exit code 1 \u2192 error (check stderr output for details)\n- If a window is not found \u2192 try `list-windows` first to get the exact title\n- If `code` CLI is not found \u2192 VSCode may not be in PATH; try launching it first\n\n## Troubleshooting\n\n- **\"Window not found\"** \u2192 Use `list-windows` to see exact window titles, then match more precisely\n- **\"Access denied\"** \u2192 Some system processes need admin rights; inform the user\n- **Input not working** \u2192 Make sure the target window is focused AND in the foreground\n- **VSCode CLI not found** \u2192 Try `code --version` first; if missing, launch VSCode from Start Menu\n",49 "arguments": [],50 "icons": null,51 "meta": null52 }53 ],54 "resources": [55 {56 "name": "_meta.json",57 "title": null,58 "uri": "skill://_meta.json",59 "description": "{\n \"owner\": \"lexylent\",\n \"slug\": \"desktop-control-win\",\n \"displayName\": \"Desktop Control (Windows)\",\n \"latest\": {\n \"version\": \"1.0.1\",\n \"publishedAt\": 1770841588053,\n \"commit\": \"https://github.com/openclaw/skills/commit/f8e7a684f74e4d5eb275fe73390976e23684a949\"\n },\n \"history\": []\n}\n",60 "mimeType": null,61 "size": null,62 "icons": null,63 "annotations": null,64 "meta": null65 },66 {67 "name": "vscode-control.ps1.txt",68 "title": null,69 "uri": "skill://scripts/vscode-control.ps1.txt",70 "description": "# ============================================================\n# vscode-control.ps1 \u2014 VSCode Control for OpenClaw\n# Actions: open-file, open-folder, open-diff, goto,\n# list-extensions, install-extension, uninstall-extension,\n# new-terminal, command-palette, run-command, status, help\n# ============================================================\n\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"open-file\",\"open-folder\",\"open-diff\",\"goto\",\"list-extensions\",\"install-extension\",\"uninstall-extension\",\"new-terminal\",\"command-palette\",\"run-command\",\"status\",\"help\")]\n [string]$Action,\n\n [string]$Path = \"\",\n [string]$Path2 = \"\",\n [int]$Line = 0,\n [int]$Column = 0,\n [string]$ExtensionId = \"\",\n [string]$Command = \"\",\n [switch]$NewWindow,\n [switch]$Reuse\n)\n\n# --- Locate code CLI ---\nfunction Find-VSCodeCLI {\n # Try 'code' in PATH first\n $codePath = Get-Command \"code\" -ErrorAction SilentlyContinue\n if ($codePath) { return $codePath.Source }\n\n # Common install locations\n $candidates = @(\n \"$env:LOCALAPPDATA\\Programs\\Microsoft VS Code\\bin\\code.cmd\",\n \"$env:ProgramFiles\\Microsoft VS Code\\bin\\code.cmd\",\n \"${env:ProgramFiles(x86)}\\Microsoft VS Code\\bin\\code.cmd\",\n \"$env:LOCALAPPDATA\\Programs\\Microsoft VS Code\\Code.exe\",\n \"$env:ProgramFiles\\Microsoft VS Code\\Code.exe\"\n )\n foreach ($c in $candidates) {\n if (Test-Path $c) { return $c }\n }\n\n # VSCode Insiders\n $insiders = Get-Command \"code-insiders\" -ErrorAction SilentlyContinue\n if ($insiders) { return $insiders.Source }\n\n return $null\n}\n\n$codeCLI = Find-VSCodeCLI\nif (-not $codeCLI -and $Action -ne \"help\") {\n Write-Error \"VSCode CLI ('code') not found. Make sure VSCode is installed and 'code' is in PATH.\"\n Write-Error \"Tip: Open VSCode, press Ctrl+Shift+P, type 'Shell Command: Install code command in PATH'\"\n exit 1\n}\n\n# --- Helper to focus VSCode window ---\nfunction Focus-VSCode {\n Add-Type @\"\n using System;\n using System.Runtime.InteropServices;\n using System.Text;\n public class VSCFocus {\n [DllImport(\"user32.dll\")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);\n [DllImport(\"user32.dll\")] public static extern bool IsWindowVisible(IntPtr hWnd);\n [DllImport(\"user32.dll\", CharSet=CharSet.Auto)]\n public static extern int GetWindowText(IntPtr hWnd, StringBuilder sb, int maxCount);\n [DllImport(\"user32.dll\")] public static extern int GetWindowTextLength(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool SetForegroundWindow(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);\n [DllImport(\"user32.dll\")] public static extern bool IsIconic(IntPtr hWnd);\n public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n }\n\"@\n $found = $false\n $callback = [VSCFocus+EnumWindowsProc]{\n param($hWnd, $lParam)\n if ([VSCFocus]::IsWindowVisible($hWnd)) {\n $len = [VSCFocus]::GetWindowTextLength($hWnd)\n if ($len -gt 0) {\n $sb = New-Object System.Text.StringBuilder($len + 1)\n [VSCFocus]::GetWindowText($hWnd, $sb, $sb.Capacity) | Out-Null\n if ($sb.ToString() -like \"*Visual Studio Code*\") {\n if ([VSCFocus]::IsIconic($hWnd)) {\n [VSCFocus]::ShowWindow($hWnd, 9) | Out-Null\n }\n [VSCFocus]::SetForegroundWindow($hWnd) | Out-Null\n $script:found = $true\n return $false # Stop enumeration\n }\n }\n }\n return $true\n }\n [VSCFocus]::EnumWindows($callback, [IntPtr]::Zero) | Out-Null\n}\n\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output @\"\ndesktop-control / vscode-control.ps1\nActions:\n open-file -Path <file> Open a file in VSCode\n goto -Path <file> -Line <n> Open file at line[:column]\n open-folder -Path <folder> Open folder/workspace [-NewWindow]\n open-diff -Path <file1> -Path2 <file2> Diff two files\n list-extensions List installed extensions\n install-extension -ExtensionId <id> Install extension (e.g. \"ms-python.python\")\n uninstall-extension -ExtensionId <id> Uninstall extension\n new-terminal Open/toggle integrated terminal\n command-palette Open command palette (Ctrl+Shift+P)\n run-command -Command <cmd> Run a VSCode command by ID\n status Show VSCode version and status\n\"@\n }\n\n \"open-file\" {\n if (-not $Path) { Write-Error \"Missing -Path parameter\"; exit 1 }\n $resolvedPath = Resolve-Path $Path -ErrorAction SilentlyContinue\n if (-not $resolvedPath) { $resolvedPath = $Path }\n $args_ = @(\"--goto\", \"$resolvedPath\")\n if ($Reuse) { $args_ += \"--reuse-window\" }\n & $codeCLI @args_\n Write-Output \"Opened in VSCode: $resolvedPath\"\n }\n\n \"goto\" {\n if (-not $Path) { Write-Error \"Missing -Path parameter\"; exit 1 }\n if ($Line -le 0) { Write-Error \"Missing -Line parameter\"; exit 1 }\n $resolvedPath = Resolve-Path $Path -ErrorAction SilentlyContinue\n if (-not $resolvedPath) { $resolvedPath = $Path }\n $location = \"${resolvedPath}:${Line}\"\n if ($Column -gt 0) { $location += \":${Column}\" }\n & $codeCLI --goto $location\n Write-Output \"Opened in VSCode: $location\"\n }\n\n \"open-folder\" {\n if (-not $Path) { Write-Error \"Missing -Path parameter\"; exit 1 }\n $resolvedPath = Resolve-Path $Path -ErrorAction SilentlyContinue\n if (-not $resolvedPath) { $resolvedPath = $Path }\n $args_ = @(\"$resolvedPath\")\n if ($NewWindow) { $args_ += \"--new-window\" }\n & $codeCLI @args_\n Write-Output \"Opened folder in VSCode: $resolvedPath\"\n }\n\n \"open-diff\" {\n if (-not $Path -or -not $Path2) { Write-Error \"Missing -Path and -Path2 parameters\"; exit 1 }\n $r1 = Resolve-Path $Path -ErrorAction SilentlyContinue\n $r2 = Resolve-Path $Path2 -ErrorAction SilentlyContinue\n if (-not $r1) { $r1 = $Path }\n if (-not $r2) { $r2 = $Path2 }\n & $codeCLI --diff \"$r1\" \"$r2\"\n Write-Output \"Opened diff: $r1 <-> $r2\"\n }\n\n \"list-extensions\" {\n Write-Output \"Installed VSCode extensions:\"\n Write-Output \"---\"\n & $codeCLI --list-extensions --show-versions\n }\n\n \"install-extension\" {\n if (-not $ExtensionId) { Write-Error \"Missing -ExtensionId parameter\"; exit 1 }\n Write-Output \"Installing extension: $ExtensionId ...\"\n & $codeCLI --install-extension $ExtensionId --force\n if ($LASTEXITCODE -eq 0) {\n Write-Output \"Successfully installed: $ExtensionId\"\n } else {\n Write-Error \"Failed to install: $ExtensionId\"; exit 1\n }\n }\n\n \"uninstall-extension\" {\n if (-not $ExtensionId) { Write-Error \"Missing -ExtensionId parameter\"; exit 1 }\n Write-Output \"Uninstalling extension: $ExtensionId ...\"\n & $codeCLI --uninstall-extension $ExtensionId\n if ($LASTEXITCODE -eq 0) {\n Write-Output \"Successfully uninstalled: $ExtensionId\"\n } else {\n Write-Error \"Failed to uninstall: $ExtensionId\"; exit 1\n }\n }\n\n \"new-terminal\" {\n Focus-VSCode\n Start-Sleep -Milliseconds 300\n Add-Type -AssemblyName System.Windows.Forms\n # Ctrl+` toggles terminal\n [System.Windows.Forms.SendKeys]::SendWait(\"^``\")\n Write-Output \"Toggled integrated terminal in VSCode\"\n }\n\n \"command-palette\" {\n Focus-VSCode\n Start-Sleep -Milliseconds 300\n Add-Type -AssemblyName System.Windows.Forms\n # Ctrl+Shift+P opens command palette\n [System.Windows.Forms.SendKeys]::SendWait(\"^+p\")\n Write-Output \"Opened command palette in VSCode\"\n }\n\n \"run-command\" {\n if (-not $Command) { Write-Error \"Missing -Command parameter (e.g. 'workbench.action.toggleSidebarVisibility')\"; exit 1 }\n # Use the code CLI to execute a command via extension\n # Fallback: focus VSCode, open command palette, type the command\n Focus-VSCode\n Start-Sleep -Milliseconds 300\n Add-Type -AssemblyName System.Windows.Forms\n [System.Windows.Forms.SendKeys]::SendWait(\"^+p\")\n Start-Sleep -Milliseconds 500\n $escaped = $Command -replace '([\\+\\^\\%\\~\\(\\)\\{\\}\\[\\]])', '{$1}'\n [System.Windows.Forms.SendKeys]::SendWait($escaped)\n Start-Sleep -Milliseconds 200\n [System.Windows.Forms.SendKeys]::SendWait(\"{ENTER}\")\n Write-Output \"Executed VSCode command: $Command\"\n }\n\n \"status\" {\n Write-Output \"VSCode Status:\"\n Write-Output \"---\"\n & $codeCLI --version\n Write-Output \"---\"\n $vscProcs = Get-Process -Name \"Code\" -ErrorAction SilentlyContinue\n if ($vscProcs) {\n $totalMem = ($vscProcs | Measure-Object -Property WorkingSet64 -Sum).Sum / 1MB\n Write-Output \"Running: Yes ($($vscProcs.Count) processes, $([math]::Round($totalMem))MB total memory)\"\n } else {\n Write-Output \"Running: No\"\n }\n }\n }\n exit 0\n} catch {\n Write-Error \"ERROR: $_\"\n exit 1\n}\n",71 "mimeType": null,72 "size": null,73 "icons": null,74 "annotations": null,75 "meta": null76 },77 {78 "name": "process-manager.ps1.txt",79 "title": null,80 "uri": "skill://scripts/process-manager.ps1.txt",81 "description": "# process-manager.ps1 - Process Management for OpenClaw\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"list\",\"info\",\"start\",\"kill\",\"monitor\",\"wait\",\"help\")]\n [string]$Action,\n [string]$Name = \"\",\n [int]$ProcId = 0,\n [string]$Path = \"\",\n [string]$Arguments = \"\",\n [ValidateSet(\"memory\",\"cpu\",\"name\",\"pid\",\"\")][string]$SortBy = \"\",\n [int]$Top = 0,\n [int]$Duration = 5,\n [switch]$Force\n)\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output \"process-manager.ps1 - list, info, start, kill, monitor, wait\"\n Write-Output \" list [-Name [filter]] [-SortBy memory|cpu|name|pid] [-Top [n]]\"\n Write-Output \" info -ProcId [pid]\"\n Write-Output \" start -Path [exe] [-Arguments [args]]\"\n Write-Output \" kill -ProcId [pid] | -Name [name] [-Force]\"\n Write-Output \" monitor -ProcId [pid] [-Duration [seconds]]\"\n Write-Output \" wait -ProcId [pid]\"\n }\n \"list\" {\n $procs = Get-Process -ErrorAction SilentlyContinue\n if ($Name) { $procs = $procs | Where-Object { $_.ProcessName -like \"*$Name*\" } }\n $data = $procs | Where-Object { $_.Id -ne 0 } | ForEach-Object {\n [PSCustomObject]@{\n PID=$_.Id; Name=$_.ProcessName\n MemMB=[math]::Round($_.WorkingSet64/1MB,1)\n CPU=if($_.CPU){[math]::Round($_.CPU,1)}else{0.0}\n Title=if($_.MainWindowTitle){$_.MainWindowTitle}else{\"-\"}\n }\n }\n switch ($SortBy) {\n \"memory\" { $data = $data | Sort-Object MemMB -Descending }\n \"cpu\" { $data = $data | Sort-Object CPU -Descending }\n \"name\" { $data = $data | Sort-Object Name }\n \"pid\" { $data = $data | Sort-Object PID }\n default { $data = $data | Sort-Object MemMB -Descending }\n }\n if ($Top -gt 0) { $data = $data | Select-Object -First $Top }\n $data | ForEach-Object {\n $t = if($_.Title -ne \"-\"){ ' Title=\"' + $_.Title + '\"' } else { \"\" }\n Write-Output (\"PID={0,-6} Mem={1,8}MB CPU={2,8}s Name={3}{4}\" -f $_.PID,$_.MemMB,$_.CPU,$_.Name,$t)\n }\n Write-Output \"`nTotal: $($data.Count) processes$(if($Name){\" matching '$Name'\"})\"\n }\n \"info\" {\n if ($ProcId -le 0) { Write-Error \"Missing -ProcId\"; exit 1 }\n $proc = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $proc) { Write-Error \"Not found: PID=$ProcId\"; exit 1 }\n $st = try{$proc.StartTime.ToString(\"yyyy-MM-dd HH:mm:ss\")}catch{\"N/A\"}\n $ep = try{$proc.Path}catch{\"N/A\"}\n Write-Output \"PID=$ProcId Name=$($proc.ProcessName)\"\n Write-Output \"Path: $ep\"\n Write-Output \"Started: $st\"\n Write-Output \"Memory: $([math]::Round($proc.WorkingSet64/1MB,1))MB (peak $([math]::Round($proc.PeakWorkingSet64/1MB,1))MB)\"\n Write-Output \"CPU: $([math]::Round($proc.CPU,2))s Threads: $($proc.Threads.Count) Handles: $($proc.HandleCount)\"\n Write-Output \"Window: $(if($proc.MainWindowTitle){$proc.MainWindowTitle}else{'(none)'})\"\n Write-Output \"Responding: $($proc.Responding) Priority: $($proc.PriorityClass)\"\n }\n \"start\" {\n if (-not $Path) { Write-Error \"Missing -Path\"; exit 1 }\n $p = if($Arguments){Start-Process $Path -ArgumentList $Arguments -PassThru}else{Start-Process $Path -PassThru}\n Start-Sleep -Milliseconds 500\n Write-Output \"Started: $Path (PID=$($p.Id))\"\n }\n \"kill\" {\n if ($ProcId -gt 0) {\n $p = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $p) { Write-Error \"Not found: PID=$ProcId\"; exit 1 }\n if ($Force) { Stop-Process -Id $ProcId -Force } else { Stop-Process -Id $ProcId }\n Write-Output \"Killed: $($p.ProcessName) (PID=$ProcId)\"\n } elseif ($Name) {\n $ps = Get-Process -Name \"*$Name*\" -EA SilentlyContinue\n if (-not $ps) { Write-Error \"No match: '$Name'\"; exit 1 }\n $ps | ForEach-Object { if($Force){Stop-Process -Id $_.Id -Force}else{Stop-Process -Id $_.Id} }\n Write-Output \"Killed: $($ps.Count) process(es) matching '$Name'\"\n } else { Write-Error \"Missing -ProcId or -Name\"; exit 1 }\n }\n \"monitor\" {\n if ($ProcId -le 0) { Write-Error \"Missing -ProcId\"; exit 1 }\n $proc = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $proc) { Write-Error \"Not found: PID=$ProcId\"; exit 1 }\n Write-Output \"Monitoring PID=$ProcId ($($proc.ProcessName)) for ${Duration}s...\"\n $prev = $proc.CPU\n for ($i=0; $i -lt $Duration; $i++) {\n Start-Sleep 1\n $proc = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $proc) { Write-Output \"Process exited.\"; break }\n $d = [math]::Round($proc.CPU - $prev, 2); $prev = $proc.CPU\n Write-Output \"[$((Get-Date).ToString('HH:mm:ss'))] Mem=$([math]::Round($proc.WorkingSet64/1MB,1))MB CPU-delta=${d}s Threads=$($proc.Threads.Count)\"\n }\n }\n \"wait\" {\n if ($ProcId -le 0) { Write-Error \"Missing -ProcId\"; exit 1 }\n $proc = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $proc) { Write-Output \"PID=$ProcId already exited.\"; exit 0 }\n Write-Output \"Waiting for PID=$ProcId ($($proc.ProcessName))...\"\n $proc.WaitForExit()\n Write-Output \"PID=$ProcId exited (code: $($proc.ExitCode))\"\n }\n }\n exit 0\n} catch { Write-Error \"ERROR: $_\"; exit 1 }\n",82 "mimeType": null,83 "size": null,84 "icons": null,85 "annotations": null,86 "meta": null87 },88 {89 "name": "app-control.ps1.txt",90 "title": null,91 "uri": "skill://scripts/app-control.ps1.txt",92 "description": "# ============================================================\n# app-control.ps1 \u2014 Window Management for OpenClaw\n# Actions: list-windows, launch, focus, close, minimize,\n# maximize, restore, move, resize, snap, help\n# ============================================================\n\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"list-windows\",\"launch\",\"focus\",\"close\",\"minimize\",\"maximize\",\"restore\",\"move\",\"resize\",\"snap\",\"help\")]\n [string]$Action,\n\n [string]$Target = \"\",\n [int]$ProcId = 0,\n [string]$Arguments = \"\",\n [int]$X = -1,\n [int]$Y = -1,\n [int]$Width = -1,\n [int]$Height = -1,\n [ValidateSet(\"left\",\"right\",\"top\",\"bottom\",\"topleft\",\"topright\",\"bottomleft\",\"bottomright\",\"\")]\n [string]$Position = \"\"\n)\n\n# --- Win32 API ---\nAdd-Type @\"\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Collections.Generic;\n\npublic class Win32Window {\n [DllImport(\"user32.dll\")] public static extern bool SetForegroundWindow(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);\n [DllImport(\"user32.dll\")] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);\n [DllImport(\"user32.dll\")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);\n [DllImport(\"user32.dll\")] public static extern IntPtr GetForegroundWindow();\n [DllImport(\"user32.dll\")] public static extern bool IsWindowVisible(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool IsIconic(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool IsZoomed(IntPtr hWnd);\n [DllImport(\"user32.dll\", SetLastError=true, CharSet=CharSet.Auto)]\n public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);\n [DllImport(\"user32.dll\")] public static extern int GetWindowTextLength(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);\n [DllImport(\"user32.dll\")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);\n [DllImport(\"user32.dll\")] public static extern bool BringWindowToTop(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern IntPtr SetFocus(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);\n [DllImport(\"kernel32.dll\")] public static extern uint GetCurrentThreadId();\n [DllImport(\"user32.dll\")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);\n\n public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n\n [StructLayout(LayoutKind.Sequential)]\n public struct RECT { public int Left, Top, Right, Bottom; }\n\n public const int SW_HIDE = 0;\n public const int SW_NORMAL = 1;\n public const int SW_MINIMIZE = 6;\n public const int SW_MAXIMIZE = 3;\n public const int SW_RESTORE = 9;\n public const int SW_SHOW = 5;\n\n public static void ForceForeground(IntPtr hWnd) {\n IntPtr fg = GetForegroundWindow();\n uint fgThread = GetWindowThreadProcessId(fg, IntPtr.Zero);\n uint curThread = GetCurrentThreadId();\n if (fgThread != curThread) {\n AttachThreadInput(curThread, fgThread, true);\n BringWindowToTop(hWnd);\n ShowWindow(hWnd, SW_SHOW);\n AttachThreadInput(curThread, fgThread, false);\n }\n SetForegroundWindow(hWnd);\n }\n}\n\"@\n\n# --- Helpers ---\nfunction Get-AllWindows {\n $windows = [System.Collections.ArrayList]::new()\n $callback = [Win32Window+EnumWindowsProc]{\n param($hWnd, $lParam)\n if ([Win32Window]::IsWindowVisible($hWnd)) {\n $len = [Win32Window]::GetWindowTextLength($hWnd)\n if ($len -gt 0) {\n $sb = New-Object System.Text.StringBuilder($len + 1)\n [Win32Window]::GetWindowText($hWnd, $sb, $sb.Capacity) | Out-Null\n $title = $sb.ToString()\n $wpid = [uint32]0\n [Win32Window]::GetWindowThreadProcessId($hWnd, [ref]$wpid) | Out-Null\n $rect = New-Object Win32Window+RECT\n [Win32Window]::GetWindowRect($hWnd, [ref]$rect) | Out-Null\n $state = \"Normal\"\n if ([Win32Window]::IsIconic($hWnd)) { $state = \"Minimized\" }\n elseif ([Win32Window]::IsZoomed($hWnd)) { $state = \"Maximized\" }\n $null = $windows.Add([PSCustomObject]@{\n Handle = $hWnd\n WinPID = $wpid\n Title = $title\n X = $rect.Left\n Y = $rect.Top\n Width = $rect.Right - $rect.Left\n Height = $rect.Bottom - $rect.Top\n State = $state\n })\n }\n }\n return $true\n }\n [Win32Window]::EnumWindows($callback, [IntPtr]::Zero) | Out-Null\n return $windows\n}\n\nfunction Find-Window {\n param([string]$TitlePattern, [int]$ByProcId = 0)\n $all = Get-AllWindows\n if ($ByProcId -gt 0) {\n return $all | Where-Object { $_.WinPID -eq $ByProcId } | Select-Object -First 1\n }\n if ($TitlePattern) {\n $match = $all | Where-Object { $_.Title -eq $TitlePattern } | Select-Object -First 1\n if (-not $match) {\n $match = $all | Where-Object { $_.Title -like \"*$TitlePattern*\" } | Select-Object -First 1\n }\n return $match\n }\n return $null\n}\n\nfunction Get-ScreenSize {\n Add-Type -AssemblyName System.Windows.Forms\n $screen = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea\n return @{ Width = $screen.Width; Height = $screen.Height; X = $screen.X; Y = $screen.Y }\n}\n\n# --- Actions ---\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output @\"\ndesktop-control / app-control.ps1\nActions:\n list-windows List all visible windows\n launch -Target <path> Launch an application [-Arguments <args>]\n focus -Target <title> Bring window to foreground [-ProcId <pid>]\n close -Target <title> Close a window gracefully [-ProcId <pid>]\n minimize -Target <title> Minimize a window [-ProcId <pid>]\n maximize -Target <title> Maximize a window [-ProcId <pid>]\n restore -Target <title> Restore a window [-ProcId <pid>]\n move -Target <title> Move window -X <x> -Y <y>\n resize -Target <title> Resize window -Width <w> -Height <h>\n snap -Target <title> Snap window -Position <left|right|...>\n\"@\n }\n\n \"list-windows\" {\n $wins = Get-AllWindows | Where-Object { $_.Width -gt 0 -and $_.Height -gt 0 }\n $wins | ForEach-Object {\n Write-Output (\"PID={0} State={1} Pos=({2},{3}) Size={4}x{5} Title=\"\"{6}\"\"\" -f $_.WinPID, $_.State, $_.X, $_.Y, $_.Width, $_.Height, $_.Title)\n }\n Write-Output \"\"\n Write-Output \"Total: $($wins.Count) windows\"\n }\n\n \"launch\" {\n if (-not $Target) { Write-Error \"Missing -Target (application path or name)\"; exit 1 }\n if ($Arguments) {\n $proc = Start-Process -FilePath $Target -ArgumentList $Arguments -PassThru\n } else {\n $proc = Start-Process -FilePath $Target -PassThru\n }\n Start-Sleep -Milliseconds 500\n Write-Output \"Launched: $Target (PID=$($proc.Id))\"\n }\n\n \"focus\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target' (ProcId=$ProcId)\"; exit 1 }\n if ([Win32Window]::IsIconic($win.Handle)) {\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_RESTORE) | Out-Null\n }\n [Win32Window]::ForceForeground($win.Handle)\n Write-Output \"Focused: \"\"$($win.Title)\"\" (PID=$($win.WinPID))\"\n }\n\n \"close\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $proc = Get-Process -Id $win.WinPID -ErrorAction SilentlyContinue\n if ($proc) {\n $proc.CloseMainWindow() | Out-Null\n Write-Output \"Close signal sent: \"\"$($win.Title)\"\" (PID=$($win.WinPID))\"\n } else {\n Write-Error \"Process not found for PID=$($win.WinPID)\"; exit 1\n }\n }\n\n \"minimize\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_MINIMIZE) | Out-Null\n Write-Output \"Minimized: \"\"$($win.Title)\"\"\"\n }\n\n \"maximize\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_MAXIMIZE) | Out-Null\n Write-Output \"Maximized: \"\"$($win.Title)\"\"\"\n }\n\n \"restore\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_RESTORE) | Out-Null\n Write-Output \"Restored: \"\"$($win.Title)\"\"\"\n }\n\n \"move\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $newX = if ($X -ge 0) { $X } else { $win.X }\n $newY = if ($Y -ge 0) { $Y } else { $win.Y }\n [Win32Window]::MoveWindow($win.Handle, $newX, $newY, $win.Width, $win.Height, $true) | Out-Null\n Write-Output \"Moved: \"\"$($win.Title)\"\" to ($newX, $newY)\"\n }\n\n \"resize\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $newW = if ($Width -gt 0) { $Width } else { $win.Width }\n $newH = if ($Height -gt 0) { $Height } else { $win.Height }\n [Win32Window]::MoveWindow($win.Handle, $win.X, $win.Y, $newW, $newH, $true) | Out-Null\n Write-Output \"Resized: \"\"$($win.Title)\"\" to ${newW}x${newH}\"\n }\n\n \"snap\" {\n if (-not $Position) { Write-Error \"Missing -Position\"; exit 1 }\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n if ([Win32Window]::IsZoomed($win.Handle)) {\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_RESTORE) | Out-Null\n Start-Sleep -Milliseconds 100\n }\n $scr = Get-ScreenSize\n $hw = [math]::Floor($scr.Width / 2)\n $hh = [math]::Floor($scr.Height / 2)\n switch ($Position) {\n \"left\" { $sx=$scr.X; $sy=$scr.Y; $sw=$hw; $sh=$scr.Height }\n \"right\" { $sx=$scr.X+$hw; $sy=$scr.Y; $sw=$hw; $sh=$scr.Height }\n \"top\" { $sx=$scr.X; $sy=$scr.Y; $sw=$scr.Width; $sh=$hh }\n \"bottom\" { $sx=$scr.X; $sy=$scr.Y+$hh; $sw=$scr.Width; $sh=$hh }\n \"topleft\" { $sx=$scr.X; $sy=$scr.Y; $sw=$hw; $sh=$hh }\n \"topright\" { $sx=$scr.X+$hw; $sy=$scr.Y; $sw=$hw; $sh=$hh }\n \"bottomleft\" { $sx=$scr.X; $sy=$scr.Y+$hh; $sw=$hw; $sh=$hh }\n \"bottomright\" { $sx=$scr.X+$hw; $sy=$scr.Y+$hh; $sw=$hw; $sh=$hh }\n }\n [Win32Window]::MoveWindow($win.Handle, $sx, $sy, $sw, $sh, $true) | Out-Null\n Write-Output \"Snapped: \"\"$($win.Title)\"\" to $Position (${sw}x${sh} at ${sx},${sy})\"\n }\n }\n exit 0\n} catch {\n Write-Error \"ERROR: $_\"\n exit 1\n}\n",93 "mimeType": null,94 "size": null,95 "icons": null,96 "annotations": null,97 "meta": null98 },99 {100 "name": "input-sim.ps1.txt",101 "title": null,102 "uri": "skill://scripts/input-sim.ps1.txt",103 "description": "# ============================================================\n# input-sim.ps1 \u2014 Keyboard & Mouse Input Simulation for OpenClaw\n# Actions: type-text, send-keys, mouse-click, mouse-move,\n# mouse-scroll, help\n# ============================================================\n\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"type-text\",\"send-keys\",\"mouse-click\",\"mouse-move\",\"mouse-scroll\",\"help\")]\n [string]$Action,\n\n [string]$Text = \"\",\n [string]$Keys = \"\",\n [int]$X = -1,\n [int]$Y = -1,\n [ValidateSet(\"left\",\"right\",\"middle\",\"\")]\n [string]$Button = \"left\",\n [switch]$DoubleClick,\n [int]$Clicks = 0,\n [int]$DelayMs = 50\n)\n\nAdd-Type -AssemblyName System.Windows.Forms\nAdd-Type @\"\nusing System;\nusing System.Runtime.InteropServices;\n\npublic class InputSim {\n [DllImport(\"user32.dll\")] public static extern void SetCursorPos(int X, int Y);\n [DllImport(\"user32.dll\")] public static extern void mouse_event(uint dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo);\n [DllImport(\"user32.dll\")] public static extern bool GetCursorPos(out POINT lpPoint);\n\n [StructLayout(LayoutKind.Sequential)]\n public struct POINT { public int X; public int Y; }\n\n public const uint MOUSEEVENTF_LEFTDOWN = 0x0002;\n public const uint MOUSEEVENTF_LEFTUP = 0x0004;\n public const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;\n public const uint MOUSEEVENTF_RIGHTUP = 0x0010;\n public const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020;\n public const uint MOUSEEVENTF_MIDDLEUP = 0x0040;\n public const uint MOUSEEVENTF_WHEEL = 0x0800;\n public const uint MOUSEEVENTF_ABSOLUTE = 0x8000;\n public const uint MOUSEEVENTF_MOVE = 0x0001;\n}\n\"@\n\n# --- Key Mapping for SendKeys ---\nfunction ConvertTo-SendKeysFormat {\n param([string]$KeyCombo)\n # Parse combos like \"Ctrl+Shift+P\", \"Alt+F4\", \"F5\", \"Enter\"\n $parts = $KeyCombo -split '\\+'\n $modifiers = \"\"\n $key = \"\"\n foreach ($part in $parts) {\n switch ($part.Trim().ToLower()) {\n \"ctrl\" { $modifiers += \"^\" }\n \"control\" { $modifiers += \"^\" }\n \"alt\" { $modifiers += \"%\" }\n \"shift\" { $modifiers += \"+\" }\n \"win\" { # Win key handled separately\n $modifiers += \"^{ESC}\" # Approximation\n }\n \"enter\" { $key = \"{ENTER}\" }\n \"return\" { $key = \"{ENTER}\" }\n \"tab\" { $key = \"{TAB}\" }\n \"escape\" { $key = \"{ESC}\" }\n \"esc\" { $key = \"{ESC}\" }\n \"backspace\" { $key = \"{BACKSPACE}\" }\n \"delete\" { $key = \"{DELETE}\" }\n \"del\" { $key = \"{DELETE}\" }\n \"up\" { $key = \"{UP}\" }\n \"down\" { $key = \"{DOWN}\" }\n \"left\" { $key = \"{LEFT}\" }\n \"right\" { $key = \"{RIGHT}\" }\n \"home\" { $key = \"{HOME}\" }\n \"end\" { $key = \"{END}\" }\n \"pageup\" { $key = \"{PGUP}\" }\n \"pgup\" { $key = \"{PGUP}\" }\n \"pagedown\" { $key = \"{PGDN}\" }\n \"pgdn\" { $key = \"{PGDN}\" }\n \"space\" { $key = \" \" }\n \"insert\" { $key = \"{INSERT}\" }\n \"ins\" { $key = \"{INSERT}\" }\n \"capslock\" { $key = \"{CAPSLOCK}\" }\n \"numlock\" { $key = \"{NUMLOCK}\" }\n \"scrolllock\"{ $key = \"{SCROLLLOCK}\" }\n \"prtsc\" { $key = \"{PRTSC}\" }\n \"break\" { $key = \"{BREAK}\" }\n \"f1\" { $key = \"{F1}\" }\n \"f2\" { $key = \"{F2}\" }\n \"f3\" { $key = \"{F3}\" }\n \"f4\" { $key = \"{F4}\" }\n \"f5\" { $key = \"{F5}\" }\n \"f6\" { $key = \"{F6}\" }\n \"f7\" { $key = \"{F7}\" }\n \"f8\" { $key = \"{F8}\" }\n \"f9\" { $key = \"{F9}\" }\n \"f10\" { $key = \"{F10}\" }\n \"f11\" { $key = \"{F11}\" }\n \"f12\" { $key = \"{F12}\" }\n default {\n $k = $part.Trim()\n if ($k.Length -eq 1) {\n # Single character \u2014 check if it's special in SendKeys\n if ($k -match '[\\+\\^\\%\\~\\(\\)\\{\\}\\[\\]]') {\n $key = \"{$k}\"\n } else {\n $key = $k.ToLower()\n }\n } else {\n $key = $k.ToLower()\n }\n }\n }\n }\n if ($modifiers -and $key) {\n return \"$modifiers($key)\"\n } elseif ($key) {\n return $key\n } else {\n return $KeyCombo\n }\n}\n\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output @\"\ndesktop-control / input-sim.ps1\nActions:\n type-text -Text <text> Type text into focused window [-DelayMs <ms>]\n send-keys -Keys <combo> Send keyboard shortcut (e.g. \"Ctrl+S\", \"Alt+F4\", \"Enter\", \"F5\")\n mouse-click -X <x> -Y <y> Click at coordinates [-Button left|right|middle] [-DoubleClick]\n mouse-move -X <x> -Y <y> Move mouse to coordinates\n mouse-scroll -Clicks <n> Scroll (positive=up, negative=down)\n\nKey combos: Ctrl, Alt, Shift + letter/number/F-key/special\nSpecial keys: Enter, Tab, Escape, Backspace, Delete, Up, Down, Left, Right, Home, End,\n PageUp, PageDown, Space, F1-F12, Insert, CapsLock, NumLock\n\"@\n }\n\n \"type-text\" {\n if (-not $Text) { Write-Error \"Missing -Text parameter\"; exit 1 }\n Start-Sleep -Milliseconds 100\n # Use SendKeys for each character with optional delay\n # Escape special SendKeys characters\n $escaped = $Text -replace '([\\+\\^\\%\\~\\(\\)\\{\\}\\[\\]])', '{$1}'\n [System.Windows.Forms.SendKeys]::SendWait($escaped)\n Write-Output \"Typed: \"\"$Text\"\" ($($Text.Length) characters)\"\n }\n\n \"send-keys\" {\n if (-not $Keys) { Write-Error \"Missing -Keys parameter\"; exit 1 }\n Start-Sleep -Milliseconds 100\n $sendKeysFormat = ConvertTo-SendKeysFormat $Keys\n [System.Windows.Forms.SendKeys]::SendWait($sendKeysFormat)\n Write-Output \"Sent: $Keys (SendKeys format: $sendKeysFormat)\"\n }\n\n \"mouse-click\" {\n if ($X -lt 0 -or $Y -lt 0) { Write-Error \"Missing -X and -Y coordinates\"; exit 1 }\n [InputSim]::SetCursorPos($X, $Y)\n Start-Sleep -Milliseconds 50\n switch ($Button.ToLower()) {\n \"left\" {\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [IntPtr]::Zero)\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_LEFTUP, 0, 0, 0, [IntPtr]::Zero)\n if ($DoubleClick) {\n Start-Sleep -Milliseconds 50\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [IntPtr]::Zero)\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_LEFTUP, 0, 0, 0, [IntPtr]::Zero)\n }\n }\n \"right\" {\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, [IntPtr]::Zero)\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_RIGHTUP, 0, 0, 0, [IntPtr]::Zero)\n }\n \"middle\" {\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, [IntPtr]::Zero)\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_MIDDLEUP, 0, 0, 0, [IntPtr]::Zero)\n }\n }\n $clickType = if ($DoubleClick) { \"Double-click\" } else { \"Click\" }\n Write-Output \"$clickType ($Button) at ($X, $Y)\"\n }\n\n \"mouse-move\" {\n if ($X -lt 0 -or $Y -lt 0) { Write-Error \"Missing -X and -Y coordinates\"; exit 1 }\n [InputSim]::SetCursorPos($X, $Y)\n Write-Output \"Mouse moved to ($X, $Y)\"\n }\n\n \"mouse-scroll\" {\n if ($Clicks -eq 0) { Write-Error \"Missing -Clicks parameter (positive=up, negative=down)\"; exit 1 }\n $scrollAmount = $Clicks * 120 # 120 = one wheel notch\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_WHEEL, 0, 0, $scrollAmount, [IntPtr]::Zero)\n $direction = if ($Clicks -gt 0) { \"up\" } else { \"down\" }\n Write-Output \"Scrolled $direction by $([Math]::Abs($Clicks)) clicks\"\n }\n }\n exit 0\n} catch {\n Write-Error \"ERROR: $_\"\n exit 1\n}\n",104 "mimeType": null,105 "size": null,106 "icons": null,107 "annotations": null,108 "meta": null109 },110 {111 "name": "screen-info.ps1.txt",112 "title": null,113 "uri": "skill://scripts/screen-info.ps1.txt",114 "description": "# screen-info.ps1 - Screen and System Info for OpenClaw\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"displays\",\"active-window\",\"window-info\",\"screenshot\",\"clipboard-get\",\"clipboard-set\",\"system-info\",\"help\")]\n [string]$Action,\n [string]$Target = \"\",\n [string]$OutputPath = \"\",\n [string]$Text = \"\"\n)\n\nAdd-Type -AssemblyName System.Windows.Forms\nAdd-Type -AssemblyName System.Drawing\n\nAdd-Type @\"\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\npublic class ScreenHelper {\n [DllImport(\"user32.dll\")] public static extern IntPtr GetForegroundWindow();\n [DllImport(\"user32.dll\")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);\n [DllImport(\"user32.dll\", CharSet=CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder sb, int maxCount);\n [DllImport(\"user32.dll\")] public static extern int GetWindowTextLength(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid);\n [DllImport(\"user32.dll\", CharSet=CharSet.Auto)] public static extern int GetClassName(IntPtr hWnd, StringBuilder sb, int maxCount);\n [DllImport(\"user32.dll\")] public static extern bool IsIconic(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool IsZoomed(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool IsWindowVisible(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool EnumWindows(EnumWindowsProc cb, IntPtr lParam);\n public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; }\n}\n\"@\n\nfunction Get-WindowDetails([IntPtr]$hWnd) {\n $sb = New-Object System.Text.StringBuilder(256)\n [ScreenHelper]::GetWindowText($hWnd, $sb, 256) | Out-Null\n $title = $sb.ToString()\n $sb.Clear() | Out-Null\n [ScreenHelper]::GetClassName($hWnd, $sb, 256) | Out-Null\n $class = $sb.ToString()\n $procId = [uint32]0\n [ScreenHelper]::GetWindowThreadProcessId($hWnd, [ref]$procId) | Out-Null\n $rect = New-Object ScreenHelper+RECT\n [ScreenHelper]::GetWindowRect($hWnd, [ref]$rect) | Out-Null\n $state = \"Normal\"\n if ([ScreenHelper]::IsIconic($hWnd)) { $state = \"Minimized\" }\n elseif ([ScreenHelper]::IsZoomed($hWnd)) { $state = \"Maximized\" }\n return @{\n Handle=$hWnd; Title=$title; Class=$class; PID=$procId\n X=$rect.Left; Y=$rect.Top\n Width=$rect.Right-$rect.Left; Height=$rect.Bottom-$rect.Top\n State=$state\n }\n}\n\nfunction Find-WindowByTitle([string]$pattern) {\n $script:result = $null\n $cb = [ScreenHelper+EnumWindowsProc]{\n param($h,$l)\n if ([ScreenHelper]::IsWindowVisible($h)) {\n $len = [ScreenHelper]::GetWindowTextLength($h)\n if ($len -gt 0) {\n $s = New-Object System.Text.StringBuilder($len+1)\n [ScreenHelper]::GetWindowText($h, $s, $s.Capacity) | Out-Null\n if ($s.ToString() -like \"*$pattern*\") {\n $script:result = $h\n return $false\n }\n }\n }\n return $true\n }\n [ScreenHelper]::EnumWindows($cb, [IntPtr]::Zero) | Out-Null\n return $script:result\n}\n\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output \"screen-info.ps1 - displays, active-window, window-info, screenshot, clipboard-get, clipboard-set, system-info\"\n }\n \"displays\" {\n $screens = [System.Windows.Forms.Screen]::AllScreens\n $i = 0\n foreach ($s in $screens) {\n $i++\n $p = if($s.Primary){\"(Primary)\"}else{\"\"}\n Write-Output \"Display #$i $p\"\n Write-Output \" Device: $($s.DeviceName)\"\n Write-Output \" Resolution: $($s.Bounds.Width)x$($s.Bounds.Height)\"\n Write-Output \" Position: ($($s.Bounds.X), $($s.Bounds.Y))\"\n Write-Output \" WorkArea: $($s.WorkingArea.Width)x$($s.WorkingArea.Height)\"\n Write-Output \" BitsPerPx: $($s.BitsPerPixel)\"\n Write-Output \"\"\n }\n Write-Output \"Total: $i display(s)\"\n }\n \"active-window\" {\n $hw = [ScreenHelper]::GetForegroundWindow()\n if ($hw -eq [IntPtr]::Zero) { Write-Error \"No active window\"; exit 1 }\n $d = Get-WindowDetails $hw\n Write-Output \"Active Window:\"\n Write-Output \" Title: $($d.Title)\"\n Write-Output \" Class: $($d.Class)\"\n Write-Output \" PID: $($d.PID)\"\n Write-Output \" Pos: ($($d.X), $($d.Y))\"\n Write-Output \" Size: $($d.Width)x$($d.Height)\"\n Write-Output \" State: $($d.State)\"\n }\n \"window-info\" {\n if (-not $Target) { Write-Error \"Missing -Target\"; exit 1 }\n $hw = Find-WindowByTitle $Target\n if (-not $hw -or $hw -eq [IntPtr]::Zero) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $d = Get-WindowDetails $hw\n Write-Output \"Window Info:\"\n Write-Output \" Title: $($d.Title)\"\n Write-Output \" Class: $($d.Class)\"\n Write-Output \" PID: $($d.PID)\"\n Write-Output \" Pos: ($($d.X), $($d.Y))\"\n Write-Output \" Size: $($d.Width)x$($d.Height)\"\n Write-Output \" State: $($d.State)\"\n }\n \"screenshot\" {\n $outPath = if($OutputPath){$OutputPath}else{\"$env:USERPROFILE\\screenshot_$(Get-Date -Format 'yyyyMMdd_HHmmss').png\"}\n if ($Target) {\n $hw = Find-WindowByTitle $Target\n if (-not $hw -or $hw -eq [IntPtr]::Zero) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $rect = New-Object ScreenHelper+RECT\n [ScreenHelper]::GetWindowRect($hw, [ref]$rect) | Out-Null\n $w = $rect.Right - $rect.Left; $h = $rect.Bottom - $rect.Top\n $bmp = New-Object System.Drawing.Bitmap($w, $h)\n $g = [System.Drawing.Graphics]::FromImage($bmp)\n $g.CopyFromScreen($rect.Left, $rect.Top, 0, 0, [System.Drawing.Size]::new($w,$h))\n $g.Dispose()\n } else {\n $bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds\n $bmp = New-Object System.Drawing.Bitmap($bounds.Width, $bounds.Height)\n $g = [System.Drawing.Graphics]::FromImage($bmp)\n $g.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)\n $g.Dispose()\n }\n $bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Png)\n $bmp.Dispose()\n Write-Output \"Screenshot saved: $outPath\"\n }\n \"clipboard-get\" {\n $clip = [System.Windows.Forms.Clipboard]::GetText()\n if ($clip) {\n Write-Output \"Clipboard content:\"\n Write-Output \"---\"\n Write-Output $clip\n Write-Output \"---\"\n Write-Output \"($($clip.Length) characters)\"\n } else { Write-Output \"Clipboard is empty or contains non-text data.\" }\n }\n \"clipboard-set\" {\n if (-not $Text) { Write-Error \"Missing -Text\"; exit 1 }\n [System.Windows.Forms.Clipboard]::SetText($Text)\n Write-Output \"Clipboard set ($($Text.Length) characters)\"\n }\n \"system-info\" {\n $os = Get-CimInstance Win32_OperatingSystem\n $cs = Get-CimInstance Win32_ComputerSystem\n $uptime = (Get-Date) - $os.LastBootUpTime\n Write-Output \"System Info:\"\n Write-Output \" Computer: $($cs.Name)\"\n Write-Output \" OS: $($os.Caption) $($os.Version)\"\n Write-Output \" RAM: $([math]::Round($cs.TotalPhysicalMemory/1GB,1)) GB\"\n Write-Output \" Free RAM: $([math]::Round($os.FreePhysicalMemory/1MB,1)) GB\"\n Write-Output \" Uptime: $($uptime.Days)d $($uptime.Hours)h $($uptime.Minutes)m\"\n Write-Output \" User: $env:USERNAME\"\n $screens = [System.Windows.Forms.Screen]::AllScreens\n Write-Output \" Displays: $($screens.Count)\"\n foreach ($s in $screens) {\n $p = if($s.Primary){\"*\"}else{\"\"}\n Write-Output \" $p $($s.DeviceName): $($s.Bounds.Width)x$($s.Bounds.Height)\"\n }\n }\n }\n exit 0\n} catch { Write-Error \"ERROR: $_\"; exit 1 }\n",115 "mimeType": null,116 "size": null,117 "icons": null,118 "annotations": null,119 "meta": null120 }121 ],122 "resource_templates": [],123 "tools": []124 },125 "error": null126 }127 ],128 "issues": [129 {130 "code": "W004",131 "message": "The MCP server is not in our registry.",132 "reference": [133 0,134 null135 ],136 "extra_data": null137 }138 ],139 "labels": [140 [141 {142 "is_public_sink": 0,143 "destructive": 0,144 "untrusted_content": 0,145 "private_data": 0146 },147 {148 "is_public_sink": 0,149 "destructive": 0,150 "untrusted_content": 0,151 "private_data": 0152 },153 {154 "is_public_sink": 0,155 "destructive": 0,156 "untrusted_content": 0,157 "private_data": 0158 },159 {160 "is_public_sink": 0,161 "destructive": 0,162 "untrusted_content": 0,163 "private_data": 0164 },165 {166 "is_public_sink": 0,167 "destructive": 0,168 "untrusted_content": 0,169 "private_data": 0170 },171 {172 "is_public_sink": 0,173 "destructive": 0,174 "untrusted_content": 0,175 "private_data": 0176 },177 {178 "is_public_sink": 0,179 "destructive": 0,180 "untrusted_content": 0,181 "private_data": 0182 }183 ]184 ],185 "error": null186 }187}188189Process exited with code 0190✓ Completed in 137385ms
npm-audit▸No package.json found — skipping npm audit
View logs
1No package.json found at /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/package.json2Skipping npm audit.
Files analyzed
Rules coverage147 patterns
Security Findings
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:24
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:44
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:51
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:54
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:57
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:63
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:66
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:71
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:76
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:77
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:78
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:83
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:88
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:94
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:107
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:113
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:114
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:115
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:121
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:122
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:128
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:131
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:134
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:139
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:145
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:146
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:157
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:162
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:167
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:172
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:177
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:182
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:187
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:193
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:198
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:203
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:215
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:218
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:221
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:226
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:231
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:236
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:237
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:242
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:253
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:258
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:263
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:269
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:272
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:277
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:282
Evidence: ss -Fil
Network reconnaissance activity
/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md:287
Evidence: ss -Fil
The MCP server is not in our registry.
Scan History1 scan
▸Warning03ad476Critical53 findings2/13/2026
Scanners4/5 ran
clawguard-rules▸52 findings4ms
View logs
1[2026-02-13T00:14:19.066Z] Running @yourclaw/clawguard-rules pattern matcher2Scanning: /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md3Content length: 14763 chars4Patterns matched: 525 [medium] MAL-008: Network reconnaissance activity6 [medium] MAL-008: Network reconnaissance activity7 [medium] MAL-008: Network reconnaissance activity8 [medium] MAL-008: Network reconnaissance activity9 [medium] MAL-008: Network reconnaissance activity10 [medium] MAL-008: Network reconnaissance activity11 [medium] MAL-008: Network reconnaissance activity12 [medium] MAL-008: Network reconnaissance activity13 [medium] MAL-008: Network reconnaissance activity14 [medium] MAL-008: Network reconnaissance activity15 [medium] MAL-008: Network reconnaissance activity16 [medium] MAL-008: Network reconnaissance activity17 [medium] MAL-008: Network reconnaissance activity18 [medium] MAL-008: Network reconnaissance activity19 [medium] MAL-008: Network reconnaissance activity20 [medium] MAL-008: Network reconnaissance activity21 [medium] MAL-008: Network reconnaissance activity22 [medium] MAL-008: Network reconnaissance activity23 [medium] MAL-008: Network reconnaissance activity24 [medium] MAL-008: Network reconnaissance activity25 [medium] MAL-008: Network reconnaissance activity26 [medium] MAL-008: Network reconnaissance activity27 [medium] MAL-008: Network reconnaissance activity28 [medium] MAL-008: Network reconnaissance activity29 [medium] MAL-008: Network reconnaissance activity30 [medium] MAL-008: Network reconnaissance activity31 [medium] MAL-008: Network reconnaissance activity32 [medium] MAL-008: Network reconnaissance activity33 [medium] MAL-008: Network reconnaissance activity34 [medium] MAL-008: Network reconnaissance activity35 [medium] MAL-008: Network reconnaissance activity36 [medium] MAL-008: Network reconnaissance activity37 [medium] MAL-008: Network reconnaissance activity38 [medium] MAL-008: Network reconnaissance activity39 [medium] MAL-008: Network reconnaissance activity40 [medium] MAL-008: Network reconnaissance activity41 [medium] MAL-008: Network reconnaissance activity42 [medium] MAL-008: Network reconnaissance activity43 [medium] MAL-008: Network reconnaissance activity44 [medium] MAL-008: Network reconnaissance activity45 [medium] MAL-008: Network reconnaissance activity46 [medium] MAL-008: Network reconnaissance activity47 [medium] MAL-008: Network reconnaissance activity48 [medium] MAL-008: Network reconnaissance activity49 [medium] MAL-008: Network reconnaissance activity50 [medium] MAL-008: Network reconnaissance activity51 [medium] MAL-008: Network reconnaissance activity52 [medium] MAL-008: Network reconnaissance activity53 [medium] MAL-008: Network reconnaissance activity54 [medium] MAL-008: Network reconnaissance activity55 [medium] MAL-008: Network reconnaissance activity56 [medium] MAL-008: Network reconnaissance activity57✓ Completed in 4ms
gitleaks▸0 findings126425ms
View logs
1[2026-02-13T00:16:25.491Z] $ gitleaks detect --source /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win --report-format json --report-path /dev/stdout --no-git23⚠ stderr output:4○5 │╲6 │ ○7 ○ ░8 ░ gitleaks910[90m12:16AM[0m [31mFTL[0m [1mReport path is not writable: /dev/stdout[0m [36merror=[0m[31m[1m"open /dev/stdout: no such device or address"[0m[0m1112Process exited with code 113✓ Completed in 126425ms
semgrep▸0 findings183123ms
View logs
1[2026-02-13T00:17:22.192Z] $ semgrep scan --json --quiet --config auto /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win2{"version":"1.151.0","results":[],"errors":[],"paths":{"scanned":["/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/SKILL.md","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/_meta.json","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/app-control.ps1.txt","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/input-sim.ps1.txt","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/process-manager.ps1.txt","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/screen-info.ps1.txt","/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/scripts/vscode-control.ps1.txt"]},"time":{"rules":[],"rules_parse_time":14.236198902130127,"profiling_times":{"config_time":20.608436346054077,"core_time":19.011754751205444,"ignores_time":0.020355224609375,"total_time":39.69200921058655},"parsing_time":{"total_time":0.0,"per_file_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_files":[]},"scanning_time":{"total_time":0.2938828468322754,"per_file_time":{"mean":0.01959218978881836,"std_dev":0.0009568232132763417},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_files":[]},"matching_time":{"total_time":0.0,"per_file_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_files":[]},"tainting_time":{"total_time":0.0,"per_def_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_defs":[]},"fixpoint_timeouts":[],"prefiltering":{"project_level_time":0.0,"file_level_time":0.0,"rules_with_project_prefilters_ratio":0.0,"rules_with_file_prefilters_ratio":0.9911764705882353,"rules_selected_ratio":0.008823529411764706,"rules_matched_ratio":0.008823529411764706},"targets":[],"total_bytes":0,"max_memory_bytes":1153514048},"engine_requested":"OSS","skipped_rules":[],"profiling_results":[]}34Process exited with code 05✓ Completed in 183123ms
mcp-scan▸1 finding137385ms
View logs
1[2026-02-13T00:16:36.456Z] $ mcp-scan --skills /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win --json2{3 "/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent": {4 "client": "not-available",5 "path": "/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent",6 "servers": [7 {8 "name": "desktop-control-win",9 "server": {10 "path": "/tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win",11 "type": "skill"12 },13 "signature": {14 "metadata": {15 "meta": null,16 "protocolVersion": "built-in",17 "capabilities": {18 "experimental": null,19 "logging": null,20 "prompts": null,21 "resources": null,22 "tools": {23 "listChanged": false24 },25 "completions": null,26 "tasks": null27 },28 "serverInfo": {29 "name": "desktop-control",30 "title": null,31 "version": "skills",32 "websiteUrl": null,33 "icons": null34 },35 "instructions": "Control desktop applications on Windows \u2014 launch, close, focus, resize, move windows, simulate keyboard/mouse input, manage processes, control VSCode, read clipboard, and capture screen info. Use when the user wants to interact with any running program, switch windows, type text, press shortcuts, open files in VSCode, manage running processes, or get system display information.",36 "prompts": {37 "listChanged": false38 },39 "resources": {40 "subscribe": null,41 "listChanged": false42 }43 },44 "prompts": [45 {46 "name": "SKILL.md",47 "title": null,48 "description": "\n\n# Desktop Control \u2014 Full Windows Application Control\n\n## Publish-only note (ClawHub)\nThis Publish package includes scripts as `.ps1.txt` because Publish only accepts text files.\nAfter download, rename each `*.ps1.txt` to `*.ps1` and place them in a `scripts/` folder to use the skill.\n\nControl any desktop application on this Windows machine. Launch programs, manage windows, simulate input, control VSCode, and monitor processes \u2014 all via PowerShell scripts.\n\n## CRITICAL: Script Location\n\nAll scripts are located relative to this skill folder:\n\n```\nSKILL_DIR = ~/.openclaw/workspace/skills/desktop-control/scripts\n```\n\nWhen running scripts, always use the full path:\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/<script>.ps1\" -Action <action> [params]\n```\n\n## IMPORTANT: Safety Rules\n\n1. **Before closing windows** \u2014 Ask user for confirmation if the window might have unsaved work\n2. **Before killing processes** \u2014 Always confirm with user unless they explicitly asked to kill it\n3. **Before sending input** \u2014 Make sure the correct window is focused first\n4. **Clipboard** \u2014 Warn user if you are overwriting clipboard content\n\n---\n\n## Action Reference\n\n### 1. Window Management (`app-control.ps1`)\n\nManage application windows \u2014 launch, close, focus, resize, move, snap.\n\n#### List all visible windows\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action list-windows\n```\nReturns: PID, window title, position (X,Y), size (W\u00d7H), state (Normal/Minimized/Maximized)\n\n#### Launch an application\n```powershell\n# By name (searches PATH and common locations)\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action launch -Target \"notepad\"\n\n# By full path\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action launch -Target \"C:\\Program Files\\MyApp\\app.exe\"\n\n# With arguments\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action launch -Target \"code\" -Arguments \"C:\\Users\\ibach\\project\"\n```\n\n#### Focus (bring to foreground)\n```powershell\n# By window title (partial match)\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action focus -Target \"Visual Studio Code\"\n\n# By PID\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action focus -ProcId 12345\n```\n\n#### Close a window gracefully\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action close -Target \"Notepad\"\n```\n\n#### Minimize / Maximize / Restore\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action minimize -Target \"Visual Studio Code\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action maximize -Target \"Visual Studio Code\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action restore -Target \"Visual Studio Code\"\n```\n\n#### Move a window\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action move -Target \"Notepad\" -X 100 -Y 200\n```\n\n#### Resize a window\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action resize -Target \"Notepad\" -Width 800 -Height 600\n```\n\n#### Snap a window (half-screen)\n```powershell\n# Options: left, right, top, bottom, topleft, topright, bottomleft, bottomright\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/app-control.ps1\" -Action snap -Target \"Notepad\" -Position left\n```\n\n---\n\n### 2. Input Simulation (`input-sim.ps1`)\n\nSimulate keyboard and mouse input into any application.\n\n**IMPORTANT:** Always focus the target window FIRST using `app-control.ps1 -Action focus` before sending input.\n\n#### Type text\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action type-text -Text \"Hello, World!\"\n```\n\n#### Send keyboard shortcut\n```powershell\n# Common shortcuts: Ctrl+S, Ctrl+C, Ctrl+V, Ctrl+Z, Alt+F4, Ctrl+Shift+P, Win+D\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"Ctrl+S\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"Ctrl+Shift+P\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"Alt+Tab\"\n```\n\n#### Send special keys\n```powershell\n# Keys: Enter, Tab, Escape, Backspace, Delete, Up, Down, Left, Right, Home, End, PageUp, PageDown, F1-F12\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"Enter\"\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action send-keys -Keys \"F5\"\n```\n\n#### Mouse click at coordinates\n```powershell\n# Left click\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-click -X 500 -Y 300\n\n# Right click\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-click -X 500 -Y 300 -Button right\n\n# Double click\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-click -X 500 -Y 300 -DoubleClick\n```\n\n#### Move mouse\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-move -X 500 -Y 300\n```\n\n#### Scroll\n```powershell\n# Scroll up (positive) or down (negative)\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-scroll -Clicks 3\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/input-sim.ps1\" -Action mouse-scroll -Clicks -3\n```\n\n---\n\n### 3. VSCode Control (`vscode-control.ps1`)\n\nControl Visual Studio Code through the `code` CLI and extensions.\n\n#### Open a file\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action open-file -Path \"C:\\Users\\ibach\\project\\main.py\"\n```\n\n#### Open a file at a specific line\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action goto -Path \"C:\\Users\\ibach\\project\\main.py\" -Line 42\n```\n\n#### Open a folder/workspace\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action open-folder -Path \"C:\\Users\\ibach\\project\"\n```\n\n#### Open diff view\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action open-diff -Path \"file1.py\" -Path2 \"file2.py\"\n```\n\n#### List installed extensions\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action list-extensions\n```\n\n#### Install an extension\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action install-extension -ExtensionId \"ms-python.python\"\n```\n\n#### Uninstall an extension\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action uninstall-extension -ExtensionId \"ms-python.python\"\n```\n\n#### Open a new terminal in VSCode\n```powershell\n# This focuses VSCode and sends Ctrl+` to toggle terminal\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action new-terminal\n```\n\n#### Open VSCode command palette\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action command-palette\n```\n\n#### Run a VSCode command by name\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/vscode-control.ps1\" -Action run-command -Command \"workbench.action.toggleSidebarVisibility\"\n```\n\n---\n\n### 4. Process Management (`process-manager.ps1`)\n\nMonitor and manage running processes.\n\n#### List running processes\n```powershell\n# All processes\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action list\n\n# Filter by name\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action list -Name \"code\"\n\n# Top N by memory\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action list -SortBy memory -Top 10\n```\n\n#### Get detailed process info\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action info -ProcId 12345\n```\n\n#### Start a new process\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action start -Path \"notepad.exe\" -Arguments \"C:\\file.txt\"\n```\n\n#### Kill a process (CONFIRM WITH USER FIRST)\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action kill -ProcId 12345\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action kill -Name \"notepad\"\n```\n\n#### Monitor process resource usage\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/process-manager.ps1\" -Action monitor -ProcId 12345 -Duration 10\n```\n\n---\n\n### 5. Screen & System Info (`screen-info.ps1`)\n\nGet display information, window details, clipboard, and screenshots.\n\n#### List displays/monitors\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action displays\n```\n\n#### Get active (focused) window info\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action active-window\n```\n\n#### Get detailed window info\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action window-info -Target \"Visual Studio Code\"\n```\n\n#### Take a screenshot\n```powershell\n# Full screen\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action screenshot -OutputPath \"$HOME/screenshot.png\"\n\n# Specific window\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action screenshot -Target \"Notepad\" -OutputPath \"$HOME/notepad-screenshot.png\"\n```\n\n#### Read clipboard\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action clipboard-get\n```\n\n#### Set clipboard text\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action clipboard-set -Text \"Text to copy\"\n```\n\n#### Get system info (uptime, OS, resolution)\n```powershell\npowershell -ExecutionPolicy Bypass -File \"$HOME/.openclaw/workspace/skills/desktop-control/scripts/screen-info.ps1\" -Action system-info\n```\n\n---\n\n## Common Workflows\n\n### Open a file in VSCode and navigate to a specific line\n```\n1. vscode-control.ps1 -Action goto -Path \"C:\\path\\to\\file.py\" -Line 42\n```\n\n### Type something into a specific application\n```\n1. app-control.ps1 -Action focus -Target \"Notepad\"\n2. input-sim.ps1 -Action type-text -Text \"Hello World\"\n```\n\n### Save the current document in any app\n```\n1. app-control.ps1 -Action focus -Target \"<app name>\"\n2. input-sim.ps1 -Action send-keys -Keys \"Ctrl+S\"\n```\n\n### Arrange two windows side-by-side\n```\n1. app-control.ps1 -Action snap -Target \"Visual Studio Code\" -Position left\n2. app-control.ps1 -Action snap -Target \"Chrome\" -Position right\n```\n\n### Kill a frozen application\n```\n1. process-manager.ps1 -Action list -Name \"frozen-app\"\n (note the PID)\n2. ASK USER FOR CONFIRMATION\n3. process-manager.ps1 -Action kill -ProcId <pid>\n```\n\n### Take a screenshot of a specific window\n```\n1. screen-info.ps1 -Action screenshot -Target \"Chrome\" -OutputPath \"$HOME/chrome.png\"\n```\n\n---\n\n## Error Handling\n\n- If a script returns exit code 0 \u2192 success\n- If a script returns exit code 1 \u2192 error (check stderr output for details)\n- If a window is not found \u2192 try `list-windows` first to get the exact title\n- If `code` CLI is not found \u2192 VSCode may not be in PATH; try launching it first\n\n## Troubleshooting\n\n- **\"Window not found\"** \u2192 Use `list-windows` to see exact window titles, then match more precisely\n- **\"Access denied\"** \u2192 Some system processes need admin rights; inform the user\n- **Input not working** \u2192 Make sure the target window is focused AND in the foreground\n- **VSCode CLI not found** \u2192 Try `code --version` first; if missing, launch VSCode from Start Menu\n",49 "arguments": [],50 "icons": null,51 "meta": null52 }53 ],54 "resources": [55 {56 "name": "_meta.json",57 "title": null,58 "uri": "skill://_meta.json",59 "description": "{\n \"owner\": \"lexylent\",\n \"slug\": \"desktop-control-win\",\n \"displayName\": \"Desktop Control (Windows)\",\n \"latest\": {\n \"version\": \"1.0.1\",\n \"publishedAt\": 1770841588053,\n \"commit\": \"https://github.com/openclaw/skills/commit/f8e7a684f74e4d5eb275fe73390976e23684a949\"\n },\n \"history\": []\n}\n",60 "mimeType": null,61 "size": null,62 "icons": null,63 "annotations": null,64 "meta": null65 },66 {67 "name": "vscode-control.ps1.txt",68 "title": null,69 "uri": "skill://scripts/vscode-control.ps1.txt",70 "description": "# ============================================================\n# vscode-control.ps1 \u2014 VSCode Control for OpenClaw\n# Actions: open-file, open-folder, open-diff, goto,\n# list-extensions, install-extension, uninstall-extension,\n# new-terminal, command-palette, run-command, status, help\n# ============================================================\n\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"open-file\",\"open-folder\",\"open-diff\",\"goto\",\"list-extensions\",\"install-extension\",\"uninstall-extension\",\"new-terminal\",\"command-palette\",\"run-command\",\"status\",\"help\")]\n [string]$Action,\n\n [string]$Path = \"\",\n [string]$Path2 = \"\",\n [int]$Line = 0,\n [int]$Column = 0,\n [string]$ExtensionId = \"\",\n [string]$Command = \"\",\n [switch]$NewWindow,\n [switch]$Reuse\n)\n\n# --- Locate code CLI ---\nfunction Find-VSCodeCLI {\n # Try 'code' in PATH first\n $codePath = Get-Command \"code\" -ErrorAction SilentlyContinue\n if ($codePath) { return $codePath.Source }\n\n # Common install locations\n $candidates = @(\n \"$env:LOCALAPPDATA\\Programs\\Microsoft VS Code\\bin\\code.cmd\",\n \"$env:ProgramFiles\\Microsoft VS Code\\bin\\code.cmd\",\n \"${env:ProgramFiles(x86)}\\Microsoft VS Code\\bin\\code.cmd\",\n \"$env:LOCALAPPDATA\\Programs\\Microsoft VS Code\\Code.exe\",\n \"$env:ProgramFiles\\Microsoft VS Code\\Code.exe\"\n )\n foreach ($c in $candidates) {\n if (Test-Path $c) { return $c }\n }\n\n # VSCode Insiders\n $insiders = Get-Command \"code-insiders\" -ErrorAction SilentlyContinue\n if ($insiders) { return $insiders.Source }\n\n return $null\n}\n\n$codeCLI = Find-VSCodeCLI\nif (-not $codeCLI -and $Action -ne \"help\") {\n Write-Error \"VSCode CLI ('code') not found. Make sure VSCode is installed and 'code' is in PATH.\"\n Write-Error \"Tip: Open VSCode, press Ctrl+Shift+P, type 'Shell Command: Install code command in PATH'\"\n exit 1\n}\n\n# --- Helper to focus VSCode window ---\nfunction Focus-VSCode {\n Add-Type @\"\n using System;\n using System.Runtime.InteropServices;\n using System.Text;\n public class VSCFocus {\n [DllImport(\"user32.dll\")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);\n [DllImport(\"user32.dll\")] public static extern bool IsWindowVisible(IntPtr hWnd);\n [DllImport(\"user32.dll\", CharSet=CharSet.Auto)]\n public static extern int GetWindowText(IntPtr hWnd, StringBuilder sb, int maxCount);\n [DllImport(\"user32.dll\")] public static extern int GetWindowTextLength(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool SetForegroundWindow(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);\n [DllImport(\"user32.dll\")] public static extern bool IsIconic(IntPtr hWnd);\n public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n }\n\"@\n $found = $false\n $callback = [VSCFocus+EnumWindowsProc]{\n param($hWnd, $lParam)\n if ([VSCFocus]::IsWindowVisible($hWnd)) {\n $len = [VSCFocus]::GetWindowTextLength($hWnd)\n if ($len -gt 0) {\n $sb = New-Object System.Text.StringBuilder($len + 1)\n [VSCFocus]::GetWindowText($hWnd, $sb, $sb.Capacity) | Out-Null\n if ($sb.ToString() -like \"*Visual Studio Code*\") {\n if ([VSCFocus]::IsIconic($hWnd)) {\n [VSCFocus]::ShowWindow($hWnd, 9) | Out-Null\n }\n [VSCFocus]::SetForegroundWindow($hWnd) | Out-Null\n $script:found = $true\n return $false # Stop enumeration\n }\n }\n }\n return $true\n }\n [VSCFocus]::EnumWindows($callback, [IntPtr]::Zero) | Out-Null\n}\n\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output @\"\ndesktop-control / vscode-control.ps1\nActions:\n open-file -Path <file> Open a file in VSCode\n goto -Path <file> -Line <n> Open file at line[:column]\n open-folder -Path <folder> Open folder/workspace [-NewWindow]\n open-diff -Path <file1> -Path2 <file2> Diff two files\n list-extensions List installed extensions\n install-extension -ExtensionId <id> Install extension (e.g. \"ms-python.python\")\n uninstall-extension -ExtensionId <id> Uninstall extension\n new-terminal Open/toggle integrated terminal\n command-palette Open command palette (Ctrl+Shift+P)\n run-command -Command <cmd> Run a VSCode command by ID\n status Show VSCode version and status\n\"@\n }\n\n \"open-file\" {\n if (-not $Path) { Write-Error \"Missing -Path parameter\"; exit 1 }\n $resolvedPath = Resolve-Path $Path -ErrorAction SilentlyContinue\n if (-not $resolvedPath) { $resolvedPath = $Path }\n $args_ = @(\"--goto\", \"$resolvedPath\")\n if ($Reuse) { $args_ += \"--reuse-window\" }\n & $codeCLI @args_\n Write-Output \"Opened in VSCode: $resolvedPath\"\n }\n\n \"goto\" {\n if (-not $Path) { Write-Error \"Missing -Path parameter\"; exit 1 }\n if ($Line -le 0) { Write-Error \"Missing -Line parameter\"; exit 1 }\n $resolvedPath = Resolve-Path $Path -ErrorAction SilentlyContinue\n if (-not $resolvedPath) { $resolvedPath = $Path }\n $location = \"${resolvedPath}:${Line}\"\n if ($Column -gt 0) { $location += \":${Column}\" }\n & $codeCLI --goto $location\n Write-Output \"Opened in VSCode: $location\"\n }\n\n \"open-folder\" {\n if (-not $Path) { Write-Error \"Missing -Path parameter\"; exit 1 }\n $resolvedPath = Resolve-Path $Path -ErrorAction SilentlyContinue\n if (-not $resolvedPath) { $resolvedPath = $Path }\n $args_ = @(\"$resolvedPath\")\n if ($NewWindow) { $args_ += \"--new-window\" }\n & $codeCLI @args_\n Write-Output \"Opened folder in VSCode: $resolvedPath\"\n }\n\n \"open-diff\" {\n if (-not $Path -or -not $Path2) { Write-Error \"Missing -Path and -Path2 parameters\"; exit 1 }\n $r1 = Resolve-Path $Path -ErrorAction SilentlyContinue\n $r2 = Resolve-Path $Path2 -ErrorAction SilentlyContinue\n if (-not $r1) { $r1 = $Path }\n if (-not $r2) { $r2 = $Path2 }\n & $codeCLI --diff \"$r1\" \"$r2\"\n Write-Output \"Opened diff: $r1 <-> $r2\"\n }\n\n \"list-extensions\" {\n Write-Output \"Installed VSCode extensions:\"\n Write-Output \"---\"\n & $codeCLI --list-extensions --show-versions\n }\n\n \"install-extension\" {\n if (-not $ExtensionId) { Write-Error \"Missing -ExtensionId parameter\"; exit 1 }\n Write-Output \"Installing extension: $ExtensionId ...\"\n & $codeCLI --install-extension $ExtensionId --force\n if ($LASTEXITCODE -eq 0) {\n Write-Output \"Successfully installed: $ExtensionId\"\n } else {\n Write-Error \"Failed to install: $ExtensionId\"; exit 1\n }\n }\n\n \"uninstall-extension\" {\n if (-not $ExtensionId) { Write-Error \"Missing -ExtensionId parameter\"; exit 1 }\n Write-Output \"Uninstalling extension: $ExtensionId ...\"\n & $codeCLI --uninstall-extension $ExtensionId\n if ($LASTEXITCODE -eq 0) {\n Write-Output \"Successfully uninstalled: $ExtensionId\"\n } else {\n Write-Error \"Failed to uninstall: $ExtensionId\"; exit 1\n }\n }\n\n \"new-terminal\" {\n Focus-VSCode\n Start-Sleep -Milliseconds 300\n Add-Type -AssemblyName System.Windows.Forms\n # Ctrl+` toggles terminal\n [System.Windows.Forms.SendKeys]::SendWait(\"^``\")\n Write-Output \"Toggled integrated terminal in VSCode\"\n }\n\n \"command-palette\" {\n Focus-VSCode\n Start-Sleep -Milliseconds 300\n Add-Type -AssemblyName System.Windows.Forms\n # Ctrl+Shift+P opens command palette\n [System.Windows.Forms.SendKeys]::SendWait(\"^+p\")\n Write-Output \"Opened command palette in VSCode\"\n }\n\n \"run-command\" {\n if (-not $Command) { Write-Error \"Missing -Command parameter (e.g. 'workbench.action.toggleSidebarVisibility')\"; exit 1 }\n # Use the code CLI to execute a command via extension\n # Fallback: focus VSCode, open command palette, type the command\n Focus-VSCode\n Start-Sleep -Milliseconds 300\n Add-Type -AssemblyName System.Windows.Forms\n [System.Windows.Forms.SendKeys]::SendWait(\"^+p\")\n Start-Sleep -Milliseconds 500\n $escaped = $Command -replace '([\\+\\^\\%\\~\\(\\)\\{\\}\\[\\]])', '{$1}'\n [System.Windows.Forms.SendKeys]::SendWait($escaped)\n Start-Sleep -Milliseconds 200\n [System.Windows.Forms.SendKeys]::SendWait(\"{ENTER}\")\n Write-Output \"Executed VSCode command: $Command\"\n }\n\n \"status\" {\n Write-Output \"VSCode Status:\"\n Write-Output \"---\"\n & $codeCLI --version\n Write-Output \"---\"\n $vscProcs = Get-Process -Name \"Code\" -ErrorAction SilentlyContinue\n if ($vscProcs) {\n $totalMem = ($vscProcs | Measure-Object -Property WorkingSet64 -Sum).Sum / 1MB\n Write-Output \"Running: Yes ($($vscProcs.Count) processes, $([math]::Round($totalMem))MB total memory)\"\n } else {\n Write-Output \"Running: No\"\n }\n }\n }\n exit 0\n} catch {\n Write-Error \"ERROR: $_\"\n exit 1\n}\n",71 "mimeType": null,72 "size": null,73 "icons": null,74 "annotations": null,75 "meta": null76 },77 {78 "name": "process-manager.ps1.txt",79 "title": null,80 "uri": "skill://scripts/process-manager.ps1.txt",81 "description": "# process-manager.ps1 - Process Management for OpenClaw\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"list\",\"info\",\"start\",\"kill\",\"monitor\",\"wait\",\"help\")]\n [string]$Action,\n [string]$Name = \"\",\n [int]$ProcId = 0,\n [string]$Path = \"\",\n [string]$Arguments = \"\",\n [ValidateSet(\"memory\",\"cpu\",\"name\",\"pid\",\"\")][string]$SortBy = \"\",\n [int]$Top = 0,\n [int]$Duration = 5,\n [switch]$Force\n)\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output \"process-manager.ps1 - list, info, start, kill, monitor, wait\"\n Write-Output \" list [-Name [filter]] [-SortBy memory|cpu|name|pid] [-Top [n]]\"\n Write-Output \" info -ProcId [pid]\"\n Write-Output \" start -Path [exe] [-Arguments [args]]\"\n Write-Output \" kill -ProcId [pid] | -Name [name] [-Force]\"\n Write-Output \" monitor -ProcId [pid] [-Duration [seconds]]\"\n Write-Output \" wait -ProcId [pid]\"\n }\n \"list\" {\n $procs = Get-Process -ErrorAction SilentlyContinue\n if ($Name) { $procs = $procs | Where-Object { $_.ProcessName -like \"*$Name*\" } }\n $data = $procs | Where-Object { $_.Id -ne 0 } | ForEach-Object {\n [PSCustomObject]@{\n PID=$_.Id; Name=$_.ProcessName\n MemMB=[math]::Round($_.WorkingSet64/1MB,1)\n CPU=if($_.CPU){[math]::Round($_.CPU,1)}else{0.0}\n Title=if($_.MainWindowTitle){$_.MainWindowTitle}else{\"-\"}\n }\n }\n switch ($SortBy) {\n \"memory\" { $data = $data | Sort-Object MemMB -Descending }\n \"cpu\" { $data = $data | Sort-Object CPU -Descending }\n \"name\" { $data = $data | Sort-Object Name }\n \"pid\" { $data = $data | Sort-Object PID }\n default { $data = $data | Sort-Object MemMB -Descending }\n }\n if ($Top -gt 0) { $data = $data | Select-Object -First $Top }\n $data | ForEach-Object {\n $t = if($_.Title -ne \"-\"){ ' Title=\"' + $_.Title + '\"' } else { \"\" }\n Write-Output (\"PID={0,-6} Mem={1,8}MB CPU={2,8}s Name={3}{4}\" -f $_.PID,$_.MemMB,$_.CPU,$_.Name,$t)\n }\n Write-Output \"`nTotal: $($data.Count) processes$(if($Name){\" matching '$Name'\"})\"\n }\n \"info\" {\n if ($ProcId -le 0) { Write-Error \"Missing -ProcId\"; exit 1 }\n $proc = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $proc) { Write-Error \"Not found: PID=$ProcId\"; exit 1 }\n $st = try{$proc.StartTime.ToString(\"yyyy-MM-dd HH:mm:ss\")}catch{\"N/A\"}\n $ep = try{$proc.Path}catch{\"N/A\"}\n Write-Output \"PID=$ProcId Name=$($proc.ProcessName)\"\n Write-Output \"Path: $ep\"\n Write-Output \"Started: $st\"\n Write-Output \"Memory: $([math]::Round($proc.WorkingSet64/1MB,1))MB (peak $([math]::Round($proc.PeakWorkingSet64/1MB,1))MB)\"\n Write-Output \"CPU: $([math]::Round($proc.CPU,2))s Threads: $($proc.Threads.Count) Handles: $($proc.HandleCount)\"\n Write-Output \"Window: $(if($proc.MainWindowTitle){$proc.MainWindowTitle}else{'(none)'})\"\n Write-Output \"Responding: $($proc.Responding) Priority: $($proc.PriorityClass)\"\n }\n \"start\" {\n if (-not $Path) { Write-Error \"Missing -Path\"; exit 1 }\n $p = if($Arguments){Start-Process $Path -ArgumentList $Arguments -PassThru}else{Start-Process $Path -PassThru}\n Start-Sleep -Milliseconds 500\n Write-Output \"Started: $Path (PID=$($p.Id))\"\n }\n \"kill\" {\n if ($ProcId -gt 0) {\n $p = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $p) { Write-Error \"Not found: PID=$ProcId\"; exit 1 }\n if ($Force) { Stop-Process -Id $ProcId -Force } else { Stop-Process -Id $ProcId }\n Write-Output \"Killed: $($p.ProcessName) (PID=$ProcId)\"\n } elseif ($Name) {\n $ps = Get-Process -Name \"*$Name*\" -EA SilentlyContinue\n if (-not $ps) { Write-Error \"No match: '$Name'\"; exit 1 }\n $ps | ForEach-Object { if($Force){Stop-Process -Id $_.Id -Force}else{Stop-Process -Id $_.Id} }\n Write-Output \"Killed: $($ps.Count) process(es) matching '$Name'\"\n } else { Write-Error \"Missing -ProcId or -Name\"; exit 1 }\n }\n \"monitor\" {\n if ($ProcId -le 0) { Write-Error \"Missing -ProcId\"; exit 1 }\n $proc = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $proc) { Write-Error \"Not found: PID=$ProcId\"; exit 1 }\n Write-Output \"Monitoring PID=$ProcId ($($proc.ProcessName)) for ${Duration}s...\"\n $prev = $proc.CPU\n for ($i=0; $i -lt $Duration; $i++) {\n Start-Sleep 1\n $proc = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $proc) { Write-Output \"Process exited.\"; break }\n $d = [math]::Round($proc.CPU - $prev, 2); $prev = $proc.CPU\n Write-Output \"[$((Get-Date).ToString('HH:mm:ss'))] Mem=$([math]::Round($proc.WorkingSet64/1MB,1))MB CPU-delta=${d}s Threads=$($proc.Threads.Count)\"\n }\n }\n \"wait\" {\n if ($ProcId -le 0) { Write-Error \"Missing -ProcId\"; exit 1 }\n $proc = Get-Process -Id $ProcId -EA SilentlyContinue\n if (-not $proc) { Write-Output \"PID=$ProcId already exited.\"; exit 0 }\n Write-Output \"Waiting for PID=$ProcId ($($proc.ProcessName))...\"\n $proc.WaitForExit()\n Write-Output \"PID=$ProcId exited (code: $($proc.ExitCode))\"\n }\n }\n exit 0\n} catch { Write-Error \"ERROR: $_\"; exit 1 }\n",82 "mimeType": null,83 "size": null,84 "icons": null,85 "annotations": null,86 "meta": null87 },88 {89 "name": "app-control.ps1.txt",90 "title": null,91 "uri": "skill://scripts/app-control.ps1.txt",92 "description": "# ============================================================\n# app-control.ps1 \u2014 Window Management for OpenClaw\n# Actions: list-windows, launch, focus, close, minimize,\n# maximize, restore, move, resize, snap, help\n# ============================================================\n\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"list-windows\",\"launch\",\"focus\",\"close\",\"minimize\",\"maximize\",\"restore\",\"move\",\"resize\",\"snap\",\"help\")]\n [string]$Action,\n\n [string]$Target = \"\",\n [int]$ProcId = 0,\n [string]$Arguments = \"\",\n [int]$X = -1,\n [int]$Y = -1,\n [int]$Width = -1,\n [int]$Height = -1,\n [ValidateSet(\"left\",\"right\",\"top\",\"bottom\",\"topleft\",\"topright\",\"bottomleft\",\"bottomright\",\"\")]\n [string]$Position = \"\"\n)\n\n# --- Win32 API ---\nAdd-Type @\"\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Collections.Generic;\n\npublic class Win32Window {\n [DllImport(\"user32.dll\")] public static extern bool SetForegroundWindow(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);\n [DllImport(\"user32.dll\")] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);\n [DllImport(\"user32.dll\")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);\n [DllImport(\"user32.dll\")] public static extern IntPtr GetForegroundWindow();\n [DllImport(\"user32.dll\")] public static extern bool IsWindowVisible(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool IsIconic(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool IsZoomed(IntPtr hWnd);\n [DllImport(\"user32.dll\", SetLastError=true, CharSet=CharSet.Auto)]\n public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);\n [DllImport(\"user32.dll\")] public static extern int GetWindowTextLength(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);\n [DllImport(\"user32.dll\")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);\n [DllImport(\"user32.dll\")] public static extern bool BringWindowToTop(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern IntPtr SetFocus(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);\n [DllImport(\"kernel32.dll\")] public static extern uint GetCurrentThreadId();\n [DllImport(\"user32.dll\")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);\n\n public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n\n [StructLayout(LayoutKind.Sequential)]\n public struct RECT { public int Left, Top, Right, Bottom; }\n\n public const int SW_HIDE = 0;\n public const int SW_NORMAL = 1;\n public const int SW_MINIMIZE = 6;\n public const int SW_MAXIMIZE = 3;\n public const int SW_RESTORE = 9;\n public const int SW_SHOW = 5;\n\n public static void ForceForeground(IntPtr hWnd) {\n IntPtr fg = GetForegroundWindow();\n uint fgThread = GetWindowThreadProcessId(fg, IntPtr.Zero);\n uint curThread = GetCurrentThreadId();\n if (fgThread != curThread) {\n AttachThreadInput(curThread, fgThread, true);\n BringWindowToTop(hWnd);\n ShowWindow(hWnd, SW_SHOW);\n AttachThreadInput(curThread, fgThread, false);\n }\n SetForegroundWindow(hWnd);\n }\n}\n\"@\n\n# --- Helpers ---\nfunction Get-AllWindows {\n $windows = [System.Collections.ArrayList]::new()\n $callback = [Win32Window+EnumWindowsProc]{\n param($hWnd, $lParam)\n if ([Win32Window]::IsWindowVisible($hWnd)) {\n $len = [Win32Window]::GetWindowTextLength($hWnd)\n if ($len -gt 0) {\n $sb = New-Object System.Text.StringBuilder($len + 1)\n [Win32Window]::GetWindowText($hWnd, $sb, $sb.Capacity) | Out-Null\n $title = $sb.ToString()\n $wpid = [uint32]0\n [Win32Window]::GetWindowThreadProcessId($hWnd, [ref]$wpid) | Out-Null\n $rect = New-Object Win32Window+RECT\n [Win32Window]::GetWindowRect($hWnd, [ref]$rect) | Out-Null\n $state = \"Normal\"\n if ([Win32Window]::IsIconic($hWnd)) { $state = \"Minimized\" }\n elseif ([Win32Window]::IsZoomed($hWnd)) { $state = \"Maximized\" }\n $null = $windows.Add([PSCustomObject]@{\n Handle = $hWnd\n WinPID = $wpid\n Title = $title\n X = $rect.Left\n Y = $rect.Top\n Width = $rect.Right - $rect.Left\n Height = $rect.Bottom - $rect.Top\n State = $state\n })\n }\n }\n return $true\n }\n [Win32Window]::EnumWindows($callback, [IntPtr]::Zero) | Out-Null\n return $windows\n}\n\nfunction Find-Window {\n param([string]$TitlePattern, [int]$ByProcId = 0)\n $all = Get-AllWindows\n if ($ByProcId -gt 0) {\n return $all | Where-Object { $_.WinPID -eq $ByProcId } | Select-Object -First 1\n }\n if ($TitlePattern) {\n $match = $all | Where-Object { $_.Title -eq $TitlePattern } | Select-Object -First 1\n if (-not $match) {\n $match = $all | Where-Object { $_.Title -like \"*$TitlePattern*\" } | Select-Object -First 1\n }\n return $match\n }\n return $null\n}\n\nfunction Get-ScreenSize {\n Add-Type -AssemblyName System.Windows.Forms\n $screen = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea\n return @{ Width = $screen.Width; Height = $screen.Height; X = $screen.X; Y = $screen.Y }\n}\n\n# --- Actions ---\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output @\"\ndesktop-control / app-control.ps1\nActions:\n list-windows List all visible windows\n launch -Target <path> Launch an application [-Arguments <args>]\n focus -Target <title> Bring window to foreground [-ProcId <pid>]\n close -Target <title> Close a window gracefully [-ProcId <pid>]\n minimize -Target <title> Minimize a window [-ProcId <pid>]\n maximize -Target <title> Maximize a window [-ProcId <pid>]\n restore -Target <title> Restore a window [-ProcId <pid>]\n move -Target <title> Move window -X <x> -Y <y>\n resize -Target <title> Resize window -Width <w> -Height <h>\n snap -Target <title> Snap window -Position <left|right|...>\n\"@\n }\n\n \"list-windows\" {\n $wins = Get-AllWindows | Where-Object { $_.Width -gt 0 -and $_.Height -gt 0 }\n $wins | ForEach-Object {\n Write-Output (\"PID={0} State={1} Pos=({2},{3}) Size={4}x{5} Title=\"\"{6}\"\"\" -f $_.WinPID, $_.State, $_.X, $_.Y, $_.Width, $_.Height, $_.Title)\n }\n Write-Output \"\"\n Write-Output \"Total: $($wins.Count) windows\"\n }\n\n \"launch\" {\n if (-not $Target) { Write-Error \"Missing -Target (application path or name)\"; exit 1 }\n if ($Arguments) {\n $proc = Start-Process -FilePath $Target -ArgumentList $Arguments -PassThru\n } else {\n $proc = Start-Process -FilePath $Target -PassThru\n }\n Start-Sleep -Milliseconds 500\n Write-Output \"Launched: $Target (PID=$($proc.Id))\"\n }\n\n \"focus\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target' (ProcId=$ProcId)\"; exit 1 }\n if ([Win32Window]::IsIconic($win.Handle)) {\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_RESTORE) | Out-Null\n }\n [Win32Window]::ForceForeground($win.Handle)\n Write-Output \"Focused: \"\"$($win.Title)\"\" (PID=$($win.WinPID))\"\n }\n\n \"close\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $proc = Get-Process -Id $win.WinPID -ErrorAction SilentlyContinue\n if ($proc) {\n $proc.CloseMainWindow() | Out-Null\n Write-Output \"Close signal sent: \"\"$($win.Title)\"\" (PID=$($win.WinPID))\"\n } else {\n Write-Error \"Process not found for PID=$($win.WinPID)\"; exit 1\n }\n }\n\n \"minimize\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_MINIMIZE) | Out-Null\n Write-Output \"Minimized: \"\"$($win.Title)\"\"\"\n }\n\n \"maximize\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_MAXIMIZE) | Out-Null\n Write-Output \"Maximized: \"\"$($win.Title)\"\"\"\n }\n\n \"restore\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_RESTORE) | Out-Null\n Write-Output \"Restored: \"\"$($win.Title)\"\"\"\n }\n\n \"move\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $newX = if ($X -ge 0) { $X } else { $win.X }\n $newY = if ($Y -ge 0) { $Y } else { $win.Y }\n [Win32Window]::MoveWindow($win.Handle, $newX, $newY, $win.Width, $win.Height, $true) | Out-Null\n Write-Output \"Moved: \"\"$($win.Title)\"\" to ($newX, $newY)\"\n }\n\n \"resize\" {\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $newW = if ($Width -gt 0) { $Width } else { $win.Width }\n $newH = if ($Height -gt 0) { $Height } else { $win.Height }\n [Win32Window]::MoveWindow($win.Handle, $win.X, $win.Y, $newW, $newH, $true) | Out-Null\n Write-Output \"Resized: \"\"$($win.Title)\"\" to ${newW}x${newH}\"\n }\n\n \"snap\" {\n if (-not $Position) { Write-Error \"Missing -Position\"; exit 1 }\n $win = Find-Window -TitlePattern $Target -ByProcId $ProcId\n if (-not $win) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n if ([Win32Window]::IsZoomed($win.Handle)) {\n [Win32Window]::ShowWindow($win.Handle, [Win32Window]::SW_RESTORE) | Out-Null\n Start-Sleep -Milliseconds 100\n }\n $scr = Get-ScreenSize\n $hw = [math]::Floor($scr.Width / 2)\n $hh = [math]::Floor($scr.Height / 2)\n switch ($Position) {\n \"left\" { $sx=$scr.X; $sy=$scr.Y; $sw=$hw; $sh=$scr.Height }\n \"right\" { $sx=$scr.X+$hw; $sy=$scr.Y; $sw=$hw; $sh=$scr.Height }\n \"top\" { $sx=$scr.X; $sy=$scr.Y; $sw=$scr.Width; $sh=$hh }\n \"bottom\" { $sx=$scr.X; $sy=$scr.Y+$hh; $sw=$scr.Width; $sh=$hh }\n \"topleft\" { $sx=$scr.X; $sy=$scr.Y; $sw=$hw; $sh=$hh }\n \"topright\" { $sx=$scr.X+$hw; $sy=$scr.Y; $sw=$hw; $sh=$hh }\n \"bottomleft\" { $sx=$scr.X; $sy=$scr.Y+$hh; $sw=$hw; $sh=$hh }\n \"bottomright\" { $sx=$scr.X+$hw; $sy=$scr.Y+$hh; $sw=$hw; $sh=$hh }\n }\n [Win32Window]::MoveWindow($win.Handle, $sx, $sy, $sw, $sh, $true) | Out-Null\n Write-Output \"Snapped: \"\"$($win.Title)\"\" to $Position (${sw}x${sh} at ${sx},${sy})\"\n }\n }\n exit 0\n} catch {\n Write-Error \"ERROR: $_\"\n exit 1\n}\n",93 "mimeType": null,94 "size": null,95 "icons": null,96 "annotations": null,97 "meta": null98 },99 {100 "name": "input-sim.ps1.txt",101 "title": null,102 "uri": "skill://scripts/input-sim.ps1.txt",103 "description": "# ============================================================\n# input-sim.ps1 \u2014 Keyboard & Mouse Input Simulation for OpenClaw\n# Actions: type-text, send-keys, mouse-click, mouse-move,\n# mouse-scroll, help\n# ============================================================\n\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"type-text\",\"send-keys\",\"mouse-click\",\"mouse-move\",\"mouse-scroll\",\"help\")]\n [string]$Action,\n\n [string]$Text = \"\",\n [string]$Keys = \"\",\n [int]$X = -1,\n [int]$Y = -1,\n [ValidateSet(\"left\",\"right\",\"middle\",\"\")]\n [string]$Button = \"left\",\n [switch]$DoubleClick,\n [int]$Clicks = 0,\n [int]$DelayMs = 50\n)\n\nAdd-Type -AssemblyName System.Windows.Forms\nAdd-Type @\"\nusing System;\nusing System.Runtime.InteropServices;\n\npublic class InputSim {\n [DllImport(\"user32.dll\")] public static extern void SetCursorPos(int X, int Y);\n [DllImport(\"user32.dll\")] public static extern void mouse_event(uint dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo);\n [DllImport(\"user32.dll\")] public static extern bool GetCursorPos(out POINT lpPoint);\n\n [StructLayout(LayoutKind.Sequential)]\n public struct POINT { public int X; public int Y; }\n\n public const uint MOUSEEVENTF_LEFTDOWN = 0x0002;\n public const uint MOUSEEVENTF_LEFTUP = 0x0004;\n public const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;\n public const uint MOUSEEVENTF_RIGHTUP = 0x0010;\n public const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020;\n public const uint MOUSEEVENTF_MIDDLEUP = 0x0040;\n public const uint MOUSEEVENTF_WHEEL = 0x0800;\n public const uint MOUSEEVENTF_ABSOLUTE = 0x8000;\n public const uint MOUSEEVENTF_MOVE = 0x0001;\n}\n\"@\n\n# --- Key Mapping for SendKeys ---\nfunction ConvertTo-SendKeysFormat {\n param([string]$KeyCombo)\n # Parse combos like \"Ctrl+Shift+P\", \"Alt+F4\", \"F5\", \"Enter\"\n $parts = $KeyCombo -split '\\+'\n $modifiers = \"\"\n $key = \"\"\n foreach ($part in $parts) {\n switch ($part.Trim().ToLower()) {\n \"ctrl\" { $modifiers += \"^\" }\n \"control\" { $modifiers += \"^\" }\n \"alt\" { $modifiers += \"%\" }\n \"shift\" { $modifiers += \"+\" }\n \"win\" { # Win key handled separately\n $modifiers += \"^{ESC}\" # Approximation\n }\n \"enter\" { $key = \"{ENTER}\" }\n \"return\" { $key = \"{ENTER}\" }\n \"tab\" { $key = \"{TAB}\" }\n \"escape\" { $key = \"{ESC}\" }\n \"esc\" { $key = \"{ESC}\" }\n \"backspace\" { $key = \"{BACKSPACE}\" }\n \"delete\" { $key = \"{DELETE}\" }\n \"del\" { $key = \"{DELETE}\" }\n \"up\" { $key = \"{UP}\" }\n \"down\" { $key = \"{DOWN}\" }\n \"left\" { $key = \"{LEFT}\" }\n \"right\" { $key = \"{RIGHT}\" }\n \"home\" { $key = \"{HOME}\" }\n \"end\" { $key = \"{END}\" }\n \"pageup\" { $key = \"{PGUP}\" }\n \"pgup\" { $key = \"{PGUP}\" }\n \"pagedown\" { $key = \"{PGDN}\" }\n \"pgdn\" { $key = \"{PGDN}\" }\n \"space\" { $key = \" \" }\n \"insert\" { $key = \"{INSERT}\" }\n \"ins\" { $key = \"{INSERT}\" }\n \"capslock\" { $key = \"{CAPSLOCK}\" }\n \"numlock\" { $key = \"{NUMLOCK}\" }\n \"scrolllock\"{ $key = \"{SCROLLLOCK}\" }\n \"prtsc\" { $key = \"{PRTSC}\" }\n \"break\" { $key = \"{BREAK}\" }\n \"f1\" { $key = \"{F1}\" }\n \"f2\" { $key = \"{F2}\" }\n \"f3\" { $key = \"{F3}\" }\n \"f4\" { $key = \"{F4}\" }\n \"f5\" { $key = \"{F5}\" }\n \"f6\" { $key = \"{F6}\" }\n \"f7\" { $key = \"{F7}\" }\n \"f8\" { $key = \"{F8}\" }\n \"f9\" { $key = \"{F9}\" }\n \"f10\" { $key = \"{F10}\" }\n \"f11\" { $key = \"{F11}\" }\n \"f12\" { $key = \"{F12}\" }\n default {\n $k = $part.Trim()\n if ($k.Length -eq 1) {\n # Single character \u2014 check if it's special in SendKeys\n if ($k -match '[\\+\\^\\%\\~\\(\\)\\{\\}\\[\\]]') {\n $key = \"{$k}\"\n } else {\n $key = $k.ToLower()\n }\n } else {\n $key = $k.ToLower()\n }\n }\n }\n }\n if ($modifiers -and $key) {\n return \"$modifiers($key)\"\n } elseif ($key) {\n return $key\n } else {\n return $KeyCombo\n }\n}\n\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output @\"\ndesktop-control / input-sim.ps1\nActions:\n type-text -Text <text> Type text into focused window [-DelayMs <ms>]\n send-keys -Keys <combo> Send keyboard shortcut (e.g. \"Ctrl+S\", \"Alt+F4\", \"Enter\", \"F5\")\n mouse-click -X <x> -Y <y> Click at coordinates [-Button left|right|middle] [-DoubleClick]\n mouse-move -X <x> -Y <y> Move mouse to coordinates\n mouse-scroll -Clicks <n> Scroll (positive=up, negative=down)\n\nKey combos: Ctrl, Alt, Shift + letter/number/F-key/special\nSpecial keys: Enter, Tab, Escape, Backspace, Delete, Up, Down, Left, Right, Home, End,\n PageUp, PageDown, Space, F1-F12, Insert, CapsLock, NumLock\n\"@\n }\n\n \"type-text\" {\n if (-not $Text) { Write-Error \"Missing -Text parameter\"; exit 1 }\n Start-Sleep -Milliseconds 100\n # Use SendKeys for each character with optional delay\n # Escape special SendKeys characters\n $escaped = $Text -replace '([\\+\\^\\%\\~\\(\\)\\{\\}\\[\\]])', '{$1}'\n [System.Windows.Forms.SendKeys]::SendWait($escaped)\n Write-Output \"Typed: \"\"$Text\"\" ($($Text.Length) characters)\"\n }\n\n \"send-keys\" {\n if (-not $Keys) { Write-Error \"Missing -Keys parameter\"; exit 1 }\n Start-Sleep -Milliseconds 100\n $sendKeysFormat = ConvertTo-SendKeysFormat $Keys\n [System.Windows.Forms.SendKeys]::SendWait($sendKeysFormat)\n Write-Output \"Sent: $Keys (SendKeys format: $sendKeysFormat)\"\n }\n\n \"mouse-click\" {\n if ($X -lt 0 -or $Y -lt 0) { Write-Error \"Missing -X and -Y coordinates\"; exit 1 }\n [InputSim]::SetCursorPos($X, $Y)\n Start-Sleep -Milliseconds 50\n switch ($Button.ToLower()) {\n \"left\" {\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [IntPtr]::Zero)\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_LEFTUP, 0, 0, 0, [IntPtr]::Zero)\n if ($DoubleClick) {\n Start-Sleep -Milliseconds 50\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [IntPtr]::Zero)\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_LEFTUP, 0, 0, 0, [IntPtr]::Zero)\n }\n }\n \"right\" {\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, [IntPtr]::Zero)\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_RIGHTUP, 0, 0, 0, [IntPtr]::Zero)\n }\n \"middle\" {\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, [IntPtr]::Zero)\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_MIDDLEUP, 0, 0, 0, [IntPtr]::Zero)\n }\n }\n $clickType = if ($DoubleClick) { \"Double-click\" } else { \"Click\" }\n Write-Output \"$clickType ($Button) at ($X, $Y)\"\n }\n\n \"mouse-move\" {\n if ($X -lt 0 -or $Y -lt 0) { Write-Error \"Missing -X and -Y coordinates\"; exit 1 }\n [InputSim]::SetCursorPos($X, $Y)\n Write-Output \"Mouse moved to ($X, $Y)\"\n }\n\n \"mouse-scroll\" {\n if ($Clicks -eq 0) { Write-Error \"Missing -Clicks parameter (positive=up, negative=down)\"; exit 1 }\n $scrollAmount = $Clicks * 120 # 120 = one wheel notch\n [InputSim]::mouse_event([InputSim]::MOUSEEVENTF_WHEEL, 0, 0, $scrollAmount, [IntPtr]::Zero)\n $direction = if ($Clicks -gt 0) { \"up\" } else { \"down\" }\n Write-Output \"Scrolled $direction by $([Math]::Abs($Clicks)) clicks\"\n }\n }\n exit 0\n} catch {\n Write-Error \"ERROR: $_\"\n exit 1\n}\n",104 "mimeType": null,105 "size": null,106 "icons": null,107 "annotations": null,108 "meta": null109 },110 {111 "name": "screen-info.ps1.txt",112 "title": null,113 "uri": "skill://scripts/screen-info.ps1.txt",114 "description": "# screen-info.ps1 - Screen and System Info for OpenClaw\nparam(\n [Parameter(Mandatory=$true)]\n [ValidateSet(\"displays\",\"active-window\",\"window-info\",\"screenshot\",\"clipboard-get\",\"clipboard-set\",\"system-info\",\"help\")]\n [string]$Action,\n [string]$Target = \"\",\n [string]$OutputPath = \"\",\n [string]$Text = \"\"\n)\n\nAdd-Type -AssemblyName System.Windows.Forms\nAdd-Type -AssemblyName System.Drawing\n\nAdd-Type @\"\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\npublic class ScreenHelper {\n [DllImport(\"user32.dll\")] public static extern IntPtr GetForegroundWindow();\n [DllImport(\"user32.dll\")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);\n [DllImport(\"user32.dll\", CharSet=CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder sb, int maxCount);\n [DllImport(\"user32.dll\")] public static extern int GetWindowTextLength(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid);\n [DllImport(\"user32.dll\", CharSet=CharSet.Auto)] public static extern int GetClassName(IntPtr hWnd, StringBuilder sb, int maxCount);\n [DllImport(\"user32.dll\")] public static extern bool IsIconic(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool IsZoomed(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool IsWindowVisible(IntPtr hWnd);\n [DllImport(\"user32.dll\")] public static extern bool EnumWindows(EnumWindowsProc cb, IntPtr lParam);\n public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; }\n}\n\"@\n\nfunction Get-WindowDetails([IntPtr]$hWnd) {\n $sb = New-Object System.Text.StringBuilder(256)\n [ScreenHelper]::GetWindowText($hWnd, $sb, 256) | Out-Null\n $title = $sb.ToString()\n $sb.Clear() | Out-Null\n [ScreenHelper]::GetClassName($hWnd, $sb, 256) | Out-Null\n $class = $sb.ToString()\n $procId = [uint32]0\n [ScreenHelper]::GetWindowThreadProcessId($hWnd, [ref]$procId) | Out-Null\n $rect = New-Object ScreenHelper+RECT\n [ScreenHelper]::GetWindowRect($hWnd, [ref]$rect) | Out-Null\n $state = \"Normal\"\n if ([ScreenHelper]::IsIconic($hWnd)) { $state = \"Minimized\" }\n elseif ([ScreenHelper]::IsZoomed($hWnd)) { $state = \"Maximized\" }\n return @{\n Handle=$hWnd; Title=$title; Class=$class; PID=$procId\n X=$rect.Left; Y=$rect.Top\n Width=$rect.Right-$rect.Left; Height=$rect.Bottom-$rect.Top\n State=$state\n }\n}\n\nfunction Find-WindowByTitle([string]$pattern) {\n $script:result = $null\n $cb = [ScreenHelper+EnumWindowsProc]{\n param($h,$l)\n if ([ScreenHelper]::IsWindowVisible($h)) {\n $len = [ScreenHelper]::GetWindowTextLength($h)\n if ($len -gt 0) {\n $s = New-Object System.Text.StringBuilder($len+1)\n [ScreenHelper]::GetWindowText($h, $s, $s.Capacity) | Out-Null\n if ($s.ToString() -like \"*$pattern*\") {\n $script:result = $h\n return $false\n }\n }\n }\n return $true\n }\n [ScreenHelper]::EnumWindows($cb, [IntPtr]::Zero) | Out-Null\n return $script:result\n}\n\ntry {\n switch ($Action) {\n \"help\" {\n Write-Output \"screen-info.ps1 - displays, active-window, window-info, screenshot, clipboard-get, clipboard-set, system-info\"\n }\n \"displays\" {\n $screens = [System.Windows.Forms.Screen]::AllScreens\n $i = 0\n foreach ($s in $screens) {\n $i++\n $p = if($s.Primary){\"(Primary)\"}else{\"\"}\n Write-Output \"Display #$i $p\"\n Write-Output \" Device: $($s.DeviceName)\"\n Write-Output \" Resolution: $($s.Bounds.Width)x$($s.Bounds.Height)\"\n Write-Output \" Position: ($($s.Bounds.X), $($s.Bounds.Y))\"\n Write-Output \" WorkArea: $($s.WorkingArea.Width)x$($s.WorkingArea.Height)\"\n Write-Output \" BitsPerPx: $($s.BitsPerPixel)\"\n Write-Output \"\"\n }\n Write-Output \"Total: $i display(s)\"\n }\n \"active-window\" {\n $hw = [ScreenHelper]::GetForegroundWindow()\n if ($hw -eq [IntPtr]::Zero) { Write-Error \"No active window\"; exit 1 }\n $d = Get-WindowDetails $hw\n Write-Output \"Active Window:\"\n Write-Output \" Title: $($d.Title)\"\n Write-Output \" Class: $($d.Class)\"\n Write-Output \" PID: $($d.PID)\"\n Write-Output \" Pos: ($($d.X), $($d.Y))\"\n Write-Output \" Size: $($d.Width)x$($d.Height)\"\n Write-Output \" State: $($d.State)\"\n }\n \"window-info\" {\n if (-not $Target) { Write-Error \"Missing -Target\"; exit 1 }\n $hw = Find-WindowByTitle $Target\n if (-not $hw -or $hw -eq [IntPtr]::Zero) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $d = Get-WindowDetails $hw\n Write-Output \"Window Info:\"\n Write-Output \" Title: $($d.Title)\"\n Write-Output \" Class: $($d.Class)\"\n Write-Output \" PID: $($d.PID)\"\n Write-Output \" Pos: ($($d.X), $($d.Y))\"\n Write-Output \" Size: $($d.Width)x$($d.Height)\"\n Write-Output \" State: $($d.State)\"\n }\n \"screenshot\" {\n $outPath = if($OutputPath){$OutputPath}else{\"$env:USERPROFILE\\screenshot_$(Get-Date -Format 'yyyyMMdd_HHmmss').png\"}\n if ($Target) {\n $hw = Find-WindowByTitle $Target\n if (-not $hw -or $hw -eq [IntPtr]::Zero) { Write-Error \"Window not found: '$Target'\"; exit 1 }\n $rect = New-Object ScreenHelper+RECT\n [ScreenHelper]::GetWindowRect($hw, [ref]$rect) | Out-Null\n $w = $rect.Right - $rect.Left; $h = $rect.Bottom - $rect.Top\n $bmp = New-Object System.Drawing.Bitmap($w, $h)\n $g = [System.Drawing.Graphics]::FromImage($bmp)\n $g.CopyFromScreen($rect.Left, $rect.Top, 0, 0, [System.Drawing.Size]::new($w,$h))\n $g.Dispose()\n } else {\n $bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds\n $bmp = New-Object System.Drawing.Bitmap($bounds.Width, $bounds.Height)\n $g = [System.Drawing.Graphics]::FromImage($bmp)\n $g.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)\n $g.Dispose()\n }\n $bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Png)\n $bmp.Dispose()\n Write-Output \"Screenshot saved: $outPath\"\n }\n \"clipboard-get\" {\n $clip = [System.Windows.Forms.Clipboard]::GetText()\n if ($clip) {\n Write-Output \"Clipboard content:\"\n Write-Output \"---\"\n Write-Output $clip\n Write-Output \"---\"\n Write-Output \"($($clip.Length) characters)\"\n } else { Write-Output \"Clipboard is empty or contains non-text data.\" }\n }\n \"clipboard-set\" {\n if (-not $Text) { Write-Error \"Missing -Text\"; exit 1 }\n [System.Windows.Forms.Clipboard]::SetText($Text)\n Write-Output \"Clipboard set ($($Text.Length) characters)\"\n }\n \"system-info\" {\n $os = Get-CimInstance Win32_OperatingSystem\n $cs = Get-CimInstance Win32_ComputerSystem\n $uptime = (Get-Date) - $os.LastBootUpTime\n Write-Output \"System Info:\"\n Write-Output \" Computer: $($cs.Name)\"\n Write-Output \" OS: $($os.Caption) $($os.Version)\"\n Write-Output \" RAM: $([math]::Round($cs.TotalPhysicalMemory/1GB,1)) GB\"\n Write-Output \" Free RAM: $([math]::Round($os.FreePhysicalMemory/1MB,1)) GB\"\n Write-Output \" Uptime: $($uptime.Days)d $($uptime.Hours)h $($uptime.Minutes)m\"\n Write-Output \" User: $env:USERNAME\"\n $screens = [System.Windows.Forms.Screen]::AllScreens\n Write-Output \" Displays: $($screens.Count)\"\n foreach ($s in $screens) {\n $p = if($s.Primary){\"*\"}else{\"\"}\n Write-Output \" $p $($s.DeviceName): $($s.Bounds.Width)x$($s.Bounds.Height)\"\n }\n }\n }\n exit 0\n} catch { Write-Error \"ERROR: $_\"; exit 1 }\n",115 "mimeType": null,116 "size": null,117 "icons": null,118 "annotations": null,119 "meta": null120 }121 ],122 "resource_templates": [],123 "tools": []124 },125 "error": null126 }127 ],128 "issues": [129 {130 "code": "W004",131 "message": "The MCP server is not in our registry.",132 "reference": [133 0,134 null135 ],136 "extra_data": null137 }138 ],139 "labels": [140 [141 {142 "is_public_sink": 0,143 "destructive": 0,144 "untrusted_content": 0,145 "private_data": 0146 },147 {148 "is_public_sink": 0,149 "destructive": 0,150 "untrusted_content": 0,151 "private_data": 0152 },153 {154 "is_public_sink": 0,155 "destructive": 0,156 "untrusted_content": 0,157 "private_data": 0158 },159 {160 "is_public_sink": 0,161 "destructive": 0,162 "untrusted_content": 0,163 "private_data": 0164 },165 {166 "is_public_sink": 0,167 "destructive": 0,168 "untrusted_content": 0,169 "private_data": 0170 },171 {172 "is_public_sink": 0,173 "destructive": 0,174 "untrusted_content": 0,175 "private_data": 0176 },177 {178 "is_public_sink": 0,179 "destructive": 0,180 "untrusted_content": 0,181 "private_data": 0182 }183 ]184 ],185 "error": null186 }187}188189Process exited with code 0190✓ Completed in 137385ms
npm-audit▸No package.json found — skipping npm audit
View logs
1No package.json found at /tmp/clawguard-scan-xeVZAz/repo/skills/lexylent/desktop-control-win/package.json2Skipping npm audit.
Scanned: 2/13/2026, 12:17:23 AM