Skip to content

Glyph protocol spec#1542

Draft
raphamorim wants to merge 5 commits intomainfrom
glyph-protocol-spec
Draft

Glyph protocol spec#1542
raphamorim wants to merge 5 commits intomainfrom
glyph-protocol-spec

Conversation

@raphamorim
Copy link
Copy Markdown
Owner

@raphamorim raphamorim commented Apr 20, 2026

Ref: https://rapha.land/introducing-glyph-protocol-for-terminals/
Ref: https://rapha.land/adding-color-glyphs-to-glyph-terminal-protocol/

TODO:

  • Finer-grained registration scope. Optional flags to share a glyph across all PTYs at once (so a system-wide icon registry survives tmux splits and reattaches), or pin one as un-evictable for the life of the session. Both go beyond the current per-session, FIFO-eviction defaults.
  • Shared colour palettes. Every colrv0/colrv1 registration currently ships its own CPAL inline. A way to upload a palette once and let subsequent glyph registrations reference it by ID would save thousands of redundant bytes for emoji families (Twemoji, Noto, Fluent) where every glyph reuses the same ~50-entry palette.
  • Custom metrics parameter
  • Hinting (v1?)

Lai Jia Yang and others added 4 commits April 19, 2026 10:25
* docs: add documentation to test_poll.rs

* chore: remove test_echo_server.rs (fully commented out, no functional tests)

* chore: remove test_close_on_drop.rs (fully commented out, no functional tests)

* chore: remove test_double_register.rs (fully commented out, no functional tests)

* chore: remove test_broken_pipe.rs (uses deprecated corcovado::deprecated module that no longer exists)
mitchellh added a commit to ghostty-org/ghostty that referenced this pull request Apr 20, 2026
This adds the core parse/encode for the still in-development and experimental
terminal glyph protocol: raphamorim/rio#1542

The only cross-cutting change necessary was changing the APC
identification logic which previously only looked at a single byte to
support multi-byte identifiers since the glyph protocol uses `25a1`.
mitchellh added a commit to ghostty-org/ghostty that referenced this pull request Apr 20, 2026
This adds the core parse/encode for the still in-development and experimental
terminal glyph protocol: raphamorim/rio#1542

The only cross-cutting change necessary was changing the APC
identification logic which previously only looked at a single byte to
support multi-byte identifiers since the glyph protocol uses `25a1`.
@mitchellh
Copy link
Copy Markdown

mitchellh commented Apr 20, 2026

Lifetime and capacity. Each terminal session carries a glossary of at most 1024 simultaneous registrations, keyed by codepoint anywhere in the three PUA ranges. Registrations live for the duration of the session. If an application registers a 1025th glyph, the terminal evicts the oldest registration in FIFO order — there is no “glossary full” error to handle. Applications that cannot tolerate silent eviction should query their codepoint before emitting.

I'd like to ask for explicit guidance on payload size limits too. At the time of writing this, I've initially set a default limit on the full APC command to 1 MB: ghostty-org/ghostty#12352 (As a comparison, for Kitty Graphic I do 65 MB). This is to prevent DoS for malformed APC commands buffering unbounded memory usage.

From a spec standpoint, it'd be helpful to have guidance on recommended limits so that application authors can be confident what works and what may not.

EDIT: I see payload_too_large now, sorry I was reading an old version of the spec. I think some guidance on the full APC payload would be good too, but this is helpful!

Finer-grained registration scope. Optional flags to share a glyph across all PTYs at once (so a system-wide icon registry survives tmux splits and reattaches), or pin one as un-evictable for the life of the session. Both go beyond the current per-session, FIFO-eviction defaults.

I think simpler protocols are better than complex protocols, especially for getting mass adoption, so I'm going to push back on this. I think this would add a lot more complexity to the terminal emulator side of things (per-session state is always easier) and I think it'd better to avoid it. Can you explain this a bit further?

@mitchellh
Copy link
Copy Markdown

mitchellh commented Apr 20, 2026

There is no mention of glyf payload validation. If you want to keep the protocol simple, it'd be easiest to put the burden on the client: glyf's must be valid, so recommend validating using a glyf library on the client side. If an invalid glyf is sent, it will take up a glossary slot but may not render (will act as if there wasn't a glossary entry).

That'd be simplest for me because in the libghostty use case we could add full Glyph protocol handling without forcing the user to provide a glyf-validator side effect callback. That could all be handled in the renderer which is... wherever it is!

EDIT: I see malformed_payload in the spec, my mistake. Just take the above as feedback then.

mitchellh added a commit to ghostty-org/ghostty that referenced this pull request Apr 20, 2026
This adds the core parse/encode for the still in-development and experimental
terminal glyph protocol: raphamorim/rio#1542

The only cross-cutting change necessary was changing the APC
identification logic which previously only looked at a single byte to
support multi-byte identifiers since the glyph protocol uses `25a1`.
@raphamorim
Copy link
Copy Markdown
Owner Author

I think simpler protocols are better than complex protocols, especially for getting mass adoption, so I'm going to push back on this. I think this would add a lot more complexity to the terminal emulator side of things (per-session state is always easier) and I think it'd better to avoid it. Can you explain this a bit further?

I agree 100% the simpler the better, and this is a concern I have regarding multiplexers running applications with the protocol usage. For example, tmux can runs many nvim or any application that can register and overwrite same codepoint. so it would lead to corruption on the other panels of the tmux. What I thought originally was add a param like locked and this would mean the icon couldn't never be cleanup.

@raphamorim
Copy link
Copy Markdown
Owner Author

Other idea though is actually introduce automatic registry and let the terminal manage the spots. It would get rid of the necessity of known the specific unicode or even evolve the scope registry.

  Request:                                                                                                                                              
  ESC _ 25a1 ; r ; cp=auto ; fmt=glyf ; upm=1000 ; <base64> ESC \                                                                                       
                                                                                                                                                        
  Reply (on success, with reply=1):                                                                                                                     
  ESC _ 25a1 ; r ; cp=100045 ; status=0 ESC \    

@raphamorim
Copy link
Copy Markdown
Owner Author

raphamorim commented Apr 21, 2026

i am thinking in also change the nature of the protocol. so you can't overwrite existing codepoints anymore. this would eliminate corruption cases.

If you want a specific cp you can still send. if it's used, then the protocol will reply it's in use. Optionally you can send auto and the terminal will manage the codepoints in runtime, security wise, for example any other malware that wants to force the same codepoint as the main running application, is also better.

EDIT: I think I will not change the nature of the protocol for now, I understand developers want freedom. I will just add support for auto and make it the recommendation for many cases

@raphamorim
Copy link
Copy Markdown
Owner Author

@qwerasd205 made a great point — auto-assignment breaks replay tools like asciinema and tee, because the "give me a free codepoint" round-trip is stateful and the reply doesn't get captured in the recorded stream. Playing the file back would ship registrations at codepoints that never match what the program later emits.

I'll revert cp=auto (§6.5 and the v1.5 change log entry). Clients can pick their own PUA codepoints as in v1.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants