COORD: 44.21.90
OFFSET: +12.5°
SYS.READY
BUFFER: 99%
FOCAL_PT
BACK TO DEVLOG
WORKSPACE

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

2026-01-05 // RAW LEARNING CAPTURE
PROJECTWORKSPACE

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 timg

Hit a Rosetta issue on Apple Silicon:

Error: Cannot install under Rosetta 2 in ARM default prefix (/opt/homebrew)!

Fix:

arch -arm64 brew install timg

Installed 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.svg

Kitty 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.svg

Uses 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.svg

Outputs 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):

ModeCharactersResolutionDiagonals
-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.svg

For universal fallback:

timg -pq -g80x24 /tmp/sketch.svg

Design 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:

  1. Write SVG to /tmp/sketch.svg
  2. Render with timg -pk /tmp/sketch.svg (Ghostty) or timg -pq -g80x24 /tmp/sketch.svg (fallback)
  3. 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

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

  2. Design to the output grid. Match viewBox to effective pixel resolution for sharp results.

  3. Wireframes > full mockups for terminal rendering. High contrast, solid fills survive the averaging.

  4. Quarter blocks (-pq) beat half blocks (-ph) for diagonal lines and rounded shapes.

  5. Always specify -g geometry in Claude Code context — auto-fit won't work.

LOG.ENTRY_END
ref:workspace
RAW