[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M699VPYAC2F3H81V1HBKMJHD":3,"skill-same:01M699VPYAC2F3H81V1HBKMJHD":61},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":31,"linkOnly":32,"markdownContent":33,"markdownBody":34,"frontMatter":35,"refName":38,"commitSha":39,"skillDirectory":40,"forksCount":41,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":44,"ownerDescription":45,"updatedAt":46,"install":47,"resources":60},"01M699VPYAC2F3H81V1HBKMJHD","launch-vscode-extension",null,"Launch and automate VS Code Insiders with the Copilot Chat extension using agent-browser via Chrome DevTools Protocol. Use when you need to interact with the VS Code UI, automate the chat panel, test the extension UI, or take screenshots. Triggers include 'automate VS Code', 'interact with chat', 'test the UI', 'take a screenshot', 'launch with debugging'.","microsoft\u002Frayfin","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M699VK9NEV8GH0Y5JKT1G8XG",661,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Flaunch-vscode-extension\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30],"launch","vscode","launch vscode extension","screenshots","chrome","test","copilot","2026-11-10 10:12:30",false,"---\nname: launch-vscode-extension\ndescription: \"Launch and automate VS Code Insiders with the Copilot Chat extension using agent-browser via Chrome DevTools Protocol. Use when you need to interact with the VS Code UI, automate the chat panel, test the extension UI, or take screenshots. Triggers include 'automate VS Code', 'interact with chat', 'test the UI', 'take a screenshot', 'launch with debugging'.\"\nmetadata:\n  allowed-tools: Bash(agent-browser:*), Bash(npx agent-browser:*)\n---\n\n# VS Code Extension Automation\n\nAutomate VS Code Insiders with the Copilot Chat extension using agent-browser. VS Code is built on Electron\u002FChromium and exposes a Chrome DevTools Protocol (CDP) port that agent-browser can connect to, enabling the same snapshot-interact workflow used for web pages.\n\n## Prerequisites\n\n- **`agent-browser` must be installed.** It's available in the project's devDependencies — run `npm install`. Use `npx agent-browser` if it's not on your PATH, or install globally with `npm install -g agent-browser`.\n- **`code-insiders` is required.** This extension uses 58 proposed VS Code APIs and targets `vscode ^1.110.0-20260223`. VS Code Stable will **not** activate it — you must use VS Code Insiders.\n- **The extension must be compiled first.** Use `npm run compile` for a one-shot build, or `npm run watch` for iterative development.\n- **CSS selectors are internal implementation details.** Selectors like `.interactive-input-part`, `.monaco-editor`, and `.view-line` are VS Code internals that may change across versions. If automation breaks after a VS Code update, re-snapshot and check for selector changes.\n\n## Core Workflow\n\n1. **Build** the extension\n2. **Launch** VS Code Insiders with the extension and remote debugging enabled\n3. **Connect** agent-browser to the CDP port\n4. **Snapshot** to discover interactive elements\n5. **Interact** using element refs\n6. **Re-snapshot** after navigation or state changes\n\n> **? Take screenshots for a paper trail.** Use `agent-browser screenshot \u003Cpath>` at key moments — after launch, before\u002Fafter interactions, and when something goes wrong. Screenshots provide visual proof of what the UI looked like and are invaluable for debugging failures or documenting what was accomplished.\n>\n> Save screenshots inside `.vscode-ext-debug\u002Fscreenshots\u002F` (gitignored) using a timestamped subfolder so each run is isolated and nothing gets overwritten:\n>\n> ```bash\n> # Create a timestamped folder for this run's screenshots\n> SCREENSHOT_DIR=\".vscode-ext-debug\u002Fscreenshots\u002F$(date +%Y-%m-%dT%H-%M-%S)\"\n> mkdir -p \"$SCREENSHOT_DIR\"\n>\n> # Windows (PowerShell):\n> # $screenshotDir = \".vscode-ext-debug\\screenshots\\$(Get-Date -Format 'yyyy-MM-ddTHH-mm-ss')\"\n> # New-Item -ItemType Directory -Force -Path $screenshotDir\n>\n> # Save a screenshot (path is a positional argument — use .\u002F or absolute paths)\n> # Bare filenames without .\u002F may be misinterpreted as CSS selectors\n> agent-browser screenshot \"$SCREENSHOT_DIR\u002Fafter-launch.png\"\n> ```\n\n```bash\n# Build and launch with the extension\nnpm run compile\n# Use a PERSISTENT user-data-dir so auth state is preserved across sessions.\n# .vscode-ext-debug is relative to the project root — works in worktrees and is gitignored.\ncode-insiders --extensionDevelopmentPath=\"$PWD\" --remote-debugging-port=9223 --user-data-dir=\"$PWD\u002F.vscode-ext-debug\"\n# On Windows (PowerShell):\n# code-insiders --extensionDevelopmentPath=\"$PWD\" --remote-debugging-port=9223 --user-data-dir=\"$PWD\\.vscode-ext-debug\"\n\n# Wait for VS Code to start, retry until connected\nfor i in 1 2 3 4 5; do agent-browser connect 9223 2>\u002Fdev\u002Fnull && break || sleep 3; done\n\n# Verify you're connected to the right target (not about:blank)\n# If `tab` shows the wrong target, run `agent-browser close` and reconnect\nagent-browser tab\nagent-browser snapshot -i\n```\n\n## Connecting\n\n```bash\n# Connect to a specific port\nagent-browser connect 9223\n\n# Or use --cdp on each command\nagent-browser --cdp 9223 snapshot -i\n\n# Auto-discover a running Chromium-based app\nagent-browser --auto-connect snapshot -i\n```\n\nAfter `connect`, all subsequent commands target the connected app without needing `--cdp`.\n\n## Tab Management\n\nVS Code uses multiple webviews internally. Use tab commands to list and switch between them:\n\n```bash\n# List all available targets (windows, webviews, etc.)\nagent-browser tab\n\n# Switch to a specific tab by index\nagent-browser tab 2\n\n# Switch by URL pattern\nagent-browser tab --url \"*settings*\"\n```\n\n## Launching VS Code Extensions for Debugging\n\nTo debug a VS Code extension via agent-browser, launch VS Code Insiders with `--extensionDevelopmentPath` pointing to your extension source and `--remote-debugging-port` for CDP. Use `--user-data-dir` to avoid conflicting with an already-running VS Code instance.\n\n```bash\n# Build the extension first (from the repo root)\nnpm run compile\n\n# Launch VS Code Insiders with the extension and CDP\n# IMPORTANT: Use a persistent directory (not \u002Ftmp) so auth state is preserved.\n# .vscode-ext-debug is relative to the project root — works in worktrees and is gitignored.\ncode-insiders \\\n  --extensionDevelopmentPath=\"$PWD\" \\\n  --remote-debugging-port=9223 \\\n  --user-data-dir=\"$PWD\u002F.vscode-ext-debug\"\n\n# Wait for VS Code to start, retry until connected\nfor i in 1 2 3 4 5; do agent-browser connect 9223 2>\u002Fdev\u002Fnull && break || sleep 3; done\n\n# Verify you're connected to the right target (not about:blank)\n# If `tab` shows the wrong target, run `agent-browser close` and reconnect\nagent-browser tab\nagent-browser snapshot -i\n```\n\n**Key flags:**\n- `--extensionDevelopmentPath=\u003Cpath>` — loads your extension from source (must be compiled first). Use `$PWD` when running from the repo root.\n- `--remote-debugging-port=9223` — enables CDP (use 9223 to avoid conflicts with other apps on 9222)\n- `--user-data-dir=\u003Cpath>` — uses a separate profile so it starts a new process instead of sending to an existing VS Code instance. **Always use a persistent path** (e.g., `$PWD\u002F.vscode-ext-debug`) rather than `\u002Ftmp\u002F...` so authentication, settings, and extension state survive across sessions.\n\n**Without `--user-data-dir`**, VS Code detects the running instance, forwards the args to it, and exits immediately — you'll see \"Sent env to running instance. Terminating...\" and CDP never starts.\n\n> **⚠️ Authentication is required.** The Copilot Chat extension needs an authenticated GitHub session to function. Using a temp directory (e.g., `\u002Ftmp\u002F...`) creates a fresh profile with no auth — the agent will hit a \"Sign in to use Copilot\" wall and model resolution will fail with \"Language model unavailable.\"\n>\n> **Always use a persistent `--user-data-dir`** like `$PWD\u002F.vscode-ext-debug`. On first use, launch once and sign in manually. Subsequent launches will reuse the auth session.\n\n## Restarting After Code Changes\n\n**After making changes to the extension source code, you must restart VS Code to pick up the new build.** The extension host loads the compiled bundle at startup — changes are not hot-reloaded.\n\n### Restart Workflow\n\n1. **Recompile** the extension\n2. **Kill** the running VS Code instance (the one using your debug user-data-dir)\n3. **Relaunch** VS Code with the same flags\n\n```bash\n# 1. Recompile\nnpm run compile\n\n# 2. Kill the VS Code instance tied to this project's debug profile, then relaunch\n# macOS \u002F Linux:\nkill $(ps ax -ww -o pid,command | grep \"$PWD\u002F.vscode-ext-debug\" | grep -v grep | awk '{print $1}' | head -1)\n\n# Windows (PowerShell):\n# Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like \"*$PWD\\.vscode-ext-debug*\" } | ForEach-Object { Stop-Process -Id $_.ProcessId }\n\n# 3. Relaunch\ncode-insiders \\\n  --extensionDevelopmentPath=\"$PWD\" \\\n  --remote-debugging-port=9223 \\\n  --user-data-dir=\"$PWD\u002F.vscode-ext-debug\"\n\n# 4. Reconnect agent-browser\nfor i in 1 2 3 4 5; do agent-browser connect 9223 2>\u002Fdev\u002Fnull && break || sleep 3; done\nagent-browser snapshot -i\n```\n\n> **Tip:** If you're iterating frequently, run `npm run watch` in a separate terminal so compilation happens automatically. You still need to kill and relaunch VS Code to load the new bundle.\n\n## Interacting with Monaco Editor (Chat Input, Code Editors)\n\nVS Code uses Monaco Editor for all text inputs including the Copilot Chat input. Monaco editors appear as textboxes in the accessibility snapshot but require specific agent-browser commands to interact with.\n\n### What Works\n\n#### `type @ref` — The Best Approach\n\nThe `type` command with a snapshot ref handles focus and input in one step:\n\n```bash\n# Snapshot to find the chat input ref\nagent-browser snapshot -i\n# Look for: textbox \"The editor is not accessible...\" [ref=e51]\n\n# Type directly using the ref — handles focus automatically\nagent-browser type @e51 \"Hello from George!\"\n\n# Send the message\nagent-browser press Enter\n\n# Wait for the response to complete before re-snapshotting.\n# Poll until the \"Stop generating\" button disappears:\nfor i in $(seq 1 30); do\n  agent-browser snapshot -i 2>\u002Fdev\u002Fnull | grep -q \"Stop generating\" || break\n  sleep 1\ndone\nagent-browser snapshot -i\n```\n\nThis is the simplest and most reliable method. It works for both the main editor chat input and the sidebar chat panel.\n\n> **Tip:** If `type @ref` silently drops text (the editor stays empty), the ref may be stale or the editor not yet ready. Re-snapshot to get a fresh ref and try again. You can verify text was entered using the snippet in \"Verifying Text in Monaco\" below.\n\n#### `keyboard type` \u002F `keyboard inserttext` — After Focus\n\nIf focus is already on a Monaco editor, `keyboard type` and `keyboard inserttext` both work:\n\n> **⚠️ Warning:** `keyboard type` can hang indefinitely in some focus states (e.g., after JS mouse events). If it doesn't return within a few seconds, interrupt it and fall back to `press` for individual keystrokes.\n\n```bash\n# Focus first (via type @ref, or JS mouse events, or a prior interaction)\nagent-browser type @e51 \"\"\n# Then keyboard type works for subsequent input\nagent-browser keyboard type \"More text here\"\nagent-browser keyboard inserttext \"And this too\"\n```\n\n#### `press` — Individual Keystrokes\n\nAlways works when focus is on a Monaco editor. Useful for special keys, keyboard shortcuts, and as a universal fallback for typing text character by character:\n\n```bash\n# Type text character by character (works on all builds)\nagent-browser press H\nagent-browser press e\nagent-browser press l\nagent-browser press l\nagent-browser press o\nagent-browser press Space  # Use \"Space\" for spaces\n\n# Select all\n# macOS:\nagent-browser press Meta+a\n# Linux \u002F Windows:\nagent-browser press Control+a\n\nagent-browser press Backspace    # Delete selection\nagent-browser press Enter        # Send message \u002F new line\n\n# Send to new chat\n# macOS:\nagent-browser press Meta+Shift+Enter\n# Linux \u002F Windows:\nagent-browser press Control+Shift+Enter\n```\n\n### What Does NOT Work\n\n| Method | Result | Reason |\n|--------|--------|--------|\n| `click @ref` | \"Element blocked by another element\" | Monaco overlays a transparent div over the textarea |\n| `fill @ref \"text\"` | \"Element not found or not visible\" | The textbox is not a standard fillable input |\n| `document.execCommand(\"insertText\")` via `eval` | No effect | Monaco intercepts and discards execCommand |\n| Setting `textarea.value` + dispatching `input` event via `eval` | No effect | Monaco doesn't read from the textarea's value property |\n\n### Fallback: Focus via JavaScript Mouse Events\n\nIf `type @ref` doesn't work (e.g., ref is stale), you can focus the editor via JavaScript:\n\n```bash\nagent-browser eval '\n(() => {\n  const inputPart = document.querySelector(\".interactive-input-part\");\n  const editor = inputPart.querySelector(\".monaco-editor\");\n  const rect = editor.getBoundingClientRect();\n  const x = rect.x + rect.width \u002F 2;\n  const y = rect.y + rect.height \u002F 2;\n  editor.dispatchEvent(new MouseEvent(\"mousedown\", { bubbles: true, clientX: x, clientY: y }));\n  editor.dispatchEvent(new MouseEvent(\"mouseup\", { bubbles: true, clientX: x, clientY: y }));\n  editor.dispatchEvent(new MouseEvent(\"click\", { bubbles: true, clientX: x, clientY: y }));\n  return \"activeElement: \" + document.activeElement?.className;\n})()'\n\n# After JS focus, keyboard type and press work\nagent-browser keyboard type \"Text after JS focus\"\n```\n\nAfter JS mouse events, `document.activeElement` becomes a `DIV` with class `native-edit-context` — this is VS Code's native text editing surface.\n\n### Verifying Text in Monaco\n\nMonaco renders text in `.view-line` elements, not the textarea:\n\n```bash\nagent-browser eval '\n(() => {\n  const inputPart = document.querySelector(\".interactive-input-part\");\n  return Array.from(inputPart.querySelectorAll(\".view-line\")).map(vl => vl.textContent).join(\"|\");\n})()'\n```\n\n### Clearing Monaco Input\n\n```bash\n# macOS:\nagent-browser press Meta+a\n# Linux \u002F Windows:\nagent-browser press Control+a\n\nagent-browser press Backspace\n```\n\n## Troubleshooting\n\n### \"Connection refused\" or \"Cannot connect\"\n\n- Make sure VS Code Insiders was launched with `--remote-debugging-port=9223`\n- If VS Code was already running, quit and relaunch with the flag\n- Check that the port isn't in use by another process:\n  - macOS \u002F Linux: `lsof -i :9223`\n  - Windows: `netstat -ano | findstr 9223`\n\n### Elements not appearing in snapshot\n\n- VS Code uses multiple webviews. Use `agent-browser tab` to list targets and switch to the right one\n- Use `agent-browser snapshot -i -C` to include cursor-interactive elements (divs with onclick handlers)\n\n### Cannot type in Monaco inputs\n\n- Standard `click` and `fill` don't work on Monaco editors — see the \"Interacting with Monaco Editor\" section above for the full compatibility matrix\n- `type @ref` is the best approach; individual `press` commands work everywhere; `keyboard type` and `keyboard inserttext` work after focus is established\n\n### Screenshots fail with \"Permission denied\" (macOS)\n\nIf `agent-browser screenshot` returns \"Permission denied\", your terminal needs Screen Recording permission. Grant it in **System Settings → Privacy & Security → Screen Recording**. As a fallback, use the `eval` verification snippet to confirm text was entered — this doesn't require screen permissions.\n\n## Cleanup\n\n**Always kill the debug VS Code instance when you're done.** Leaving it running wastes resources and holds the CDP port.\n\n```bash\n# Disconnect agent-browser\nagent-browser close\n\n# Kill the debug VS Code instance\n# macOS \u002F Linux:\nkill $(ps ax -ww -o pid,command | grep \"$PWD\u002F.vscode-ext-debug\" | grep -v grep | awk '{print $1}' | head -1)\n\n# Windows (PowerShell):\n# Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like \"*$PWD\\.vscode-ext-debug*\" } | ForEach-Object { Stop-Process -Id $_.ProcessId }\n```","# VS Code Extension Automation\n\nAutomate VS Code Insiders with the Copilot Chat extension using agent-browser. VS Code is built on Electron\u002FChromium and exposes a Chrome DevTools Protocol (CDP) port that agent-browser can connect to, enabling the same snapshot-interact workflow used for web pages.\n\n## Prerequisites\n\n- **`agent-browser` must be installed.** It's available in the project's devDependencies — run `npm install`. Use `npx agent-browser` if it's not on your PATH, or install globally with `npm install -g agent-browser`.\n- **`code-insiders` is required.** This extension uses 58 proposed VS Code APIs and targets `vscode ^1.110.0-20260223`. VS Code Stable will **not** activate it — you must use VS Code Insiders.\n- **The extension must be compiled first.** Use `npm run compile` for a one-shot build, or `npm run watch` for iterative development.\n- **CSS selectors are internal implementation details.** Selectors like `.interactive-input-part`, `.monaco-editor`, and `.view-line` are VS Code internals that may change across versions. If automation breaks after a VS Code update, re-snapshot and check for selector changes.\n\n## Core Workflow\n\n1. **Build** the extension\n2. **Launch** VS Code Insiders with the extension and remote debugging enabled\n3. **Connect** agent-browser to the CDP port\n4. **Snapshot** to discover interactive elements\n5. **Interact** using element refs\n6. **Re-snapshot** after navigation or state changes\n\n> **? Take screenshots for a paper trail.** Use `agent-browser screenshot \u003Cpath>` at key moments — after launch, before\u002Fafter interactions, and when something goes wrong. Screenshots provide visual proof of what the UI looked like and are invaluable for debugging failures or documenting what was accomplished.\n>\n> Save screenshots inside `.vscode-ext-debug\u002Fscreenshots\u002F` (gitignored) using a timestamped subfolder so each run is isolated and nothing gets overwritten:\n>\n> ```bash\n> # Create a timestamped folder for this run's screenshots\n> SCREENSHOT_DIR=\".vscode-ext-debug\u002Fscreenshots\u002F$(date +%Y-%m-%dT%H-%M-%S)\"\n> mkdir -p \"$SCREENSHOT_DIR\"\n>\n> # Windows (PowerShell):\n> # $screenshotDir = \".vscode-ext-debug\\screenshots\\$(Get-Date -Format 'yyyy-MM-ddTHH-mm-ss')\"\n> # New-Item -ItemType Directory -Force -Path $screenshotDir\n>\n> # Save a screenshot (path is a positional argument — use .\u002F or absolute paths)\n> # Bare filenames without .\u002F may be misinterpreted as CSS selectors\n> agent-browser screenshot \"$SCREENSHOT_DIR\u002Fafter-launch.png\"\n> ```\n\n```bash\n# Build and launch with the extension\nnpm run compile\n# Use a PERSISTENT user-data-dir so auth state is preserved across sessions.\n# .vscode-ext-debug is relative to the project root — works in worktrees and is gitignored.\ncode-insiders --extensionDevelopmentPath=\"$PWD\" --remote-debugging-port=9223 --user-data-dir=\"$PWD\u002F.vscode-ext-debug\"\n# On Windows (PowerShell):\n# code-insiders --extensionDevelopmentPath=\"$PWD\" --remote-debugging-port=9223 --user-data-dir=\"$PWD\\.vscode-ext-debug\"\n\n# Wait for VS Code to start, retry until connected\nfor i in 1 2 3 4 5; do agent-browser connect 9223 2>\u002Fdev\u002Fnull && break || sleep 3; done\n\n# Verify you're connected to the right target (not about:blank)\n# If `tab` shows the wrong target, run `agent-browser close` and reconnect\nagent-browser tab\nagent-browser snapshot -i\n```\n\n## Connecting\n\n```bash\n# Connect to a specific port\nagent-browser connect 9223\n\n# Or use --cdp on each command\nagent-browser --cdp 9223 snapshot -i\n\n# Auto-discover a running Chromium-based app\nagent-browser --auto-connect snapshot -i\n```\n\nAfter `connect`, all subsequent commands target the connected app without needing `--cdp`.\n\n## Tab Management\n\nVS Code uses multiple webviews internally. Use tab commands to list and switch between them:\n\n```bash\n# List all available targets (windows, webviews, etc.)\nagent-browser tab\n\n# Switch to a specific tab by index\nagent-browser tab 2\n\n# Switch by URL pattern\nagent-browser tab --url \"*settings*\"\n```\n\n## Launching VS Code Extensions for Debugging\n\nTo debug a VS Code extension via agent-browser, launch VS Code Insiders with `--extensionDevelopmentPath` pointing to your extension source and `--remote-debugging-port` for CDP. Use `--user-data-dir` to avoid conflicting with an already-running VS Code instance.\n\n```bash\n# Build the extension first (from the repo root)\nnpm run compile\n\n# Launch VS Code Insiders with the extension and CDP\n# IMPORTANT: Use a persistent directory (not \u002Ftmp) so auth state is preserved.\n# .vscode-ext-debug is relative to the project root — works in worktrees and is gitignored.\ncode-insiders \\\n  --extensionDevelopmentPath=\"$PWD\" \\\n  --remote-debugging-port=9223 \\\n  --user-data-dir=\"$PWD\u002F.vscode-ext-debug\"\n\n# Wait for VS Code to start, retry until connected\nfor i in 1 2 3 4 5; do agent-browser connect 9223 2>\u002Fdev\u002Fnull && break || sleep 3; done\n\n# Verify you're connected to the right target (not about:blank)\n# If `tab` shows the wrong target, run `agent-browser close` and reconnect\nagent-browser tab\nagent-browser snapshot -i\n```\n\n**Key flags:**\n- `--extensionDevelopmentPath=\u003Cpath>` — loads your extension from source (must be compiled first). Use `$PWD` when running from the repo root.\n- `--remote-debugging-port=9223` — enables CDP (use 9223 to avoid conflicts with other apps on 9222)\n- `--user-data-dir=\u003Cpath>` — uses a separate profile so it starts a new process instead of sending to an existing VS Code instance. **Always use a persistent path** (e.g., `$PWD\u002F.vscode-ext-debug`) rather than `\u002Ftmp\u002F...` so authentication, settings, and extension state survive across sessions.\n\n**Without `--user-data-dir`**, VS Code detects the running instance, forwards the args to it, and exits immediately — you'll see \"Sent env to running instance. Terminating...\" and CDP never starts.\n\n> **⚠️ Authentication is required.** The Copilot Chat extension needs an authenticated GitHub session to function. Using a temp directory (e.g., `\u002Ftmp\u002F...`) creates a fresh profile with no auth — the agent will hit a \"Sign in to use Copilot\" wall and model resolution will fail with \"Language model unavailable.\"\n>\n> **Always use a persistent `--user-data-dir`** like `$PWD\u002F.vscode-ext-debug`. On first use, launch once and sign in manually. Subsequent launches will reuse the auth session.\n\n## Restarting After Code Changes\n\n**After making changes to the extension source code, you must restart VS Code to pick up the new build.** The extension host loads the compiled bundle at startup — changes are not hot-reloaded.\n\n### Restart Workflow\n\n1. **Recompile** the extension\n2. **Kill** the running VS Code instance (the one using your debug user-data-dir)\n3. **Relaunch** VS Code with the same flags\n\n```bash\n# 1. Recompile\nnpm run compile\n\n# 2. Kill the VS Code instance tied to this project's debug profile, then relaunch\n# macOS \u002F Linux:\nkill $(ps ax -ww -o pid,command | grep \"$PWD\u002F.vscode-ext-debug\" | grep -v grep | awk '{print $1}' | head -1)\n\n# Windows (PowerShell):\n# Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like \"*$PWD\\.vscode-ext-debug*\" } | ForEach-Object { Stop-Process -Id $_.ProcessId }\n\n# 3. Relaunch\ncode-insiders \\\n  --extensionDevelopmentPath=\"$PWD\" \\\n  --remote-debugging-port=9223 \\\n  --user-data-dir=\"$PWD\u002F.vscode-ext-debug\"\n\n# 4. Reconnect agent-browser\nfor i in 1 2 3 4 5; do agent-browser connect 9223 2>\u002Fdev\u002Fnull && break || sleep 3; done\nagent-browser snapshot -i\n```\n\n> **Tip:** If you're iterating frequently, run `npm run watch` in a separate terminal so compilation happens automatically. You still need to kill and relaunch VS Code to load the new bundle.\n\n## Interacting with Monaco Editor (Chat Input, Code Editors)\n\nVS Code uses Monaco Editor for all text inputs including the Copilot Chat input. Monaco editors appear as textboxes in the accessibility snapshot but require specific agent-browser commands to interact with.\n\n### What Works\n\n#### `type @ref` — The Best Approach\n\nThe `type` command with a snapshot ref handles focus and input in one step:\n\n```bash\n# Snapshot to find the chat input ref\nagent-browser snapshot -i\n# Look for: textbox \"The editor is not accessible...\" [ref=e51]\n\n# Type directly using the ref — handles focus automatically\nagent-browser type @e51 \"Hello from George!\"\n\n# Send the message\nagent-browser press Enter\n\n# Wait for the response to complete before re-snapshotting.\n# Poll until the \"Stop generating\" button disappears:\nfor i in $(seq 1 30); do\n  agent-browser snapshot -i 2>\u002Fdev\u002Fnull | grep -q \"Stop generating\" || break\n  sleep 1\ndone\nagent-browser snapshot -i\n```\n\nThis is the simplest and most reliable method. It works for both the main editor chat input and the sidebar chat panel.\n\n> **Tip:** If `type @ref` silently drops text (the editor stays empty), the ref may be stale or the editor not yet ready. Re-snapshot to get a fresh ref and try again. You can verify text was entered using the snippet in \"Verifying Text in Monaco\" below.\n\n#### `keyboard type` \u002F `keyboard inserttext` — After Focus\n\nIf focus is already on a Monaco editor, `keyboard type` and `keyboard inserttext` both work:\n\n> **⚠️ Warning:** `keyboard type` can hang indefinitely in some focus states (e.g., after JS mouse events). If it doesn't return within a few seconds, interrupt it and fall back to `press` for individual keystrokes.\n\n```bash\n# Focus first (via type @ref, or JS mouse events, or a prior interaction)\nagent-browser type @e51 \"\"\n# Then keyboard type works for subsequent input\nagent-browser keyboard type \"More text here\"\nagent-browser keyboard inserttext \"And this too\"\n```\n\n#### `press` — Individual Keystrokes\n\nAlways works when focus is on a Monaco editor. Useful for special keys, keyboard shortcuts, and as a universal fallback for typing text character by character:\n\n```bash\n# Type text character by character (works on all builds)\nagent-browser press H\nagent-browser press e\nagent-browser press l\nagent-browser press l\nagent-browser press o\nagent-browser press Space  # Use \"Space\" for spaces\n\n# Select all\n# macOS:\nagent-browser press Meta+a\n# Linux \u002F Windows:\nagent-browser press Control+a\n\nagent-browser press Backspace    # Delete selection\nagent-browser press Enter        # Send message \u002F new line\n\n# Send to new chat\n# macOS:\nagent-browser press Meta+Shift+Enter\n# Linux \u002F Windows:\nagent-browser press Control+Shift+Enter\n```\n\n### What Does NOT Work\n\n| Method | Result | Reason |\n|--------|--------|--------|\n| `click @ref` | \"Element blocked by another element\" | Monaco overlays a transparent div over the textarea |\n| `fill @ref \"text\"` | \"Element not found or not visible\" | The textbox is not a standard fillable input |\n| `document.execCommand(\"insertText\")` via `eval` | No effect | Monaco intercepts and discards execCommand |\n| Setting `textarea.value` + dispatching `input` event via `eval` | No effect | Monaco doesn't read from the textarea's value property |\n\n### Fallback: Focus via JavaScript Mouse Events\n\nIf `type @ref` doesn't work (e.g., ref is stale), you can focus the editor via JavaScript:\n\n```bash\nagent-browser eval '\n(() => {\n  const inputPart = document.querySelector(\".interactive-input-part\");\n  const editor = inputPart.querySelector(\".monaco-editor\");\n  const rect = editor.getBoundingClientRect();\n  const x = rect.x + rect.width \u002F 2;\n  const y = rect.y + rect.height \u002F 2;\n  editor.dispatchEvent(new MouseEvent(\"mousedown\", { bubbles: true, clientX: x, clientY: y }));\n  editor.dispatchEvent(new MouseEvent(\"mouseup\", { bubbles: true, clientX: x, clientY: y }));\n  editor.dispatchEvent(new MouseEvent(\"click\", { bubbles: true, clientX: x, clientY: y }));\n  return \"activeElement: \" + document.activeElement?.className;\n})()'\n\n# After JS focus, keyboard type and press work\nagent-browser keyboard type \"Text after JS focus\"\n```\n\nAfter JS mouse events, `document.activeElement` becomes a `DIV` with class `native-edit-context` — this is VS Code's native text editing surface.\n\n### Verifying Text in Monaco\n\nMonaco renders text in `.view-line` elements, not the textarea:\n\n```bash\nagent-browser eval '\n(() => {\n  const inputPart = document.querySelector(\".interactive-input-part\");\n  return Array.from(inputPart.querySelectorAll(\".view-line\")).map(vl => vl.textContent).join(\"|\");\n})()'\n```\n\n### Clearing Monaco Input\n\n```bash\n# macOS:\nagent-browser press Meta+a\n# Linux \u002F Windows:\nagent-browser press Control+a\n\nagent-browser press Backspace\n```\n\n## Troubleshooting\n\n### \"Connection refused\" or \"Cannot connect\"\n\n- Make sure VS Code Insiders was launched with `--remote-debugging-port=9223`\n- If VS Code was already running, quit and relaunch with the flag\n- Check that the port isn't in use by another process:\n  - macOS \u002F Linux: `lsof -i :9223`\n  - Windows: `netstat -ano | findstr 9223`\n\n### Elements not appearing in snapshot\n\n- VS Code uses multiple webviews. Use `agent-browser tab` to list targets and switch to the right one\n- Use `agent-browser snapshot -i -C` to include cursor-interactive elements (divs with onclick handlers)\n\n### Cannot type in Monaco inputs\n\n- Standard `click` and `fill` don't work on Monaco editors — see the \"Interacting with Monaco Editor\" section above for the full compatibility matrix\n- `type @ref` is the best approach; individual `press` commands work everywhere; `keyboard type` and `keyboard inserttext` work after focus is established\n\n### Screenshots fail with \"Permission denied\" (macOS)\n\nIf `agent-browser screenshot` returns \"Permission denied\", your terminal needs Screen Recording permission. Grant it in **System Settings → Privacy & Security → Screen Recording**. As a fallback, use the `eval` verification snippet to confirm text was entered — this doesn't require screen permissions.\n\n## Cleanup\n\n**Always kill the debug VS Code instance when you're done.** Leaving it running wastes resources and holds the CDP port.\n\n```bash\n# Disconnect agent-browser\nagent-browser close\n\n# Kill the debug VS Code instance\n# macOS \u002F Linux:\nkill $(ps ax -ww -o pid,command | grep \"$PWD\u002F.vscode-ext-debug\" | grep -v grep | awk '{print $1}' | head -1)\n\n# Windows (PowerShell):\n# Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like \"*$PWD\\.vscode-ext-debug*\" } | ForEach-Object { Stop-Process -Id $_.ProcessId }\n```",{"name":5,"metadata":36,"description":7},{"allowed-tools":37},"Bash(agent-browser:*), Bash(npx agent-browser:*)","main","0979439a7a0806abd0ee48c2619b37f297ae1324",".github\u002Fskills\u002Flaunch-vscode-extension",77,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-12 01:21:10",{"source":8,"skillName":5,"commands":48,"prompt":58,"zipAvailable":59},[49,52,55],{"tool":50,"command":51},"npx","npx skills add microsoft\u002Frayfin --skill launch-vscode-extension",{"tool":53,"command":54},"bunx","bunx skills add microsoft\u002Frayfin --skill launch-vscode-extension",{"tool":56,"command":57},"pnpm","pnpm dlx skills add microsoft\u002Frayfin --skill launch-vscode-extension","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Flaunch-vscode-extension\u002FSKILL.md",true,[],[62,75,93,102,121,129],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":68,"publishedAt":31},"01M699YEY2QDVPKTZS3HR9AX84","rayfin-getting-started","Use when starting or creating a NEW Rayfin app, or when a Rayfin task comes up and you are not yet inside a Rayfin project. Gets you into a project with the Rayfin CLI, then hands off to the authoritative, version-locked in-project rayfin skill\u002Fdocs that own all in-project work. Triggers: build a Rayfin app, start a Rayfin project, create a new Rayfin app, create-rayfin, npm create @microsoft\u002Frayfin, rayfin init, scaffold rayfin, rayfin CLI, rayfin template, universal app, awesome-rayfin gallery, get started with Rayfin","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin\u002Fblob\u002Fmain\u002Fskills\u002Frayfin-getting-started\u002FSKILL.md",[],[69,70,71,72,9,73,74],"rayfin getting started","rayfin","scaffold","init","docs","cli",{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":89,"publishedAt":31},"01M699YCN4ZDW2AMDP4NVJ2QGC","visuals","Use when user wants to incorporate charts, graphs, data grid,  or other visual representations of data into their project. Use VegaVisual and DataGrid components to create these visuals,  utilizing the shared DataTable input, formatting, theme, and interactivity. Covers the onInteraction selection\u002Fclick events host apps consume, named multi-table data input for layered overlays and reference lines, and Vega-Lite native selections. Triggers: chart, graph, plot, dashboard, KPI, metric, trend, scorecard, data grid, visualize.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin\u002Fblob\u002Fmain\u002Fsamples\u002Funiversal-app\u002Ftemplate\u002F.agents\u002Fskills\u002Fvisuals\u002FSKILL.md",[81,84],{"categoryNo":82,"categoryName":83,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000013","分析与可视化",{"categoryNo":85,"categoryName":86,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[77,90,91,92],"components","dashboard","visualize",{"skillNo":94,"name":95,"nameZh":6,"description":96,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":99,"publishedAt":31},"01M699YBEP146MJZJNN8YEBZ2G","schema-discovery","Explore Power BI semantic model schemas using DAX INFO functions. Progressive metadata discovery strategy, scope estimation, and narrowing techniques for tables, columns, measures, and relationships.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin\u002Fblob\u002Fmain\u002Fsamples\u002Funiversal-app\u002Ftemplate\u002F.agents\u002Fskills\u002Fschema-discovery\u002FSKILL.md",[],[100,101],"schema discovery","dax",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":117,"publishedAt":31},"01M699Y9E80WYFKD1S4MT4B1CS","query-design","Separates DAX data-fetching from TypeScript presentation. Guides when to use  DAX vs. TypeScript vs. Vega-Lite for aggregation, total rows, FORMAT(), SELECTCOLUMNS,  BLANK handling, filtering, multi-grain queries, cross-filtering and cross-highlight subset\u002Foverlay queries, and format strings.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin\u002Fblob\u002Fmain\u002Fsamples\u002Funiversal-app\u002Ftemplate\u002F.agents\u002Fskills\u002Fquery-design\u002FSKILL.md",[108,111,114],{"categoryNo":109,"categoryName":110,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000003","演示文稿",{"categoryNo":112,"categoryName":113,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":115,"categoryName":116,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000032","设计师",[118,119,101,120],"query design","design","typescript",{"skillNo":122,"name":123,"nameZh":6,"description":124,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":125,"categories":126,"keywords":127,"publishedAt":31},"01M699Y7CKZ55QSYFE827RRVJE","functions-capability","Apply and build the Universal App functions capability. Use for trusted server-side logic, secrets, external APIs, custom model endpoints, published Fabric data agents, webhooks, or privileged operations.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin\u002Fblob\u002Fmain\u002Fsamples\u002Funiversal-app\u002Ftemplate\u002F.agents\u002Fskills\u002Ffunctions-capability\u002FSKILL.md",[],[128],"functions capability",{"skillNo":130,"name":131,"nameZh":6,"description":132,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":133,"categories":134,"keywords":135,"publishedAt":31},"01M699Y5R87YE620T78Z30KQSA","fabric-sdk","How to query Fabric data from a running app through the Rayfin connectors client. Use getRayfinClient().connectors.\u003Cname>.executeQuery to run DAX against a semantic model, and toQueryResult to normalize the response.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frayfin\u002Fblob\u002Fmain\u002Fsamples\u002Funiversal-app\u002Ftemplate\u002F.agents\u002Fskills\u002Ffabric-sdk\u002FSKILL.md",[],[136,137,101,138,70,139],"sdk","fabric sdk","rayfin connectors","connectors"]