Imported from edrouhardmicrosoft/agent-canvas-skills (
docs/AGENTS.md). Install upstream withnpx skills add edrouhardmicrosoft/agent-canvas-skills --skill docs. Copyright stays with the author.
Agent Canvas Skills - AI Agent Reference
Quick reference for AI agents to navigate and use canvas skills effectively.
Skill Selection Guide
| User Intent | Skill to Use | Command |
|---|---|---|
| Review design against spec | design-review |
uv run .claude/skills/design-review/scripts/design_review.py review <url> |
| Compare to reference image | design-review |
uv run .claude/skills/design-review/scripts/design_review.py compare <url> --reference <img> |
| See the page / take screenshot | agent-eyes |
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py screenshot <url> |
| Check accessibility issues | agent-eyes |
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py a11y <url> |
| Select an element interactively | agent-canvas |
uv run .claude/skills/agent-canvas/scripts/agent_canvas.py pick <url> |
| Edit styles/text visually | agent-canvas |
uv run .claude/skills/agent-canvas/scripts/agent_canvas.py pick <url> --with-edit |
| Show annotation overlay | canvas-edit |
uv run .claude/skills/canvas-edit/scripts/canvas_edit.py inject <url> --issues <json> |
| Apply visual edits to code | canvas-apply |
python3 .claude/skills/canvas-apply/scripts/canvas_apply.py <sessionId> --apply |
| Verify changes worked | canvas-verify |
uv run .claude/skills/canvas-verify/scripts/canvas_verify.py <url> --session <sessionId> |
| Skills not working / first use | agent-canvas-setup |
uv run .claude/skills/agent-canvas-setup/scripts/check_setup.py check |
Trigger Phrases
agent-canvas-setup
- "setup agent canvas"
- "install canvas dependencies"
- "canvas not working"
- "playwright not found"
- "first time setup"
agent-eyes
- "take a screenshot"
- "check accessibility"
- "what does this page look like"
- "analyze the UI"
- "inspect this element"
- "run a11y scan"
- "get DOM snapshot"
agent-canvas
- "select an element"
- "pick element"
- "let me choose"
- "which element"
- "interactive selection"
canvas-edit
- "show annotations"
- "display issues"
- "annotate page"
- "overlay findings"
- "inject annotations"
- "show review results"
canvas-apply
- "apply canvas changes"
- "apply session"
- "convert edits to code"
- "apply visual edits"
canvas-verify
- "verify canvas changes"
- "verify session"
- "check if changes worked"
- "compare before and after"
- "run verification"
design-review
- "review design"
- "check compliance"
- "design audit"
- "spec review"
- "check against spec"
- "compare to reference"
- "design QA"
Command Quick Reference
design-review
# Full review against default spec
uv run .claude/skills/design-review/scripts/design_review.py review <url>
# With annotated screenshot
uv run .claude/skills/design-review/scripts/design_review.py review <url> --annotate
# Compact mode (token-efficient, for AI agents)
uv run .claude/skills/design-review/scripts/design_review.py review <url> --compact
# Generate task list
uv run .claude/skills/design-review/scripts/design_review.py review <url> --generate-tasks
# Compare to reference image
uv run .claude/skills/design-review/scripts/design_review.py compare <url> --reference <image>
# Compare in compact mode
uv run .claude/skills/design-review/scripts/design_review.py compare <url> --reference <image> --compact
Standard output format:
{
"ok": true,
"sessionId": "review_...",
"summary": {"blocking": 1, "major": 3, "minor": 2},
"issues": [...],
"editableContext": {...},
"artifacts": {
"screenshot": "path/to/screenshot.png",
"sessionDir": "path/to/session"
}
}
Compact output format (--compact):
{
"ok": true,
"sessionId": "review_...",
"summary": {"blocking": 1, "major": 3, "minor": 2},
"issues": [
{
"id": 1,
"checkId": "color-contrast",
"severity": "major",
"element": ".subtitle-text",
"description": "Contrast 3.2:1 < 4.5:1"
}
],
"artifacts": {
"screenshot": "path/to/screenshot.png"
}
}
Compact mode benefits:
- ~2K tokens instead of ~10K+ tokens
- No
editableContext,details,nodes,recommendationfields - Descriptions truncated to 100 chars
- Skips writing full session files
agent-canvas-setup
# Check dependencies
uv run .claude/skills/agent-canvas-setup/scripts/check_setup.py check
# Install (recommended scope)
uv run .claude/skills/agent-canvas-setup/scripts/check_setup.py install --scope temporary
Exit codes: 0 = ready, 1 = needs setup
agent-eyes
# Screenshot
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py screenshot <url>
# Screenshot in compact mode (returns path, not base64)
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py screenshot <url> --compact
# Accessibility scan
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py a11y <url>
# Full context (screenshot + a11y + DOM)
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py context <url>
# Full context in compact mode (token-efficient)
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py context <url> --compact
# Element description
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py describe <url> --selector "<selector>"
Standard output format:
{
"ok": true,
"screenshot": "path/to/file.png",
"violations": [...],
"dom": {...}
}
Compact mode (--compact):
- Screenshots saved to file, path returned (no base64)
- DOM depth limited to 3 (vs 5)
- Max children per node: 10 (vs 20)
- Max a11y issues: 3 (vs 10)
- Text truncated to 50 chars (vs 100)
---
### agent-canvas
```bash
# Basic pick
uv run .claude/skills/agent-canvas/scripts/agent_canvas.py pick <url>
# Full workflow (RECOMMENDED)
uv run .claude/skills/agent-canvas/scripts/agent_canvas.py pick <url> --with-edit --with-eyes
# Auto-apply after editing
uv run .claude/skills/agent-canvas/scripts/agent_canvas.py pick <url> --with-edit --with-eyes --auto-apply --auto-verify
Output format (JSON lines):
{"event": "session_started", "sessionId": "ses-abc123", "url": "..."}
{"event": "selection", "index": 1, "element": {"tag": "button", "selector": "#submit"}}
{"event": "style_change", "selector": "#submit", "property": "color", "newValue": "#ff0000"}
{"event": "save_request", "changes": {...}}
{"event": "session_ended", "total_selections": 1, "total_edits": 2}
canvas-edit
SKILL_DIR=".claude/skills/canvas-edit/scripts"
# Inject annotations from issues JSON file
uv run $SKILL_DIR/canvas_edit.py inject <url> --issues issues.json
# Inject with auto-screenshot
uv run $SKILL_DIR/canvas_edit.py inject <url> --issues issues.json --screenshot
# Pipe issues from stdin
echo '[{"id": 1, "selector": "h1", "severity": "major", "title": "Issue"}]' | \
uv run $SKILL_DIR/canvas_edit.py inject <url> --issues -
Issue JSON format:
[
{
"id": 1,
"selector": ".hero-title",
"severity": "major",
"title": "Contrast ratio insufficient",
"description": "Text contrast 3.2:1 fails WCAG AA",
"pillar": "Quality Craft",
"recommendation": "Use darker text color"
}
]
Screenshot output: .canvas/screenshots/YYYY-MM-DDTHH-MM-SS_N-issues.png
Note: Canvas-edit was redesigned from a style editor to an annotation viewer. For live style/text editing, use
agent-canvas --with-edit.
canvas-apply
# List sessions
python3 .claude/skills/canvas-apply/scripts/canvas_apply.py --list
# Preview changes
python3 .claude/skills/canvas-apply/scripts/canvas_apply.py <sessionId>
# Show diff
python3 .claude/skills/canvas-apply/scripts/canvas_apply.py <sessionId> --diff
# Apply changes
python3 .claude/skills/canvas-apply/scripts/canvas_apply.py <sessionId> --apply
# Force apply (ignore low confidence)
python3 .claude/skills/canvas-apply/scripts/canvas_apply.py <sessionId> --apply --force
Output format (--json):
{
"sessionId": "ses-abc123",
"fileDiffs": [
{"filePath": "app/page.tsx", "confidence": 0.95, "changes": [...]}
],
"unmappedChanges": [],
"warnings": []
}
Confidence thresholds: <70% = warning, use --force to override
canvas-verify
# Full verification
uv run .claude/skills/canvas-verify/scripts/canvas_verify.py <url> --session <sessionId>
# Visual only
uv run .claude/skills/canvas-verify/scripts/canvas_verify.py <url> --session <sessionId> --visual
# A11y only
uv run .claude/skills/canvas-verify/scripts/canvas_verify.py <url> --session <sessionId> --a11y
# List sessions
uv run .claude/skills/canvas-verify/scripts/canvas_verify.py --list
Output format (--json):
{
"ok": true,
"sessionId": "ses-abc123",
"verification": {
"visual": {"status": "pass", "diffPercentage": 2.3},
"a11y": {"status": "pass", "fixed": [...], "introduced": []}
},
"overallStatus": "pass"
}
Exit codes: 0 = pass, 1 = fail
Workflow Sequences
Workflow 1: Full Visual Edit Cycle
# 1. Check setup (first time only)
uv run .claude/skills/agent-canvas-setup/scripts/check_setup.py check
# 2. Pick element and edit visually
uv run .claude/skills/agent-canvas/scripts/agent_canvas.py pick http://localhost:3000 --with-edit --with-eyes
# User makes changes, clicks "Save All to Code", closes browser
# 3. Read the session from disk (NOT stdout!)
SESSION_ID=$(ls -t .canvas/sessions/ | head -1)
echo "Session: $SESSION_ID"
# 4. Check if user saved changes
HAS_SAVE=$(cat .canvas/sessions/$SESSION_ID/session.json | jq -r '.summary.hasSaveRequest')
if [ "$HAS_SAVE" = "false" ]; then
echo "No changes to apply - user didn't click 'Save All to Code'"
exit 0
fi
# 5. Apply changes to source files
python3 .claude/skills/canvas-apply/scripts/canvas_apply.py $SESSION_ID --apply
# 6. Verify changes worked
uv run .claude/skills/canvas-verify/scripts/canvas_verify.py http://localhost:3000 --session $SESSION_ID
Workflow 2: Accessibility Analysis
# 1. Scan for violations
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py a11y http://localhost:3000
# 2. Parse violations array, make code fixes
# 3. Re-scan to verify fixes
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py a11y http://localhost:3000
Workflow 3: Quick Screenshot for Context
uv run .claude/skills/agent-eyes/scripts/agent_eyes.py screenshot http://localhost:3000
Workflow 4: Automated CI Pipeline
# Full automation - opens browser, applies, verifies
uv run .claude/skills/agent-canvas/scripts/agent_canvas.py pick http://localhost:3000 \
--with-edit --with-eyes --auto-apply --auto-verify
Output Parsing Guide
Key Fields to Check
| Field | Meaning | Action |
|---|---|---|
ok: true/false |
Command success | If false, check error field |
sessionId |
Session identifier | Pass to canvas-apply and canvas-verify |
violations[] |
A11y issues found | Parse and fix each violation |
confidence |
Match certainty (0-1) | Warn user if <0.70 |
overallStatus |
Verification result | "pass" or "fail" |
diffPercentage |
Visual change amount | Higher = more changed |
Parsing Examples
Check if command succeeded:
result = json.loads(output)
if not result.get("ok", False):
print(f"Error: {result.get('error')}")
Extract sessionId from agent-canvas:
for line in output.splitlines():
event = json.loads(line)
if event.get("event") == "session_started":
session_id = event["sessionId"]
Check verification passed:
result = json.loads(output)
if result["overallStatus"] == "pass":
print("Changes verified successfully")
Error Handling
| Error | Cause | Solution |
|---|---|---|
Playwright not found |
Missing browser | Run agent-canvas-setup |
Session not found |
Invalid sessionId | Use --list to find valid sessions |
Low confidence warning |
Uncertain file match | Use --force or improve selectors |
No beforeScreenshot |
Incomplete session | Re-run canvas session with --with-eyes |
uv not found |
Missing package manager | Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh |
Connection refused |
Dev server not running | Start with npm run dev |
Best Practices for Agents
- Always check setup first - Run
check_setup.py checkbefore first canvas operation - Use full flags for context -
--with-edit --with-eyesprovides maximum information - Read sessions from disk, not stdout - Sessions are saved to
.canvas/sessions/automatically - Parse JSON output - Don't rely on text output; use
--jsonflag when available - Track sessionId - Pass it consistently from agent-canvas to canvas-apply to canvas-verify
- Verify after apply - Always run canvas-verify to confirm changes worked
- Watch confidence scores - Warn users about low-confidence matches (<70%)
- Handle errors gracefully - Check
okfield and provide helpful messages on failure - Check hasSaveRequest - If
false, user didn't click "Save All to Code" and there's nothing to apply
Reading Session Artifacts (CRITICAL)
Do NOT rely on capturing stdout from agent-canvas commands. Sessions are automatically saved to disk.
After Browser Closes
# Find the latest session
SESSION_ID=$(ls -t .canvas/sessions/ | head -1)
# Quick summary
cat .canvas/sessions/$SESSION_ID/session.json | jq '.summary'
# Check if changes were saved (required for apply workflow)
cat .canvas/sessions/$SESSION_ID/session.json | jq '.summary.hasSaveRequest'
# See what elements were selected
cat .canvas/sessions/$SESSION_ID/session.json | jq '.events.selections[] | {selector: .payload.element.selector, text: .payload.element.text}'
# See edit events
cat .canvas/sessions/$SESSION_ID/session.json | jq '.events.edits'
Important: hasSaveRequest
Before running canvas-apply, always check if the user clicked "Save All to Code":
HAS_SAVE=$(cat .canvas/sessions/$SESSION_ID/session.json | jq -r '.summary.hasSaveRequest')
if [ "$HAS_SAVE" = "false" ]; then
echo "No changes to apply - user didn't click 'Save All to Code'"
fi
Session Artifacts
Sessions are stored in .canvas/sessions/<sessionId>/:
.canvas/sessions/
└── ses-abc123/
├── session.json # Full event log + metadata
└── changes.json # Extracted save_request data
Session JSON structure:
{
"sessionId": "ses-abc123",
"url": "http://localhost:3000",
"startTime": "2026-01-21T15:30:45.123Z",
"features": {"withEdit": true, "withEyes": true},
"beforeScreenshot": "data:image/png;base64,...",
"events": [...]
}
Quick Paths
# Skills directory
.claude/skills/
# Session artifacts
.canvas/sessions/
# Screenshots
.canvas/screenshots/