- 01.Starting Point
- 02.Installing timg
- 03.First Test: Simple SVG Pipe
- 04.Kitty Mode vs Half-Block Mode
- 05.Testing a Full Landing Page Mockup
- 06.The Wireframe Pivot
- 07.Pixel-Art Approach: Design to Output Grid
- 08.Quarter Blocks vs Half Blocks
- 09.Terminal Sizing
- 10.Final Working Approach
- 11.Where We Landed
- 12.Takeaways
Terminal SVG Sketching with timg
Exploring whether Claude can sketch UI layouts that render directly in the terminal using `timg`, keeping visual feedback in-flow without opening browser windows. Goal: fast iteration on layout ideas
Starting Point
Exploring whether Claude can sketch UI layouts that render directly in the terminal using timg, keeping visual feedback in-flow without opening browser windows. Goal: fast iteration on layout ideas during Claude Code sessions.
Installing timg
brew install timgHit a Rosetta issue on Apple Silicon:
Error: Cannot install under Rosetta 2 in ARM default prefix (/opt/homebrew)!
Fix:
arch -arm64 brew install timgInstalled v1.6.3 with GraphicsMagick, librsvg, poppler (PDF), libsixel, and kitty graphics support.
First Test: Simple SVG Pipe
Tried piping SVG directly to timg:
echo '<svg viewBox="0 0 200 100"><rect fill="#3b82f6" width="200" height="100"/></svg>' | timg -pk -Failed with:
If this is a video on stdin, use '-V' to skip image probing
timg can't probe file type from stdin for images. Workaround: write to temp file first.
echo '<svg ...>' > /tmp/test.svg && timg /tmp/test.svgKitty Mode vs Half-Block Mode
Created a night landscape SVG (/tmp/cool.svg) to test rendering modes.
Half-block mode (-ph) — works in Claude Code's bash preview:
timg -ph -g80x25 /tmp/cool.svgUses ANSI color codes + Unicode half-block characters (▄▀). Any terminal can render these as styled text. This rendered inline in Claude Code output.
Kitty mode (-pk) — raw protocol output in Claude Code:
timg -pk -g80x25 /tmp/cool.svgOutputs base64-encoded PNG data with escape sequences:
_Ga=T,i=2923789313,q=2,f=100,m=0;iVBORw0KGgoAAAANSUhEUgAAA...
Claude Code's bash preview captures stdout as text, doesn't interpret Kitty graphics protocol. User would need to run in actual Kitty/Ghostty terminal to see rendered image.
Testing a Full Landing Page Mockup
Created Vercel-style landing page (/tmp/vercel-landing.svg) with:
- Dark background, gradient glow
- Nav with logo, links, CTA button
- Hero headline with gradient text
- Two CTA buttons (filled + outlined)
- Logo bar, feature cards
At 120x40 half-blocks, the mockup rendered but gradients got mushy and text was illegible. Conclusion: full-color designs don't survive half-block averaging.
The Wireframe Pivot
Switched to wireframe style with high contrast:
- White on dark gray
- Solid fills only, no gradients
- Placeholder rectangles for content
- X marks for image placeholders
<svg viewBox="0 0 800 600" xmlns="http://www.w3.org/2000/svg">
<rect width="800" height="600" fill="#fff"/>
<!-- Navbar -->
<rect x="0" y="0" width="800" height="50" fill="#f5f5f5" stroke="#ddd"/>
<rect x="20" y="12" width="80" height="26" fill="#333" rx="4"/>
...
</svg>
Rendered much cleaner. Structure readable at a glance.
Pixel-Art Approach: Design to Output Grid
Key insight: design SVG viewBox to match output resolution.
For -g120x40 with half-blocks, effective resolution is 120x80 pixels. So:
<svg viewBox="0 0 120 80" xmlns="http://www.w3.org/2000/svg">
<rect width="120" height="80" fill="#111"/>
<!-- Nav: 8 units tall -->
<rect x="0" y="0" width="120" height="8" fill="#222"/>
<rect x="2" y="2" width="12" height="4" fill="#fff"/>
...
</svg>
This produced sharp, predictable results. Elements aligned to the grid, no sub-pixel blurring.
Quarter Blocks vs Half Blocks
Compared -ph (half blocks) vs -pq (quarter blocks):
| Mode | Characters | Resolution | Diagonals |
|---|---|---|---|
-ph | ▄▀ | COLSx(LINES×2) | Stair-stepped |
-pq | ▗▖▝▘ | (COLS×2)x(LINES×4) | Smoother |
Quarter blocks render diagonal lines better (rounded corners on outlined buttons). Recommend -pq as fallback when quality matters.
Terminal Sizing
Query dimensions before sketching:
COLS=$(tput cols)
LINES=$(tput lines)
echo "Terminal: ${COLS}x${LINES} chars"
echo "Half-block effective: ${COLS}x$((LINES*2)) pixels"In test session: 80x24 chars → 80x48 effective pixels for half-block.
Auto-fit (-g0x0) fails in Claude Code because timg can't query terminal size in non-interactive context. Must specify explicit geometry.
Final Working Approach
For Ghostty users (Kitty protocol works):
timg -pk /tmp/sketch.svgFor universal fallback:
timg -pq -g80x24 /tmp/sketch.svgDesign guidelines for half-block/quarter-block:
- Use solid fills, no gradients
- High contrast palette:
#111,#222,#333,#555,#fff - Think pixel art — align to grid
- Thick lines (2+ units) over 1px
- Design viewBox to match output:
viewBox="0 0 ${COLS} $((LINES*2))"
Where We Landed
Working workflow for terminal UI sketching:
- Write SVG to
/tmp/sketch.svg - Render with
timg -pk /tmp/sketch.svg(Ghostty) ortimg -pq -g80x24 /tmp/sketch.svg(fallback) - Iterate on SVG, re-render
Half-block mode renders inline in Claude Code output. Kitty mode shows raw protocol (but renders in actual Ghostty terminal).
Takeaways
-
Kitty graphics protocol doesn't render in Claude Code's bash preview — it captures stdout as text. Half-block mode works because it's just ANSI codes + Unicode.
-
Design to the output grid. Match viewBox to effective pixel resolution for sharp results.
-
Wireframes > full mockups for terminal rendering. High contrast, solid fills survive the averaging.
-
Quarter blocks (
-pq) beat half blocks (-ph) for diagonal lines and rounded shapes. -
Always specify
-ggeometry in Claude Code context — auto-fit won't work.