-
Notifications
You must be signed in to change notification settings - Fork 92
Add Kitty Graphics Protocol V2 API with Image ID Support #324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Thanks for the PR. Have you checked that this still works on the wezterm, ghostty or kitty terminals? I will review it in depth soon. |
|
The If you look at chafa/chafa/internal/chafa-kitty-renderer.c Line 274 in c067bf1
|
This commit fixes video playback issues in iTerm2 by properly implementing image ID support in the Kitty graphics protocol while maintaining backward compatibility with the existing V1 API. Key changes: 1. Created V2 API (BEGIN_KITTY_IMMEDIATE_IMAGE_V2) with 6 parameters including image_id, while keeping V1 API unchanged at 5 parameters to preserve public API compatibility. 2. Added chafa_kitty_next_image_id() function with atomic operations for thread-safe unique image ID generation. 3. Implemented runtime API detection with graceful fallback - prefers V2 for better iTerm2 compatibility, falls back to V1 for older terminals. 4. Fixed chunk sizes to exact multiples of 3 (63 bytes for iTerm2/Screen, 510 bytes for tmux) to avoid base64 padding issues. 5. Restored independent chunk encoding with encode_chunk() function for simpler implementation compared to streaming base64. 6. Updated capability detection to check for both V2 and V1 APIs. Technical details: - iTerm2 requires image ID (i=) parameter as it uses identifiers as dictionary keys in its _images storage - Separates image_id (identifies image data) from placement_id (identifies display position) - Thread-safe ID generation prevents collisions in multi-threaded environments - Chunk sizes are multiples of 3 to ensure clean base64 encoding without padding characters in the middle of transmission Fixes video playback in iTerm2 terminal.
|
Because some compatibility issues, the PR has been closed for now and will be reopened after the fixes and testing are completed. |
|
Problem: When using Kitty graphics protocol V2 API (with image IDs) to fix iTerm2 compatibility, terminals send acknowledgment responses that appear as visible text pollution in the shell after chafa exits: - "Gi=1;OK" from BEGIN_KITTY_IMMEDIATE_IMAGE_V2 sequence - "Gi=0;OK" from END_KITTY_IMAGE sequence Root Cause: The Kitty protocol sends responses by default when processing image commands. Since chafa is a non-interactive tool that exits immediately after rendering, these responses arrive after the program terminates and are displayed as text in the user's shell. Solution: Add the q=2 parameter (quiet/suppress responses mode) to both: 1. BEGIN_KITTY_IMMEDIATE_IMAGE_V2 sequence 2. END_KITTY_IMAGE sequence This suppresses terminal responses while maintaining image ID support required for iTerm2 compatibility. Testing: Verified in iTerm2, Kitty, and Ghostty - images display correctly with no terminal response text pollution. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
ProblemWhen using Kitty graphics protocol V2 API (with image IDs) to fix iTerm2 compatibility, terminal
Root Causechafa is a non-interactive CLI tool that exits immediately after rendering. Terminal responses SolutionAdd q=2 (quiet mode) parameter to suppress terminal responses in:
This maintains image ID support (required for iTerm2) while preventing response pollution. Testing✅ Verified in iTerm2, Kitty, and Ghostty |
|
The updated code fixes the issue where iTerm2 couldn’t display images when using the Kitty graphics protocol. WezTerm, Ghostty, and Kitty all worked normally. |
|
Thanks for the update. The chunk size needs to be big also for The _V2 macro handling needs a bit more work. ChafaImage will need an ID like ChafaPlacement has, that will have to be passed down and not generated on site. If iTerm can't handle un-numbered images, isn't that technically an iTerm bug? Maybe it should just be fixed there? |
Pass a stable ChafaImage-owned ID down to the kitty renderer for V2 transfers instead of generating IDs at render time. Keep Screen on small base64 chunks but use larger (multiple-of-3) chunks for other passthrough modes (including CHAFA_PASSTHROUGH_NONE) to avoid mid-stream base64 padding issues.
|
Thanks for suggestions! This updates Kitty graphics protocol output in two ways:
I believe that’s technically an iTerm2 bug. If i= is omitted (unnumbered images), iTerm2 appears to mishandle multipart transmit+display: it stores identifier==0 as a “last image”, but later looks it up using key 0, so the image may not be found after transmission. I’m in the process of reporting this to iTerm2 (and can follow up with a fix there). In the meantime, Chafa emitting a stable i= when V2 is available is a practical compatibility workaround for existing iTerm2 releases. |
|
It seems that iTerm has an upstream patch fixing this. |
|
If you think that introducing a new V2 API is unnecessary, and that the issue can be resolved simply by adding the q=2 parameter, please close this PR after completing the corresponding changes. |
|
I think we do need more Kitty seqs eventually, but the "immediate" one is supposed to not need any ID handling by the client. The Kitty docs say this:
So although the specification is a bit ambiguous, I'm choosing to interpret the acknowledgement condition as being "if and only if" an image ID is specified. So iTerm2 seems to be doing the wrong thing here - other terminals don't print an acknowledgement. However, I suppose we could add tl;dr: I think we should keep the block size change and add |
|
The upstream change in iTerm now decodes each chunk from Base64 individually and accumulates the binary data, which allows each chunk to be independently encoded and to include padding. The Kitty graphics protocol documentation states: “If you are using the graphics protocol from a limited client, such as a shell script, it might be useful to avoid having to process responses from the terminal. For this, you can use the q key. Set it to 1 to suppress OK responses and to 2 to suppress failure responses.” Therefore, whether q=1 or q=2 should be used requires further investigation. I plan to close this PR and have you implement this change directly. |
|
Yeah, the documentation seems unclear with respect to whether images uploaded without an ID should generate a response or not. Kitty does not seem to generate a response. Thanks for following up on this in the iTerm tracker and here. Sometimes the research is the biggest task. |

Summary
This PR adds support for Kitty graphics protocol V2, which includes explicit image ID parameters.
This improves compatibility with terminals like iTerm2 that have issues with the V1 protocol.
Changes
Fix base64 chunk alignment (commit 1)
Add image ID generation (commit 2)
Implement V2 API (commit 3)
BEGIN_KITTY_IMMEDIATE_IMAGE_V2with 6 parametersAPI Compatibility
Testing
Tested on:
Technical Details
The implementation checks for
CHAFA_TERM_SEQ_BEGIN_KITTY_IMMEDIATE_IMAGE_V2availability atruntime:
This approach ensures maximum compatibility without breaking existing functionality.