| name | docs-screenshot |
| description | Capture a 600×400 documentation screenshot from the running Silo app and composite it on the standard wallpaper. Use whenever adding or updating screenshots in apps/docs/public/img/guide/. |
| tools | Bash, Read |
Silo Docs Screenshot
Produces a 600×400 PNG of a Silo UI region composited over the standard orange/purple
wallpaper (apps/docs/public/img/wallpaper.jpg), styled as a windowed screenshot floating
on the desktop — consistent with every other image in the guide.
Quick reference
Corner Desktop visible Window bleeds Window canvas pos Merged geometry Round corner
────────── ───────────────── ─────────────── ───────────────────── ─────────────────── ────────────
top-left top(65) left(80) right, bottom (80, 65) +40+30 all 4
bot-left bot(10) left(80) top, right (80, 0) +40+-35 bot-left only
top-right top(65) right(80) left, bottom (520-OW, 65) +(480-OW)+30 top-right only
bot-right bot(10) right(80) top, left (520-OW, 390-OH) +(480-OW)+(355-OH) bot-right only
center all sides ~50px none ((600-OW)/2, (400-OH)/2) +((600-OW)/2-40)+((400-OH)/2-35) all 4
top-left — top half of app, feature on the LEFT (e.g. workspaces panel, editor).
bot-left — bottom of app, feature on the LEFT (e.g. status bar menu).
top-right — top half of app, feature on the RIGHT (e.g. file explorer, right side panel).
bot-right — bottom of app, feature on the RIGHT (e.g. right-side status items, output panel).
Pipeline
1. Take the screenshot
silo(){ curl -s -m30 -X POST http://127.0.0.1:7878/ \
-H 'X-Silo-Automation: 1' -H 'Content-Type: application/json' \
--data "$1"; }
silo '{"op":"screenshot"}' > /tmp/shot.json
python3 -c "
import json,base64
d=json.load(open('/tmp/shot.json'))
r=d['result']
open('/tmp/silo.png','wb').write(base64.b64decode(r['png_base64']))
print(r['width'], r['height'])
"
2. Choose your crop
The source is 3024×1898 at 2× retina (logical: 1512×949).
Pick the region of interest in 2× pixels and a window output size that fits the composition:
| Style | Typical output window | Typical source crop | Scale |
|---|
| top-left | 580×439 | 900×680 from (0,0) | 0.644× |
| bot-left | 520×390 | 1131×848 from (0,Y) | 0.460× |
Crop rules:
- Source crop
W×H and output window w×h must satisfy W/H = w/h (same aspect ratio).
- For top-left: start at (0,0); choose crop height to include the feature; bleed at right + bottom is automatic since
w > 600-80 and h > 400-65.
- For bot-left: start high enough (Y) that the full feature is inside the crop; the crop bottom is always
1898 (window bottom). Status bar = y≈1050 is a safe start for a menu+statusbar shot.
- To zoom in more: use a smaller source crop (same output window size → larger apparent zoom).
- To zoom out / show more context: use a larger source crop.
3. Compose
WALL="apps/docs/public/img/wallpaper.jpg"
DOCS="apps/docs/public/img/guide"
APP=/tmp/silo.png
CORNER=top-left
CW=900; CH=680
CX=0; CY=0
OW=580; OH=439
OUT="$DOCS/feature.png"
magick "$WALL" -resize "600x400^" -gravity center -extent 600x400 /tmp/bg.png
magick "$APP" -crop ${CW}x${CH}+${CX}+${CY} +repage -resize ${OW}x${OH} /tmp/win-scaled.png
R=10
case "$CORNER" in
top-left)
magick /tmp/win-scaled.png \
\( +clone -alpha extract -fill black -colorize 100 \
-fill white -draw "roundrectangle 0,0 $((OW-1)),$((OH-1)) 10,10" \) \
-alpha off -compose CopyOpacity -composite /tmp/win-rounded.png
;;
bot-left)
magick /tmp/win-scaled.png \
\( +clone -alpha extract -fill black -colorize 100 \
-fill white -draw "rectangle 0,0 $((OW-1)),$((OH-1))" \
-fill black -draw "rectangle 0,$((OH-R)) $((R-1)),$((OH-1))" \
-fill white -draw "circle ${R},$((OH-R)) 0,$((OH-R))" \
\) -alpha off -compose CopyOpacity -composite /tmp/win-rounded.png
;;
top-right)
magick /tmp/win-scaled.png \
\( +clone -alpha extract -fill black -colorize 100 \
-fill white -draw "rectangle 0,0 $((OW-1)),$((OH-1))" \
-fill black -draw "rectangle $((OW-R)),0 $((OW-1)),$((R-1))" \
-fill white -draw "circle $((OW-R)),${R} $((OW-1)),${R}" \
\) -alpha off -compose CopyOpacity -composite /tmp/win-rounded.png
;;
bot-right)
magick /tmp/win-scaled.png \
\( +clone -alpha extract -fill black -colorize 100 \
-fill white -draw "rectangle 0,0 $((OW-1)),$((OH-1))" \
-fill black -draw "rectangle $((OW-R)),$((OH-R)) $((OW-1)),$((OH-1))" \
-fill white -draw "circle $((OW-R)),$((OH-R)) $((OW-1)),$((OH-R))" \
\) -alpha off -compose CopyOpacity -composite /tmp/win-rounded.png
;;
esac
magick /tmp/win-rounded.png \
\( +clone -background '#00000099' -shadow 90x20+0+10 \) \
+swap -background none -layers merge +repage /tmp/win-shadowed.png
case "$CORNER" in
top-left) GX=40; GY=30 ;;
bot-left) GX=40; GY=$((-35)) ;;
top-right) GX=$((480-OW)); GY=30 ;;
bot-right) GX=$((480-OW)); GY=$((355-OH)) ;;
esac
magick /tmp/bg.png /tmp/win-shadowed.png -geometry +${GX}+${GY} -composite "$OUT"
magick identify -format "%wx%h\n" "$OUT"
Shadow offset math (reference)
-shadow 90x20+0+10 with layers merge places the source window at (40, 35) inside
the merged RGBA image regardless of the window dimensions.
Formula: -geometry +(canvas_x − 40)+(canvas_y − 35)
Verify any time the shadow params change:
magick -size 100x100 xc:red \
\( +clone -background '#00000099' -shadow 90x20+0+10 \) \
+swap -background none -layers merge +repage /tmp/t.png
magick identify /tmp/t.png
Common shots
| Guide section | Corner | Source crop (2×) | Output window | Output file |
|---|
| Workspaces panel | top-left | 900×680 from (0,0) | 580×439 | workspaces-panel.png |
| Workspaces + button | top-left | 900×680 from (0,0) | 580×439 | workspaces-open.png (cursor at + button tip≈(48,265)) |
| Status bar + menu | bot-left | 1131×848 from (0,1050) | 520×390 | workspaces-statusbar.png |
| File explorer panel | top-right | 1324×1000 from (1700,0) | 580×438 | panels-file-explorer.png |
| Getting started | center | full window (no crop) | 480×304 | getting-started-app.png |
Rules
- Output is always 600×400 — verify with
magick identify.
- Never cut the app artificially — the window must be a real contiguous region of the app, just cropped at the canvas edge due to bleed.
- Zoom into the feature — pick a crop tight enough that the relevant UI is clearly readable.
- Close any menus or dialogs after capturing so the app is left in a clean state.
- Always embed with
width="400" — the 600px image at 400 CSS pixels gives a sharp 1.5× render on retina displays without being too small. Never use width="600" (blurry on retina) or width="300" (too small).