원클릭으로
gif-protocol
Sharp bits and gotchas for sending GIFs and scrolling text to the iPIXEL LED cap
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Sharp bits and gotchas for sending GIFs and scrolling text to the iPIXEL LED cap
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
How to use the CLI interface. Use this skill when interacting with the tool as an end user.
Use whenever creating, editing, renaming, or deleting any file under .claude/skills/, .claude/agents/, .agents/skills/, or .codex/agents/. Teaches the dual-tool Claude/Codex layout and reminds to run `make sync-agent-config`.
Convert PRDs to prd.json format for the Ralph autonomous agent system. Use when you have an existing PRD and need to convert it to Ralph's JSON format.
| name | gif-protocol |
| description | Sharp bits and gotchas for sending GIFs and scrolling text to the iPIXEL LED cap |
| user_invocable | true |
| triggers | ["/gif-protocol"] |
Reference for sending GIF animations (including scrolling text) to the iPIXEL LED cap. These are non-obvious constraints discovered through hardware testing.
The device's GIF decoder is simple. Two Pillow settings are mandatory for smooth playback:
frames[0].save(
buf,
format="GIF",
save_all=True,
append_images=frames[1:],
duration=frame_duration,
loop=0,
disposal=2, # REQUIRED: restore to background between frames
optimize=False, # REQUIRED: full frames, no inter-frame diffs
)
disposal=2: Without this, the device stacks frames on top of each other, causing visual corruption and discontinuous jumps.optimize=False: Pillow's default inter-frame optimization produces diffs the device can't decode properly. Each frame must be a complete image.convert("RGBA"): Frames should be converted to RGBA before saving (matches the format that worked with pre-made GIFs).The native text protocol (CMD_TEXT = 0x0100) causes an immediate device disconnect on this hardware variant. Scrolling text is implemented by rendering text frames as a GIF animation instead.
Key design decisions:
total_width = text_width + display_width. Text at position 0, one display-width of blank padding at the end for the loop gap.max(30, 250 - speed * 3) ms, where speed is 0-100.Payloads exceeding 12,288 bytes (WINDOW_SIZE) are split into windows by src/protocol/transport.py:
[option][total_size:4LE][crc32:4LE][0x00][slot]option=0x00, subsequent: option=0x020x03 = all data received; 0x01 = more windows expectedFor non-scrolling text, render to a 32x16 PNG and send via CMD_GIF_DATA (0x0003). The PNG must be exactly the display dimensions (32x16) - oversized PNGs are accepted (ACK) but not displayed.
| Symptom | Cause | Fix |
|---|---|---|
| Frames flash/jump discontinuously | Missing disposal=2 or optimize=False | Add both to GIF save |
| Text not visible, blank display | PNG wider than 32px | Render to exact display dimensions |
| Device disconnects on send | Using native text protocol (0x0100) | Use GIF-based scrolling instead |
| Only see flicker of text edges | Too many blank padding frames | Start text at x=0, not x=width |
| Scrolling looks janky | Step size too large | Use step=2px for smooth movement |
| Send hangs/times out | Payload >12KB without windowing | Use send_data() from transport.py |