Problem
There's no way to include or view images in notes. Markdown image syntax () is either ignored or treated as plain text. Terminal graphics protocols (Kitty, iTerm2, Sixel) make inline image rendering possible in modern terminals.
Context
The block model (internal/block/block.go) has 10 block types — no Image type. The parser (internal/block/parse.go) doesn't handle  syntax. There is zero terminal protocol detection or image rendering in the codebase. Dependencies are Bubble Tea v2 + lipgloss — no image libraries.
mdfried (Rust) uses ratatui-image for protocol auto-detection and rendering with a half-block Unicode fallback. In Go, github.com/BourgeoisBear/rasterm supports Kitty, iTerm2, and Sixel protocols. For half-block fallback, github.com/makeworld-the-better-one/dither or manual implementation with ▀▄ characters.
Key files:
internal/block/block.go — Block struct, BlockType enum
internal/block/parse.go — Markdown → Blocks parser
internal/block/serialize.go — Blocks → Markdown serializer
internal/editor/render.go — All rendering paths
internal/editor/editor.go — Editor model, block operations
Approach
Phase 1: Data model + parsing
- Add
Image BlockType to the enum
- Block's
Content stores the path/URL, could add an Alt field or encode as alt|path
- Parser detects
 lines → creates Image blocks
- Serializer writes them back as standard markdown image syntax
Phase 2: Terminal protocol detection
- At startup, detect supported graphics protocol by querying the terminal
- Priority: Kitty → iTerm2 → Sixel → half-block fallback
- Check
$TERM, $TERM_PROGRAM, and/or send escape sequence queries
- Store detected protocol in the editor model for rendering
Phase 3: Image rendering
- In view mode: load image from disk (local paths relative to note file), decode (PNG/JPEG/GIF), resize to fit within
viewMaxWidth equivalent pixel width, render via detected protocol
- In edit mode: show placeholder block (e.g.,
[Image: filename.png]) — rendering inline images in an editable textarea is impractical
- Cache decoded images to avoid re-loading on every render cycle
- Handle missing files gracefully (show alt text or error indicator)
Dependencies to evaluate
github.com/BourgeoisBear/rasterm — Kitty/iTerm2/Sixel rendering
golang.org/x/image or standard image package — decoding
github.com/nfnt/resize or golang.org/x/image/draw — resizing
Tasks
Acceptance criteria
Problem
There's no way to include or view images in notes. Markdown image syntax (
) is either ignored or treated as plain text. Terminal graphics protocols (Kitty, iTerm2, Sixel) make inline image rendering possible in modern terminals.Context
The block model (
internal/block/block.go) has 10 block types — no Image type. The parser (internal/block/parse.go) doesn't handlesyntax. There is zero terminal protocol detection or image rendering in the codebase. Dependencies are Bubble Tea v2 + lipgloss — no image libraries.mdfried (Rust) uses
ratatui-imagefor protocol auto-detection and rendering with a half-block Unicode fallback. In Go,github.com/BourgeoisBear/rastermsupports Kitty, iTerm2, and Sixel protocols. For half-block fallback,github.com/makeworld-the-better-one/ditheror manual implementation with▀▄characters.Key files:
internal/block/block.go— Block struct, BlockType enuminternal/block/parse.go— Markdown → Blocks parserinternal/block/serialize.go— Blocks → Markdown serializerinternal/editor/render.go— All rendering pathsinternal/editor/editor.go— Editor model, block operationsApproach
Phase 1: Data model + parsing
ImageBlockType to the enumContentstores the path/URL, could add anAltfield or encode asalt|pathlines → creates Image blocksPhase 2: Terminal protocol detection
$TERM,$TERM_PROGRAM, and/or send escape sequence queriesPhase 3: Image rendering
viewMaxWidthequivalent pixel width, render via detected protocol[Image: filename.png]) — rendering inline images in an editable textarea is impracticalDependencies to evaluate
github.com/BourgeoisBear/rasterm— Kitty/iTerm2/Sixel renderinggolang.org/x/imageor standardimagepackage — decodinggithub.com/nfnt/resizeorgolang.org/x/image/draw— resizingTasks
Imageto BlockType enum ininternal/block/block.gointernal/block/parse.goto detectsyntaxinternal/block/serialize.goto write image markdowninternal/terminal/graphics.go)renderViewBlock()ininternal/editor/render.gointernal/editor/palette.goAcceptance criteria
in markdown is parsed into Image blocks and round-trips correctly