Silo Docs Screenshot

SkillDocs & knowledge

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/.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Silo Docs Screenshot skill

What this skill tells your AI

The instructions your AI receives, as published by silo-code/silo in .agents/skills/docs-screenshot/SKILL.md and read by ahel’s review.

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"; }

# Set up any app state first (open panels, menus, etc.), then:
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'])
"
# Typical output: 3024 1898  (2× retina — logical pixels are half)

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:

StyleTypical output windowTypical source cropScale
top-left580×439900×680 from (0,0)0.644×
bot-left520×3901131×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   # or your saved screenshot

# ── Variables ──────────────────────────────────────────────────────────────
CORNER=top-left         # top-left | bot-left
CW=900; CH=680          # source crop width × height (2× pixels)
CX=0;   CY=0            # source crop origin (2× pixels)
OW=580; OH=439          # output window width × height (pixels)
OUT="$DOCS/feature.png" # destination

# ── Wallpaper background ───────────────────────────────────────────────────
magick "$WALL" -resize "600x400^" -gravity center -extent 600x400 /tmp/bg.png

# ── Crop + scale ───────────────────────────────────────────────────────────
magick "$APP" -crop ${CW}x${CH}+${CX}+${CY} +repage -resize ${OW}x${OH} /tmp/win-scaled.png

# ── Mouse cursor (optional) ────────────────────────────────────────────────
# Use when you want to indicate where the user should click.
# IMPORTANT: Do NOT use SVG — ImageMagick renders it as a plain white square.
# Draw the cursor natively instead. Cursor tip is at pixel (2,2) within the image.
#
# TIP_X=48; TIP_Y=265   # desired tip position in output-window coordinates
# magick -size 24x28 xc:none \
#   -fill white -stroke black -strokewidth 1.5 \
#   -draw "polygon 2,2 2,22 7,17 11,26 14,24 10,15 18,15" \
#   /tmp/cursor.png
# magick /tmp/win-scaled.png /tmp/cursor.png \
#   -geometry +$((TIP_X-2))+$((TIP_Y-2)) -composite /tmp/win-scaled.png
#
# Placement rule: subtract 2 from both axes (tip offset within cursor image).
# Place the cursor AFTER crop+scale but BEFORE rounded corners so it gets
# clipped correctly if it's near an edge.

# ── Rounded corners ────────────────────────────────────────────────────────
R=10
case "$CORNER" in
  top-left)
    # All 4 corners — top-left is the real window corner; others bleed but rounding is consistent
    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)
    # Round bottom-left corner only; top bleeds off canvas, right bleeds off canvas
    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)
    # Round top-right corner only; left bleeds off canvas, bottom bleeds off canvas
    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)
    # Round bottom-right corner only; top bleeds off canvas, left bleeds off canvas
    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

# ── Drop shadow ────────────────────────────────────────────────────────────
# shadow 90x20+0+10 → window lands at (40,35) inside the merged image
magick /tmp/win-rounded.png \
  \( +clone -background '#00000099' -shadow 90x20+0+10 \) \
  +swap -background none -layers merge +repage /tmp/win-shadowed.png

# ── Composite onto background ──────────────────────────────────────────────
# Shadow offset: window in merged image sits at (40,35). Formula: geometry = +(canvas_x−40)+(canvas_y−35)
# top-left:  window canvas (80, 65)           → +40+30
# bot-left:  window canvas (80, 0)            → +40+-35
# top-right: window canvas (520−OW, 65)       → +(480−OW)+30
# bot-right: window canvas (520−OW, 390−OH)   → +(480−OW)+(355−OH)
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"   # must print 600x400

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   # merged WxH
# window_x_offset = (merged_W - 100) / 2
# window_y_offset determined empirically or via: (merged_H - 100 - 10) / 2

Common shots

Guide sectionCornerSource crop (2×)Output windowOutput file
Workspaces paneltop-left900×680 from (0,0)580×439workspaces-panel.png
Workspaces + buttontop-left900×680 from (0,0)580×439workspaces-open.png (cursor at + button tip≈(48,265))
Status bar + menubot-left1131×848 from (0,1050)520×390workspaces-statusbar.png
File explorer paneltop-right1324×1000 from (1700,0)580×438panels-file-explorer.png
Getting startedcenterfull window (no crop)480×304getting-started-app.png

Rules

  1. Output is always 600×400 — verify with magick identify.
  2. 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.
  3. Zoom into the feature — pick a crop tight enough that the relevant UI is clearly readable.
  4. Close any menus or dialogs after capturing so the app is left in a clean state.
  5. 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).

Signals

GitHub stars
56
Forks
5
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
docs-screenshot
Source
github.com/silo-code/silo