Miro Board Connector
Connect to a Miro board via OAuth, inspect board items, and download full-size images by spatial region.
Bundle Layout
SKILL.md: primary workflowscripts/miro_api.py: OAuth + board inspection + image download helperCODEX_BOOTSTRAP.md: Codex-specific activation notesCLAUDE_BOOTSTRAP.md: Claude Code-specific activation notesOPENCLAW_BOOTSTRAP.md: OpenClaw-specific activation notes
Run commands from the installed skill directory so relative paths like scripts/miro_api.py resolve correctly.
Setup Flow
Step 1: Check for existing token
test -f ~/.miro-token && echo "Miro token file found" || echo "No Miro token file yet"If a token exists, test it:
python3 scripts/miro_api.py test-tokenIf valid, skip to Step 3. If expired or missing, continue.
Step 2: OAuth Setup
The user needs a Miro app with boards:read and boards:write scopes. Guide them:
- Go to https://miro.com/app/settings/user-profile/apps
- Click Create new app (or use an existing one)
- Set Redirect URI to
http://localhost:9876/callbackand click Add - Check boards:read and boards:write permissions
- Save the app
- Share the Client ID and Client Secret
Once you have credentials, run the OAuth flow:
python3 scripts/miro_api.py oauth \
--client-id CLIENT_ID \
--client-secret CLIENT_SECRETThis will:
- Start a local server on port 9876
- Print an authorization URL for the user to open in their browser
- Wait for the OAuth callback
- Exchange the code for an access token
- Save token metadata to
~/.miro-token
Tell the user to open the printed URL in their browser and authorize the app.
Step 3: Browse a board
Get board info:
python3 scripts/miro_api.py board-info --board-url "BOARD_URL"List all items with spatial positions and text content:
python3 scripts/miro_api.py list-items --board-url "BOARD_URL"This outputs item type, position, size, and text content for every item on the board. Use the text content to identify sections, then use positions to find images in those regions.
Step 4: Download images
Download images from a spatial region:
python3 scripts/miro_api.py download-images \
--board-url "BOARD_URL" \
--region "x_min,y_min,x_max,y_max" \
--output-dir /tmp/miro-images \
--format originalDownload ALL images on the board:
python3 scripts/miro_api.py download-images \
--board-url "BOARD_URL" \
--output-dir /tmp/miro-images \
--format originalTypical Workflow
- User says "connect Miro" or "grab images from Miro board"
- Check for existing token → if missing, run OAuth setup
- User provides board URL
- Run
list-itemsto see board layout — identify sections by text labels - Identify regions of interest from text item positions
- Run
download-imageswith--regionfor each area of interest - View downloaded images with the Read tool to understand their content
- Use the images as needed (insert into GitHub issues, docs, etc.)
Writing: Create boards and draw diagrams
Create a board
python3 scripts/miro_api.py create-board --name "My Board" --description "Optional"Draw a diagram from JSON
Create a JSON file defining shapes and connectors, then draw it on a board:
python3 scripts/miro_api.py draw-diagram \
--board-url "BOARD_URL" \
--json-file diagram.json \
--offset-x 0 --offset-y 0JSON format:
{
"title": {"text": "<strong>Diagram Title</strong>", "x": 0, "y": -400, "size": 36, "color": "#fbbf24"},
"shapes": [
{"id": "api", "content": "<strong>API</strong><br>FastAPI", "x": 0, "y": 0, "w": 180, "h": 70, "fill": "#1e3a5f", "border": "#3b82f6"},
{"id": "db", "content": "<strong>Database</strong>", "x": 0, "y": 200, "w": 160, "h": 70, "fill": "#3b1a1a", "border": "#ef4444"}
],
"connectors": [
{"from": "api", "to": "db", "start_snap": "bottom", "end_snap": "top", "color": "#fbbf24"}
]
}Shape properties: id (for connectors), content (HTML), x, y, w, h, fill, border, text_color, font_size, shape (round_rectangle, rectangle, circle, etc.)
Connector snap positions: top, bottom, left, right
Create individual items
# Shape
python3 scripts/miro_api.py create-shape --board-url URL \
--content "<strong>Title</strong>" --x 0 --y 0 --width 200 --height 80 \
--fill "#1e3a5f" --border "#3b82f6"
# Text
python3 scripts/miro_api.py create-text --board-url URL \
--content "Header" --x 0 --y -100 --font-size 36 --color "#fbbf24"
# Connector (use shape IDs from create-shape output)
python3 scripts/miro_api.py create-connector --board-url URL \
--start-id SHAPE_ID --end-id SHAPE_ID --start-snap bottom --end-snap topNotes
- Requires
python3and outbound network access to Miro - Board URL format:
https://miro.com/app/board/BOARD_ID=/ - The
--format originalflag downloads full-size images (not thumbnails) - Token metadata is saved to
~/.miro-tokenwith0600permissions - When Miro returns a refresh token, the helper auto-refreshes expiring access tokens
- Images keep their original PNG/JPEG/WebP/SVG file extension when downloaded
- For write operations, the token must have
boards:writescope