
Texttop – An interactive X Linux desktop rendered in TTY and streamable over SSH - sandebert
https://github.com/tombh/texttop
======
tombh
Author here. Surprised to see this here as I've been literally spending the
last 2 weeks on a complete rewrite from scratch that actually layers REAL text
over the blocks. You can get an idea of my approach with this function:
[https://github.com/tombh/texttop/blob/webext-
rewrite/webext/...](https://github.com/tombh/texttop/blob/webext-
rewrite/webext/src/text_builder.js#L165)

After the success of hitting the front page here last year, I really wanted to
sit down and do this properly. So not only am I working on real text support
(that you can of course copy and paste without even zooming). But I've removed
the dependencies on ffmpeg, Xorg (for Firefox at least - Chrome strangely
doesn't support webextensions in headless mode), docker AND it will work on
all webextension-compatible browsers. It's going to be a single cross-
platform, static, Go binary, that launches your preferred browser in the
background.

Generally it's bad luck to talk about something before it's finished, but
seeing as it's suddenly on the front page I wanted to let all those interested
know that I'm making this 10 times better. And an early apology, because I'll
definitely be posting the rewrite (and rename) here and hoping to get all your
attention again.

~~~
dukoid
You might get a slightly better resolution with the approach taken here:
[https://github.com/stefanhaustein/TerminalImageViewer](https://github.com/stefanhaustein/TerminalImageViewer)
(= find best matching block graphics character for most prominent colors in a
cell; there is a comparison to half blocks at the end).

~~~
igravious
Cool, TIV looks great! (Just compiled, ran, and tested it.)

I thought
[cacaview]([https://github.com/cacalabs/libcaca](https://github.com/cacalabs/libcaca))
was the only terminal image viewer player in town with their attendant
`cacaview' prog. I'd very much appreciate it if anyone here knows of any other
libs or especially the sanest way to do this in either C/C++ or Ruby … It's
for a terminal-based project I have in mind :)

~~~
dukoid
Some alternatives are listed in this askubuntu thread:
[https://askubuntu.com/questions/97542/how-do-i-make-my-
termi...](https://askubuntu.com/questions/97542/how-do-i-make-my-terminal-
display-graphical-pictures/)

------
fsiefken
While the geekery is really really cool I also wonder if this method can be
beaten with the best in video comepression. Extremely low bandwidth encoding
perhaps provides better results (if you put cpu/gpu load aside), for example
see this x265 example over 50 Kbit/s. [http://wp.xin.at/archives/4020/comment-
page-1](http://wp.xin.at/archives/4020/comment-page-1) People are watching
Netflix in low quality in 100-200 Kbit/s. With the upcoming AV! (AOmedia Video
1) it gets even beter. Another avenue is Citrix/RDP connection work ok over
30-50 Kbit/s. Then there is the counterpart FreeRDP. Wouldn't FreeRDP be the
preferred solution here, except then that Mosh solves the potential latency
issue? With linux desktops running on low power clients already, why bother?
Does it use less battery life so you can get 48 hours surfing the internet in
the mountains or forest while the solar powered server runs at home?

~~~
tombh
I certainly think you can get close with video. But one of the things about
this method is that I wanted it to be as universal and as accessible as
possible. As in: accessing a fully modern JS-enabled browser over just an SSH
client.

------
callesgg
I did project with Webkit that renders to the terminal:

[https://github.com/callesg/termkit](https://github.com/callesg/termkit)

~~~
tombh
Waat! We need to talk - I'm taking a very similar approach in my rewrite.
There are some very interesting algorithm problems. Eg; I'm actually comparing
pixels in 2 screenshots --with and without text rendered--, in order to get
text colour and visibility. This way is actually more performant than using
`getElementAt(x, y)` and `getComputedStyle(element)`.

~~~
callesgg
I rewrote mine to. One big problem i hit before rewriting was performance and
also css :after classes they are not reachable in the DOM if I remember
correctly. So I resorted to patching phantom to give me access to the WebKit
render tree.(which is a tree similar to the Dom tree but not the same.

I can't remember if there was some big issue that eventually made me stop
developing. I think the final issue was characters with dual width like many
Chinese characters the gui library blessed did not understand the concept of
characters with non standard width and a single such character would destroy
the entire layout. And issues with correlting the render tree and the Dom
tree.

~~~
callesgg
Now I remember the main problem before switching to the render three was text
rows. there is no good way of knowing where a text line will break without
resorting to the render tree or to use some form of ocr.

~~~
tombh
Ah yes, that was a big hurdle, but that's actually fully supported now with
DOM Ranges - basically codified selection boxes, those regions that highlight
when you select with a mouse. There's still some extra leg work though to
render whitespace in the same way as the browser.

~~~
callesgg
I did that to if you are referring to getBoundingClientRect & getClientRects,
before I switched over to the render tree.

It does work perfecly for single line text but not multi line text. The rect
will become larger than the text and you won't know where each line starts.

Well that is what I remember happening.

~~~
tombh
Oh! Sorry I just assumed they weren't around then. That's really interesting
to know. Hey could I have a chat with somewhere, IM, or something? Would be
really good to hear your story with this.

------
betolink
Previously on HN:
[https://news.ycombinator.com/item?id=11744221](https://news.ycombinator.com/item?id=11744221)

------
jxy
It uses Xvfb, ffmpeg, hiptext (with fixes from the author), and a custom
interfacer written in go, which employs xzoom in C and termbox-go (with fixes
from the author).

The interfacer alone looks fun, seems like I can control a remote X session
via ssh.

------
jaytaylor
This looks amazingly cool!

And I apparently starred the repo previously, but don't remember ever having
seen this particular badass shit before.

Am I losing it?

~~~
mdaniel
If your situation is anything like mine, it goes much more like: "oh, neat;
I'll look at that tonight" followed by a browser bounce, or something else
becoming a _bigger_ priority, lather, rinse, repeat.

There is so much great content -- both "empty calories" and otherwise -- that
it is so easy to get buried under it. I came to HN to retrieve _one specific
link_ and ended up with 7 new browser tabs open, counting this one.

~~~
nerflad
HN Tabs are like an unstoppable cancer. I'm on XFCE and I have a whole
workspace dedicated to over a year's worth of articles, books, discussions,
etc from HN that "I'll eventually get around to reading".

~~~
StavrosK
I use [https://www.linkpack.io/](https://www.linkpack.io/) on iOS as my black
hole for links.

~~~
Fnoord
Didn't know about that one. Pocket would also work, esp if you're using
Firefox. Also works on the Kobo e-reader.

Other options I'm aware of are conventional bookmarks, and OneTab.

------
mseidl
[https://github.com/HouzuoGuo/headmore](https://github.com/HouzuoGuo/headmore)

Another interesting project, that's similar, but for VNC.

------
nmg
Finally, good news in the world of computing. The zoom function is a nice
touch...

------
krylon
I expected this to be an elaborate joke, but the author obviously has a good
use case for it. That is quite ingenious!

------
kevin_thibedeau
> Why not VNC?

Why not ssh -Y and use X protocol as intended?

~~~
shakna
> sometimes I don't have very good Internet. If all I have is a 3kbps
> connection

I don't think X would handle that very well, and you may not have an X server
at the other side.

~~~
pvdebbe
3 kbps is not enough for smooth TTY text-only ssh either...

~~~
reaperducer
I've done pretty productive work over much tighter links than that. Think
300bps.

One of the systems I'm responsible for currently can only be reached over a
1200bps dialup connection.

~~~
pvdebbe
But does this work require full refreshes of 80x24 screen or larger?

------
shironineja
Hmm I wonder how many of these I can run at the same ti

------
daurnimator
For more detail, there's sixels, see
[https://github.com/saitoha/libsixel](https://github.com/saitoha/libsixel)

~~~
tombh
I did look into that, but it's not as widely supported as the UTF8 half-block.

~~~
espadrine
With many bytes necessary to print just six pixels, it wouldn't be as low-
bandwidth, right?

On the other hand, how about libcaca?
[https://en.wikipedia.org/wiki/Libcaca](https://en.wikipedia.org/wiki/Libcaca)

~~~
tombh
The TTY "graphics" rendering is actually relatively trivial, it's really just
a few lines of JS in my rewrite now. So there's no need for an external
rendering lib. Also with the new approach, I'm focussing on real text as the
main feature, so you'll actually be able to turn off the colour blocks and
just surf the web as raw text, with all the goodness of full CSS rendered,
realtime text and JS.

------
paule89
Wow. I definitely like the Idea.

After reading the first few paragraphs i also finally understand why it would
be such a great idea to have a blocky firefox.

------
davidcamel
This is awesome, I've always wanted something like this. Zoom is the killer
feature.

------
djsumdog
I wonder how you'd implement something like this in Wayland? Would you have a
composer on the remote side rendering the text to a terminal (that you'd
connect to over ssh/mosh)?

------
moondev
Wow! Can't wait to try this! Coolest thing I have seen in a minute!

------
blice
That's a good idea. I'll continue reading about it.

------
newman8r
very creative, looking forward to giving it a try.

------
sykseh
rick roll opportunity totally missed ;D

------
erikb
Why not stream X directly over ssh?

~~~
rostigerpudel
Because X over SSH requires a somewhat low latency and high bandwidth. The
guy's requirement is unpredictable latency and low bandwidth (like 3 kbps). X
is no fun at all over that kind of connection.

------
cryptonector
Finally, high-performance remote display!

~~~
cryptonector
No sound though :)

~~~
sgc
It's a feature not a bug ;)

~~~
cryptonector
Thus the smiley :)

------
candyman2018
BUy all your drugs at drughouse.store

------
krmbzds
That's fucking nuts!

------
Fnoord
Given the quality of text (or the requirement to zoom) I'm not sure what the
fuss is about. It looks abysmal, and having to zoom all the time is a habit I
am glad we got rid of due to higher resolutions. Though still existing on
mobile devices it is also user-friendlier to zoom there, and the reason for
the feature is the device is more mobile.

You could already run a browser in a framebuffer for ages. Which means you're
not bound to X11. My friend, X11 hater (he was former Amiga user), just used
CLI and a CLI web browser (well, he used Emacs) but sometimes he did need GUI
and that was his solution. We're talking end of '90s/begin of '00s here during
a time where X didn't even compositing.

If you want to run X11 over SSH, that's also possible, e.g. via NX Server.
Another route could be SDN plus (Free)RDP. Mosh is great for latency, tho
can't be used for SSH over Tor due to UDP.

~~~
tombh
I'm actually in the middle of a complete rewrite (I was hoping to stay under
the radar until then). I'm ditching X11 and ffmpeg and actually rendering real
text as a layer over the TTY blocks. See:
[https://github.com/tombh/texttop/blob/webext-
rewrite/webext/...](https://github.com/tombh/texttop/blob/webext-
rewrite/webext/src/text_builder.js#L165)

~~~
Fnoord
Can't edit my post anymore but I just tried Texttop out. I ran it according to
your Quickstart guide in Docker as you suggested. In Terminal the keybinds
didn't work, in iTerm zooming at least works. Whilst I was zooming in, I
noticed my CPU fans suddenly went crazy on my MBP compared to Chrome RDP. The
only time that happens on RDP is when I play a game remotely, or watch a video
remotely. Htop confirmed it was iTerm.App. I didn't see either of these
terminals in your known to work list either.

~~~
tombh
Thanks for trying. Yes the iTerm keybindings are a known problem. Like I said,
I've completely rewritten Texttop from scratch - it's now merely a lightweight
Go binary (to receive a websocket and print to STDOUT) and a webextension. So
it's significantly more performant.

~~~
Fnoord
Tom, my bad. It seems there is a bug in Docker for Mac which causes high CPU
usage [1]. Def made the overheating worse. I'll give it a whirl on a different
environment instead.

EDIT: Just tried it on Windows. Is there a terminal you can recommend working
on Windows? I tried CMD.exe, Powershell, Bash (WSL / Ubuntu) and Cmder. None
worked well.

[1] [https://github.com/docker/for-
mac/issues/1759](https://github.com/docker/for-mac/issues/1759)

~~~
tombh
Oh, interesting, I never tried it on Windows. What doesn't work? Everything!?
Can you make an Github Issue for it?

~~~
Fnoord
I was using RDP. Had different issues with each terminal but am going to try
local, and I'll report the issue(s) on GitHub.

~~~
tombh
Thank you :)

