Demo Vscode
demo-vscode
Capture 3 screenshots for a tip page — two card captures from the website + a VS Code demo. Trigger: /demo-vscode <tip-url>
SKILL.md
Full skill instructions
IMPORTANT: VS Code Ownership
Before starting, tell the user:
This skill will take full control of your VS Code window for screenshot capture. Do NOT interact with VS Code while this is running — any clicks or keystrokes will break the automation. Work in a different app (browser, other terminal) while this runs.
Goal
Produce 3 screenshot images for a developer tip page, ready to share on Slack:
- Insights card — Key Insights block from the tip page
- Actions card — Action Items block from the tip page
- VS Code demo — Live demonstration of the tip concept in VS Code
Flow
digraph demo_vscode {
"Parse URL & derive slug" [shape=box];
"Navigate to tip page" [shape=box];
"Wait for page load" [shape=box];
"Extract block text" [shape=box];
"Screenshot block 1" [shape=box];
"Screenshot block 2" [shape=box];
"Spawn demo-planner" [shape=box];
"Plan valid?" [shape=diamond];
"Execute VS Code demo" [shape=box];
"Screenshot VS Code" [shape=box];
"Report" [shape=doublecircle];
"Parse URL & derive slug" -> "Navigate to tip page";
"Navigate to tip page" -> "Wait for page load";
"Wait for page load" -> "Extract block text";
"Extract block text" -> "Screenshot block 1";
"Screenshot block 1" -> "Screenshot block 2";
"Screenshot block 2" -> "Spawn demo-planner";
"Spawn demo-planner" -> "Plan valid?";
"Plan valid?" -> "Execute VS Code demo" [label="yes"];
"Plan valid?" -> "Spawn demo-planner" [label="retry (max 2)"];
"Execute VS Code demo" -> "Screenshot VS Code";
"Screenshot VS Code" -> "Report";
}
Node Details
Parse URL & derive slug
Extract the slug from the URL path. Example:
- URL:
https://easingthemes.github.io/dx-aem-flow/learn/tldr/the-three-tools-you-need-to-know/ - Slug:
the-three-tools-you-need-to-know
Create output directory: tools/screenshots/<slug>/
Navigate to tip page
mcp__playwright__browser_navigate(url: "<tip-url>")
Wait for page load
Wait for the tip blocks to render. Playwright's browser_wait_for waits on text / textGone / time (seconds) — not a CSS selector. Wait for visible tip-card text, or fall back to a short settle:
mcp__playwright__browser_wait_for(text: "<a phrase visible in the tip card>")
Extract block text
Use browser_evaluate to get the text content from both tip blocks. Both cards have the tip-block class — first is insights, second is actions.
mcp__playwright__browser_evaluate(
function: "() => {
const blocks = document.querySelectorAll('.tip-block');
return {
insights: blocks[0]?.innerText || '',
actions: blocks[1]?.innerText || '',
focus: blocks[0]?.querySelector('[class*=bg-cyan]')?.innerText || 'All Tools'
};
}"
)
Save the extracted text — it becomes the input for the planner.
Screenshot block 1
Inject ARIA attributes so .tip-block divs appear in the a11y tree with refs:
mcp__playwright__browser_evaluate(
function: "() => {
const blocks = document.querySelectorAll('.tip-block');
blocks[0]?.setAttribute('role', 'region');
blocks[0]?.setAttribute('aria-label', 'tip-insights');
blocks[1]?.setAttribute('role', 'region');
blocks[1]?.setAttribute('aria-label', 'tip-actions');
return blocks.length;
}"
)
Take a snapshot to get refs — look for region "tip-insights" and region "tip-actions":
mcp__playwright__browser_snapshot()
Screenshot each block by ref (element screenshot needs element + ref). browser_take_screenshot saves a filename basename under the Playwright MCP output dir — copy it to the target path afterward:
mcp__playwright__browser_take_screenshot(
element: "tip insights card",
ref: "<tip-insights-ref>",
filename: "<slug>-insights.png"
)
# then: cp <playwright-output-dir>/<slug>-insights.png tools/screenshots/<slug>/<slug>-insights.png
Screenshot block 2
mcp__playwright__browser_take_screenshot(
element: "tip actions card",
ref: "<tip-actions-ref>",
filename: "<slug>-actions.png"
)
# then: cp <playwright-output-dir>/<slug>-actions.png tools/screenshots/<slug>/<slug>-actions.png
Spawn demo-planner
Spawn the demo-planner agent with the extracted block text:
Agent(
subagent_type: "demo-planner",
prompt: "Plan a VS Code demo for this tip.
Block 1 (Key Insights):
<insights text>
Block 2 (Action Items):
<actions text>
Focus: <focus value>
Return the demo plan in the specified format."
)
Plan valid?
The planner returns a structured plan. Validate:
- Has at least 1 action
- Every
type:action hasenter: true - Wait times are reasonable (1-30s each, total under 120s)
- Prompts are under 80 chars
- At least one tool matches the focus
If invalid, retry with feedback (max 2 retries).
Execute VS Code demo
Execute the plan actions sequentially using vscode-automator MCP tools.
VS Code Layout
VS Code has two distinct areas for running AI tools:
- Terminal Panel (bottom) — standard integrated terminal. Claude Code runs here.
- Editor Area (top/main) — where files and editor tabs live. Copilot CLI opens here via Command Palette.
- Chat Panel (side panel) — VS Code Chat / Copilot Chat. Separate from both terminal and editor.
Verified Execution Sequence
CRITICAL RULES:
typeandkeystroke(enter)must be back-to-back — NO intervening tool calls- Always wait 1s after focus switch before typing (AppleScript race condition)
- Each tool needs a FRESH session — don't reuse existing ones
- Clear input before typing:
Ctrl+E→Ctrl+U(readline fields only, NOT VS Code Chat)
Step-by-step (order matters):
1. vscode_focus()
2. vscode_command("Chat: New CLI Session to the Side") → fresh Copilot CLI in Editor Area
3. wait 5s (Copilot CLI init)
4. Ctrl+E → Ctrl+U → clear any leftover input
5. type "<copilot prompt>" + enter → Copilot CLI working
6. vscode_new_terminal() → fresh terminal
7. wait 1s
8. type "claude" + enter → Claude Code launching
9. wait 12s (init + MCP servers)
10. type "<claude prompt>" + enter → Claude Code working
11. Cmd+Shift+I → focus VS Code Chat
12. wait 1s
13. Cmd+N → NEW chat session (clean input)
14. wait 1s
15. type "<chat prompt>" + enter → Chat working
16. wait 30s → ALL THREE respond in parallel
17. vscode_screenshot
Focus Switching (for additional prompts after initial setup)
| Tool | Focus command | Wait | Clear input |
|---|---|---|---|
| Copilot CLI | vscode_command("View: Focus First Editor Group") | 1s | Ctrl+E → Ctrl+U |
| Claude Code | vscode_keystroke(key: "\", modifiers: ["control"])` | 1s | Ctrl+E → Ctrl+U |
| VS Code Chat | vscode_keystroke(key: "i", modifiers: ["command", "shift"]) | 1s | Cmd+N (new chat, not clear) |
Action Mapping (from planner output)
| Plan action | MCP calls |
|---|---|
open_copilot_cli | vscode_command("Chat: New CLI Session to the Side") |
new_terminal | vscode_new_terminal() |
new_chat | Cmd+Shift+I → wait 1s → Cmd+N → wait 1s |
focus_copilot | vscode_command("View: Focus First Editor Group") → wait 1s |
focus_terminal | Ctrl+backtick → wait 1s |
focus_chat | Cmd+Shift+I → wait 1s |
clear_input | Ctrl+E → Ctrl+U (terminal/CLI only) |
type: "text" | enter: true | vscode_type(text) then IMMEDIATELY vscode_keystroke(key: "enter") |
wait: N | vscode_wait(seconds: N) |
After all actions + final wait from the plan:
- Proceed to screenshot
Screenshot VS Code
mcp__vscode-automator__vscode_screenshot(
output_path: "tools/screenshots/<slug>/<slug>-demo.png"
)
Report
Print a summary with the 3 image paths:
## Screenshots Ready
| Image | Path |
|-------|------|
| Insights card | `tools/screenshots/<slug>/<slug>-insights.png` |
| Actions card | `tools/screenshots/<slug>/<slug>-actions.png` |
| VS Code demo | `tools/screenshots/<slug>/<slug>-demo.png` |
Ready to share on Slack.
