Ink: React for interactive command-line apps
github.com
github.com
[1] https://github.com/charmbracelet/bubbletea
You can see this discussion post about it [2].
https://www.ruby-toolbox.com/categories/terminal_ui?display=...
Very convenient to run multiple terminals as multiple clients in parallel. Much nicer at least than something like Postman for Websocket tests.
Full screen took some time to get right and still flickers when using iterm 2. But it does work on the apple terminal and for now I am happy with that.
My only issue is that Ink does not support nested rendering / overlays, i.e. modals.
why not just write tests?
i'm getting super down voted on this, but come on... why? this person built some buggy utility and those bugs can end up causing more problems than just writing tests in the first place.
no wonder we end up with such buggy junk software... people... write tests!
99% of the time, I debug using tests. You write the expected output and then fill in the implementation. If you don't get what you expect, something is wrong with your code and it is easy to run it in the debugger to figure out what is wrong.
At the end of that, you end up with a test and some code that works.
Other people call this TDD.
Yes. They made their own purpose-built debugger. It's a tool that makes it easier to see what the program is doing. Your debugger is no more or less valid than their debugger. It's a tool, and the best tool is the one that enables the programmer to accomplish their goal. And that's what they did.
There is a term called "blackbox testing", which is more or less what we do for 3rd party code | services anyway.
Just not as good for websockets
Ink allowed me to quickly add a simple admin and debug UI
I guess so, but is it a good reason? It's a fancy ui for curl...!?
Now I’m wondering your thoughts on Burpsuite
And wondering if you feel GitHub is just a fancy UI for git lol
websockets themselves are well debugged, similar to http. years ago, i stopped spinning up a http server just to test my endpoints. now i just call the functions directly. thus, it would be an issue with the OPs code that is sending/receiving. take websockets out of the equation and everything would work fine with tests.
Friend, we need to be damned careful about how we view others code when they don't have tests or embrace TDD.
When we work with TDD or even a well tested codebase, we do benefit enormously.
We also risk becoming evangelical, and that almost always comes across as condescending and off-putting.
TDD Tests do not capture every possible point of faillure. There's clear use cases for things like Postman, Debugging Proxys, or OPs _debugging_ tool.
PSA - avoid being a hype monger or evangelist of anything, it's about the worst way to support practices or tools you believe in. Trust me, I'm not only a practitioner of TDD but also a Lisp advocate and Emacs user... All these things are the best ever thing that happened /s
No, the whole world won't ever be a place where everyone is "doing it right" by your estimation, or mine, or anyone else's.
Quite the opposite, so settle in and mellow your jets.
i'm not being evangelical by asking a question.
i'm also not trying to start a sermon. my response was to explain where i was coming from because i was being called condescending.
i don't care about doing it right. i can ask why someone would write a tool, instead of using one of the existing ones... or writing tests.
my jets are plenty mellow.
absolutely condescending and holier than thou. I view TDD as a premature optimization when writing software that isn't simplistic or cut-and-dry CRUD. Trying to do something new doesn't always mean there's a known output before writing the actual code. Experimentation is a valid thing in software development and writing tests before writing the code would stifle some types of development. In a lot of cases it's bass-ackwards to write tests before the implementation is producing a useful result. I know this type of development might seem foreign to some, but you don't always know what you don't know before you start experimenting while writing code, and TDD doesn't really fit all types of development.
That was an update after I was downvoted.
You're right, there are reasons to not always do TDD. Writing a tool to inspect websockets, isn't one of them.
What kind of developer makes a blanket statement like that? There are all kinds of situations where debugging is more like detective work. When you discover the problem, then you have the knowledge necessaryto actually write the test that fails and which you can then make succeed.
One with over 20 years of experience building software used by millions of people daily.
You're trying to generalize a very specific conversation.
OP was talking about building a tool to debug websockets. You don't need to debug websockets, you need to debug your code that is sending and receiving data _over_ websockets. In that case, you don't even need websockets at all. Meaning you don't need a tool to inspect the data either. Just make sure that your code is sending and receiving the correct data and you're done.
Of course, if you want to build a tool, go ahead... that's your choice, but my question is still valid. Why not write tests?
TDD "evangelism" is often toxic and abusive. The actual practice of a functioning TEAM (not just the devs) who know what it is and how it works, changes things fundamentally for the better.
Spikes are used to do the "whimsical" how the F do we do Y, parts. XP devs don't TDD those and the code is usually tossed out (with the good bits used to help build the production code.)
Similarly TDD isn't a religion, and only an fool would apply it like one. The good parts are, you get a test suite, you get developer examples of how to use a unit, you get an extra step to think about naming, so you're _slightly_ less likely to be saddled with a poorly thought out API / naming scheme.
It's broadly useful, helps teams integrate code, much faster.
Everyone needs to be playing the game, though, and they need to know the rules.
C2 wiki is about the best place to find organic conversations about XP and TDD (archived though, so no sanctimonious claptrap from the likes of me), and the wide internet is a great place to get polarized.
I'm sorry you got a bad taste, and it may have put you off, but a functioning TDD team is about the sanest, quickest, dev team you'll have the pleasure of working with. While, as you've found, an oppressive diktat to DO TDD PROPERLY when the team isn't really doing that, is hellish.
That's assuming quite a bit and not at all true in all cases. I deal with websockets with wireless IoT devices and I can tell you that your insistence that debugging websockets doesn't require writing any custom tools is just wrong.
So great, you wrote a test that passes. Your test runs it once. Maybe your test runs it twice. But what happens when the IoT device fails in an unexpected way after the 150th run? Your test isn't going to catch that. If you ran tests repetitively then your test is never going to finish in a reasonable amount of time. Do you think running the tests for an entire day is reasonable? No. That's why sometimes building a "debugging CLI" like OP wrote is needed.
Not everything can always be debugged with a simple test, or any kind of test. Network congestion effects can be tricky to work out. Memory leaks in remote devices you don't control. There's a whole lot of reasons why tests aren't always the catch-all some people think they are. I'm not saying don't write tests, just don't go around suggesting they're a cure-all.
Don't believe me? Jespen is a great example of difficult distributed testing done well: https://jepsen.io/
Ok.... why?
So you're first instinct is to write a tool to inspect websockets?
I’m trying to figure out if Ink enabled you to do something at all, made it easier, or you just liked using it. All of which are fair. It seems like you just liked using it.
Sure you can do that other ways. Personally I’d love to build terminal tuis with react component!
I have it integrated into a bigger CLI project where only a few commands enter the UI. Most of them just render to stdout and are meant to be pipeable
It's a lot harder than I expected. Especially since the terminal has no notion of focus, and with Rust it's really hard to not just clone everything you get your hands on when writing a UI library. The borrow checker really feels like it gets in the way of features like signals [1], and partial re-renders.
[0]: https://docs.rs/intuitive/latest/intuitive/ [1]: https://preactjs.com/guide/v10/signals/
I'm currently bouncing back and forth between VB6 and HTML/CSS and yeah sometimes it is nice to just quickly drag something into place, but other times I really wish I could just use a layout system like CSS Grid (or Flexbox) and give it all the items I need and let it figure out how to lay it out.
For instance, recently I had to edit some "tables" in VB6 that turned out to have been hand-drawn with pixel-perfect lines and changes were incredibly slow and I would have murdered for that to be in HTML/CSS.
Sometimes I like (and miss) the best of both worlds in XAML where it has drag-and-drop design tools, but also the copy-and-paste and handwrite support of XML, and it has modern layout tools like Grids for auto-layouts/responsive layouts.
Anybody have good examples of tools (graphics editors for instance) that has a good alternative to that clunky property pane?
It has drag-and-drop design tools, and copy-paste, and it can be written programmatically.
So the best of both worlds exists, and it is just not used enough.
wxWidgets has Python bindings.
Mind you, this was a long time ago now.
Replace "compile" with transpile, "install" with deploy that are the same things anyways and it sounds like most projects done by web developers.
>"That's insane to me"
Congrats
Yes, Electron is bad, but there are alternatives in progress. Layouting with HTML and CSS is here to stay. It's like git, the best of all the worst tools to get the job done.
Maybe I'll revisit this sometime. :)
I'm wondering if this is worth it to use for very simple CLI scenarios that can be addressed by more lightweight libraries like Cobra. Maybe so your client-side business logic can stay more unified?
It's also really funny to me that what is considered the absolute simplest use case in programming – write a program that outputs a line of text to the console – is still not free from the Node/npm/React experience.
Stating the obvious, but if you are outputting a line of text to the console, don't use this.
For example using React to generate a simple "hello, world" style website is overkill but not totally unthinkable. Is it worse for the CLI case?
<!doctype HTML><html><body>Hello World</body></html>
console.log("Hello World")
This is for interactive CLI.I guess you could expect Linux distros to come with Node (though it's probably a quite dated release). Looking at standalone binaries, both bun.sh and Node.js are about 30MB. In comparison, Python 3.10 is 9MB and starts slower than bun but faster than Node. Bundling is easy too, you can take a loot at vercel/pkg https://github.com/vercel/pkg
And if React is like English, then using it to write a CLI is like using Webster's dictionary to translate hieroglyphs.
The primary use case for this would be CLI apps that are already written in JS or TypeScript.
Trying to use this as a front-end for a CLI app written in a different language isn't impossible, but it's a lot of extra work. You'd be better off looking for a similar CLI library in the language you're already using.
I'd say yes. Performance will be "good enough". Disk space use or whatever other nonsense HN people love to fret about will be "good enough". And the gains from reusing the same stack everywhere are worth it. I used to think writing little helper scripts in a JVM language (Scala) was an unacceptable overhead, then I realised how low the practical cost was.
My only real complaint is how everything in your VDOM seems to re-render on a state change. IIRC this is being addressed [1], but is something to be mindful of, especially if your users may be using slow machines.
I wish there was as nice a library for cascading style sheets in terminal apps, but we can't have it all.
In Python we have Will McGugan's "Textual" framework which supports a form of CSS designed specifically for terminal apps.
Ink: React for interactive command-line apps - https://news.ycombinator.com/item?id=14831961 - July 2017 (42 comments)
The ESM transition has by far been the biggest pain point of working with JS/TS these last few years.
EDIT: Got it working. Was still a lot more painful than I wish it was. Definitely not converting anything else to use ESM until the landscape here improves.
The promises of "easy" and "features" where they don't belong, like using JS and CSS in TUIs is tech debt, security concerns, and resource waste waiting to happen.
Picking on a convenient victim, say Rust, it has: cursive, tuikit, ratatui, and termion that make for powerful, safe, performant, and maintainable code.
It's always cute when absurd things are made possible, but some ideas are impractical for anything beyond toys. If you want toys, sure, do anything and go nuts with it.
It's exactly the same concept, but for Jetpack Compose, the primary toolkit used in modern Android apps.
You can use it in desktop JVM apps written in Kotlin.
Ink is great to get bare minimums up and running, but the capabilities are quite limited and you can't build full blown interactive dashboards with this like HTOP etc.
Every time I see a tool that seems usefull its a hassle to install the correct node environment for it to work.
It wasn't.
I guess it might be good for dynamic apps, but I just love having control over exactly what I a printing out. I'm still looking for a way to write cli apps that also can be accessed from a browser. I always find myself wanting better log viewing functionality - like folding, grouping, search, etc. But there is something so nice about the terminal vs gui. I always avoid gui because the toolchain is horrific and then you have to think about the API layers and everything becomes overly complex and slow.
I wish Node was portable, it would definitely be far more superior than GO CLIs that lacks this kind of features.
I would use this if I needed to write a command line app with nodejs:
I considered blessed for a recent project, but ended up just simplifying the approach & making do with Inquirer + Meow instead due to the maintenance status. Haven't found anything else equivalent to blessed, other than Ink.
Can you link to those other projects you used? I'm not familiar. It would be awesome if you had a write-up
inquirer for interactivity/input (select, text, boolean, etc) https://github.com/SBoudrias/Inquirer.js
This one got my attention: https://github.com/sindresorhus/emoj
I do use emojipedia.org quite often, so I must admit I find this would be quite useful :D. But the thought of having a framework like React powering this behind the scenes, right on my freaking terminal, makes me think that there's no hope for future generations to keep software development simple, "lean" for the foreseeable future. Imagine using 100MB to search for emojis.
and yeah i'm aware of lynx
maybe there's some sort of midground where an app is both a display thing and a terminal thing. not sure, but feels like it needs exploring
It was a lot of fun to make and stylize, but felt slower than it should. I guess it was the “layout stage” (IIRC lots of h/v-boxes).
It was 2 years ago and seems like it’s been well maintained, so maybe they sorted those things out.
[1]: https://replit.com/@vadimdemedes/ink-jest-demo (tested in safari mobile)
just kidding, this seems interesting.
Something like this with vue should be possible right?
ah yes, all zero of them
https://www.npmjs.com/package/yoga-wasm-web?activeTab=depend...
though to be fair, ncurses isn't a joy to work with.
(n)curses isn't great, but the joy of ncurses is it's so bad you know you need to replace it (or more likely layer something on top of it.)
But... clearly... if you like react on HTML and want to have browser-like rendering of text on your terminal than more power to you. I'll go off now and build something that demonstrates my concerns. Thx for not severely down-voting my comment before I could begin to clarify...
The built-in components are all conceived as TTY-native ideas, not as HTML concepts:
<Text>
<Box>
<Newline>
<Spacer>
<Static>
<Transform>I wrote a disk drive monitor in Ruby in an afternoon using curses to crop the window and reduce flashing of redrawing.
Basically I mainly want to use the styles
As someone who's authored many CLI tools in the past, libraries like oclif, ink, inquirer, etc were game changers. A little overhead for UX rendering is not material to the performance for many CLI tools. The actual byte streaming/processing and any network calls dwarf the handful of milliseconds you could save by rendering in some more "optimized" way.
Being able to render visualizations, handle user input interactions, and responsively re-render are very useful things.
Or Electron, etc.
I feel like command-line is alienating (deliberately, obviously) a huge portion of potential users. It basically guarantees whatever you made will only get used by tinkerers and not anybody serious (like if I have to pass a proof of concept pet project along to my manager, terminal might make it a non-starter 85% of the time)
You mean like being able to access a web page?
There are just situations where the question goes the other way around: Is there any need for _more_ than a command line interface? No. Anyone competent enough to do anything meaningful on that server is also capable of doing it via command line.
> Is there any need for _more_ than a command line interface?
Reworded: is there any need to make this harder to access than the equivalent of:
* kube-forwarder + open Chrome to http://localhost:3000
* ssh -L ...
* ngrok ...
We use Web UIs for some things, and cli tools for other things.
My development process usually starts in the terminal, as I am a terminal user and do iterative development there as well as tinkering with system interfaces.
A CLI is the natural first product of my development. Building a web interface is additional work. Also, it's been a decade since I have written any reasonable web frontend.
Granted, it's not a real TUI with curses and stuff, but I like to do some eye-candy with escape sequences. Because I am the most frequent user of my tools and I always like seeing something I deliberately made look good. :)
One could argue that this is extra complexity... but I don't think this argument flies in comparison to "React for CLI", especially once you take into account all the dependencies.
"Note that disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders."
Counterpoint: tinkerers have a lot of overlap with the "serious" users for many CLI apps. People who want no-frills functionality. People who want things to run over N-deep nested SSH hops. Y'know, "unix-y" people (:
I use things like ncdu and vim on remote non-graphical systems all the time, for instance.
Though I do agree that non-interactive is the primary use-case for most CLI stuff.
2. Every app doesn't have to target every user in the world. There is an entire category of developer-focused tooling that is very suitable for the command line.
3. There are plenty of contexts where the command line is the only interface available.
I think by "interactive command-line apps", parent commenter is talking more about "TUI applications" like e.g. `htop` or `vim`- which are persistent/interactive and treat the terminal as an interactive, 2d canvas into which they render the program content. As opposed to what I'd call "normal" CLI applications, which typically render output and expect user input on a line-by-line basis. (Like most REPLs, or the various ctl programs like `kubectl`, `pgctl`, etc.)
* easier to write
* great if you use terminal only remote
* likely faster keyboard interaction when you get used to it.
At least that has been my take on the situation
I personally love the growth of fancy, responsive TUI's. SSH-friendliness is a huge feature IMHO.
It makes no sense, just more search engine noise.
FYI: I use the pen with a gnome app called Write, in Ubuntu 22.04.
There is Microsoft Windows Ink which does handwriting recognition.
Think about namespaces, in the software namespace, Ink is a loaded term, and most of its use has nothing to do with command-line apps.
This is far closer to a Rust implementation of the readline library. Again, nothing to do with pen recognition software, which is the common use of Ink.
Just look at this list:
They called it Ink because they considered the terminal is a canvas where you draw stuff. That's it. There's no way anyone will ever confuse a CLI rendering lib with an OCR or a vector graphics editor or whatever.