Somewhere, I have a small patch set for FreeBSD that adds two features.
The first is a content-negotiation protocol for pipes. This follows the model used for drag and drop and is backwards compatible if one end doesn’t support it. The sender does an ioctl to advertise a list of types that it supports. If the receiver does a read or a poll/select/kqueue wait, this returns an error indicating that the receiver does not support it. The receiver does an ioctl to receive the list of types and another to specify the desired type. The first ioctl similarly returns an error if the sender writes data to the pipe (i.e. they don’t support content negotiation). The sender then writes data according to the agreed type.
The second was ‘pipe peeling’ in the TTY layer. This let you get a second data channel to the terminal emulator (or whatever owns the server side of the tty), so you could send text for display on the normal terminal but also have a completely different stream (or more than one) for other data. You could use this to provide structured data for other rendering, accessibility data, and so on.
I also modified libxo, which a bunch of FreeBSD tools use to provide structured output, so that it would use both of these. If the standard output was a pipe, it would try content negotiation. If the standard output was a try, it would try to peel off a pipe and send structured output there as well as normal output to the tty.
I had a little demo that implemented a tiny tty server that mostly forwarded to the host terminal but accepted peeled pipes and asked for HTML that it would then send to a web browser to open, so anything that used libxo would automatically display pretty (sortable, filterable) output as well as the terminal output.
I had planned to add support for the additional channels in SSH (SSH supports additional data channels, they just needed wiring up), but I never got around to it.
There were some cleanups to do, but it gave you a very simple model for providing rich content between command-line tools (and between tools and the terminal emulator).
The entire diff was only around a hundred lines of code, implementing the same thing in multiple operating systems wouldn’t be very hard.