[HN Gopher] Ink: React for interactive command-line apps ___________________________________________________________________ Ink: React for interactive command-line apps Author : thunderbong Score : 355 points Date : 2023-05-08 16:46 UTC (6 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | bilalq wrote: | The same tired, disparaging comments for anything done in JS get | pretty annoying. No, there are not 1000+ dependencies. The entire | transitive closure _with_ dev dependencies comes down to 42 | dependencies total. Is that a lot? Maybe, but there is value | here. | | 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. | [deleted] | bweitzman wrote: | Pretty neat. I adapted the state management of hooks to Haskell a | few years ago. Could be used for similar purposes, but there's no | support for templating or styling yet: | https://github.com/benweitzman/hooks | Brendinooo wrote: | I used this a couple of years ago to build a little CLI tool to | monitor a subreddit that people use to sell a commodity. It was | fun to work with! | aloer wrote: | I recently used Ink to build a small debugging CLI for a | websocket-heavy project of mine. All it does is subscribe to a | specific channel and print out the message or send dummy data | when I press a specific button. The frontend websocket code could | be reused easily so it was very fast to do. | | 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. | latchkey wrote: | > I recently used Ink to build a small debugging CLI for a | websocket-heavy project of mine. | | 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! | amne wrote: | I would argue that, based on my experience, most of the code | I'm debugging is not my code so it really doesn't matter how | many tests I write because the problem is I misunderstood how | a library or someone else's code I'm using works or there's a | bug I can't find just with tests. | verdverm wrote: | You're writing code against other's code, the UI seems like | overhead over when you can just have a script that can | effectively do the same thing. | | There is a term called "blackbox testing", which is more or | less what we do for 3rd party code | services anyway. | aobdev wrote: | Automated testing and debugging are not the same | latchkey wrote: | I didn't say anything about automated. | | 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. | verdverm wrote: | most of the time, I write a small amount of code to work | through or debug other's code. It's much easier to be | consistent and capture more workflow in a script. Later | this can be turned into tests or interfaces. Early on, | the script offers much better visibility by typically | having access to a debugger | hitchdev wrote: | [dead] | aloer wrote: | Not everything can or should be a codified test. There's a | reason postman is a billion dollar product. | | Just not as good for websockets | | Ink allowed me to quickly add a simple admin and debug UI | vanviegen wrote: | > There's a reason postman is a billion dollar product | | I guess so, but is it a good reason? It's a fancy ui for | curl...!? | throwaway675309 wrote: | Building a simple debugging tool to monitor your program for | possible inconsistently reproducible bugs and having unit | tests are _not_ mutually exclusive concept. You 're getting | downvoted because you're making condescending assumptions | about the developer. | ajkjk wrote: | that's not what they wanted to do? | xrd wrote: | I tried this a long time ago when I was in love with react. It | felt difficult to wrap my head around the yoga layout engine. I'm | glad others here in this thread seem to like yoga, but I didn't. | And, now I really dislike react for various reasons. | | I would use this if I needed to write a command line app with | nodejs: | | https://github.com/chjj/blessed | lucideer wrote: | Alas | https://github.com/chjj/blessed/issues/418#issuecomment-1533... | | 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. | travisd wrote: | Curious to know -- how do these kinds of things affect | accessibility for visually impaired people? If you're using a | screenreader, do these kinds of things work? | swarfield wrote: | It's really cool, I've used it before and it's super easy. | wstone wrote: | I love Ink. Made a game with it: | https://www.npmjs.com/package/5dice | nicoburns wrote: | There is also Rink, a Rust port of Ink that uses Dioxus instead | of React for the high-level API | https://github.com/DioxusLabs/dioxus/tree/master/packages/ri... | WorldMaker wrote: | It might be interesting to see less Flexbox and more CSS Grid | support. I think that would make certain styles of TUIs like the | Midnight Commander style apps easier to build. | nicoburns wrote: | I maintain a library (https://github.com/DioxusLabs/taffy) that | implements both Flexbox and CSS Grid and is designed to be | easily embedded (similar to Yoga, which Ink is using), if | anyone wants add CSS Grid support to their app/framework. | seanp2k2 wrote: | Back in my day, we had curses and we liked it. | verdverm wrote: | dev hipsters rule the day, we rue the day | DLA wrote: | Just what I was looking for, 1000+ JS dependencies and Yoga's | deps to make a CLI app. Nope. Hard pass. But, I do love the | concept of components for CLIs. I've had much success with the | Charm set of tools for CLIs with Go (https://charm.sh). | evan_ wrote: | > Yoga's deps | | ah yes, all zero of them | | https://www.npmjs.com/package/yoga-wasm-web?activeTab=depend... | h1fra wrote: | Everytime I see this project I'm flabbergasted (in a very good | way) that we can achieve this. | | I wish Node was portable, it would definitely be far more | superior than GO CLIs that lacks this kind of features. | garfij wrote: | A sibling comment points at | https://github.com/charmbracelet/bubbletea as a Go alternative | with a similar architecture | mofle wrote: | Node.js now supports generating self-contained binaries: | https://nodejs.org/api/single-executable-applications.html | h1fra wrote: | oh wow, amazing news. Still experimental, but very exciting! | thanks for sharing | kelseyfrog wrote: | Yoga is a great choice for layout here. In my own terminal-based | projects, I was initially worried that there would be a mismatch | between its intended use (pixel-based layout) and the chunkiness | of character-based layout in terminal apps, but I was happily | proven wrong. Yoga is a great choice for laying out terminal | apps. | | I wish there was as nice a library for cascading style sheets in | terminal apps, but we can't have it all. | blooalien wrote: | > 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. | lrobinovitch wrote: | Similarly there is Lipgloss for the Go ecosystem | shane_b wrote: | this is very good library that i was a little nervous about at | first but i used it to build a custom command line tool for my | business and it's helped so much. it's also very easy to create | fancy cli features that make it feel like a real application. | dang wrote: | Related: | | _Ink: React for interactive command-line apps_ - | https://news.ycombinator.com/item?id=14831961 - July 2017 (42 | comments) | paxys wrote: | This looks amazing. Can anyone talk about the added overhead of | this? I'm assuming having to bundle all of Node.js/V8 in your | executable is one of them. Plus extra processing to re-render the | tree for changes. | | 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. | pzmarzly wrote: | > I'm assuming having to bundle all of Node.js/V8 in your | executable is one of them | | 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 | bombolo wrote: | well node is 30mb but then you need another 30 of js | dependencies most likely. | pzmarzly wrote: | You should tree-shake your imports. And in case of Node, it | exposes V8 internals to generate bytecode, so you can | compile your code - then you don't even need to ship it as | text | lmm wrote: | > 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? | | 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. | paulddraper wrote: | > write a program that outputs a line of text to the console | | Stating the obvious, but if you are outputting a line of text | to the console, don't use this. | paxys wrote: | Why is that obvious? That was exactly my question. | | 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? | paulddraper wrote: | Not unthinkable, but equally dumb. | <!doctype HTML><html><body>Hello World</body></html> | console.log("Hello World") | | This is for _interactive_ CLI. | PragmaticPulp wrote: | > Can anyone talk about the added overhead of this? I'm | assuming having to bundle all of Node.js/V8 in your executable | is one of them. | | 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. | kokanee wrote: | React kind of reminds me of English. It is ubiquitous for | reasons that essentially boil down to imperialism. It imposes | at least as many problems as it solves. There is ample evidence | that we were getting along fine (if not better) without it. At | some point it became the only language many young people know. | | And if React is like English, then using it to write a CLI is | like using Webster's dictionary to translate hieroglyphs. | thih9 wrote: | How does it deal with more complex refresh actions? E.g., the | online jest demo blinks a lot [1]; is that expected? Are there | workarounds? | | [1]: https://replit.com/@vadimdemedes/ink-jest-demo (tested in | safari mobile) | newah1 wrote: | very cool, I'll remember this for my next project in the CLI | tommy_axle wrote: | I'll need to try Ink but you were also able to do this with | react + blessed via https://github.com/Yomguithereal/react- | blessed | toppy wrote: | For Golang there is Bubbletea [1], Textual [2] for Python and | tui-rs for Rust [3]. | | [1] https://github.com/charmbracelet/bubbletea | | [2] https://github.com/textualize/textual | | [3] https://github.com/fdehau/tui-rs | EddieRingle wrote: | There's also Mosaic, which is an experiment of sorts to build | console UI using Kotlin and Jetpack Compose: | https://github.com/JakeWharton/mosaic | fbdab103 wrote: | Is tui-rs actively maintained? Currently 52 outstanding pull | requests and last commit was ~9 months ago. | azemetre wrote: | It has been forked and actively maintained on [1] ratatui | crate. | | You can see this discussion post about it [2]. | | [1] https://github.com/tui-rs-revival/ratatui | | [2] https://github.com/fdehau/tui-rs/issues/654 | xixixao wrote: | Just FYI that neither use React or anything close to it, | they follow the "immediate" rendering approach. | nicoburns wrote: | Dioxus (https://github.com/dioxuslabs/dioxus) is pretty | React like, and has a TUI rendering mode. | midoBB wrote: | I highly recommend Bubbletea. I used it for an internal tool, | and it combined with Viper makes an easy-to-use TUI application | development easy. Though it uses an approach more similar to | Elm than to React. | beebeepka wrote: | I guess I am not a visionary because this makes zero sense to me. | I guess anything react related receives points simply for | existing | FpUser wrote: | Give it another 30 years and they will "invent" Turbo Vision | MuffinFlavored wrote: | Is there really a good reason in 2023 to have an interactive | command line app? I've seen apps that at least maybe display a | web server on localhost and then interact with it through the | browser | | 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) | pmarreck wrote: | The end-user of these things is not manager types... and that | is both OK, and probably part of the point. | | I personally love the growth of fancy, responsive TUI's. SSH- | friendliness is a huge feature IMHO. | bstar77 wrote: | Just look at the "Who's using Ink?" section and that will | answer your question. | paxys wrote: | 1. Command line UIs are still an order of magnitude easier to | build than even the most basic web page. | | 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. | mhink wrote: | > Command line UIs are still an order of magnitude easier to | build than even the most basic web page. | | 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.) | interroboink wrote: | > tinkerers and not anybody serious | | 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. | graypegg wrote: | Yes definitely. Being able to easily access them via a remote | shell is a killer feature IMO. Being able to pipe + automate is | useful too if used non-interactively. | MuffinFlavored wrote: | > Being able to easily access them via a remote shell is a | killer feature IMO | | You mean like being able to access a web page? | graypegg wrote: | Hah, that is a fair point. | wolletd wrote: | I have systems that have no web server and don't need one | and adding one would add complexity and potential security | risks to the system. Administration is only done via SSH. | | 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. | int_19h wrote: | Thing is, if you can establish an SSH connection to the | target machine, you can easily tunnel HTTP over that. And | it doesn't need to have a dedicated web server service | for that; the app can embed a localhost-only HTTP server | directly. | | 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. | MuffinFlavored wrote: | I don't disagree with you, I'm just devil's | advocating/showing an alternative viewpoint: | | > 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 ... | wolletd wrote: | From my point of view, I'm not actively making it harder, | I just don't make it as simple. | | 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. :) | codetrotter wrote: | All of the things you listed are still additional steps | compared to just ssh and run the cli tool. Web UIs are | nice too, for some things. But for many things, for at | lot of us, the cli is where it's at. And that is where it | will continue to be. | | We use Web UIs for some things, and cli tools for other | things. | lost_tourist wrote: | * lower bandwidth | | * 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 | gofreddygo wrote: | "Ink" and "interactive" in the same sentence has a strong | association in my mind for Inkle's Ink [1] | | [1]: https://www.inklestudios.com/ink/ | pimlottc wrote: | This was my immediate first thought as well, I thought it was | perhaps a React-based implementation of this existing product. | pranshuchittora wrote: | Glad to see this lib on #1. I have built a CLI tool called | Autarky a long long time back | https://github.com/pranshuchittora/autarky. | | 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. | koromak wrote: | Wow, those are some big names. Never heard of this before, very | cool. | claytongulick wrote: | [flagged] | Shorel wrote: | Why would it be called Ink if it doesn't recognize my laptop's | pen? | | It makes no sense, just more search engine noise. | | FYI: I use the pen with a gnome app called Write, in Ubuntu | 22.04. | thiht wrote: | It's like how Firefox doesn't have anything to do with foxes or | fire, wtf | enricozb wrote: | I tried (and sort of failed) to build something like this for | rust [0] (warning it's broken at the moment). | | 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/ | jacobp100 wrote: | Very glad to see gap support added. I was playing around with a | fork to add it, but didn't get much time to polish it up | brundolf wrote: | Very neat idea. I love how decoupled React is from the different | renderers, and how well its paradigm of "render a tree of things | that updates as state changes" translates to different kinds of | UIs | mhink wrote: | One of my favorite side projects (from several years ago now) | was a custom renderer implementation that let one use React to | manage the parts of an Electron app _outside_ the page being | rendered. [1] I never found the time to actually go through and | make it robust enough to use in a production setting, but I | remember being very pleased with how much easier it was to use | than the native Electron APIs. | | Maybe I'll revisit this sometime. :) | | 1: https://github.com/mhink/react-ionize | brundolf wrote: | Hah, that's pretty cool! | blackbear_ wrote: | React is indeed really neat. At the same time, however, I miss | the visual drag & drop GUI designers that were in vogue a few | decades ago. HTML and CSS are the tragedy of modern UI design. | manojlds wrote: | That's what a lot of low code platforms are trying to | achieve. | kaeland wrote: | Try CLOG, https://github.com/rabbibotton/clog | seanp2k2 wrote: | I view the rise of React and especially Electron as the | failure of things like GTK, Qt, and e.g. Swing to make a | useable cross-platform GUI toolkit that isn't a total | nightmare to work with / compile / debug / install / | package...it's literally easier to ship [most of] an entire | web browser instead. That's insane to me. | lockhouse wrote: | The drag and drop GUI designers used to work because most | people were using screens that were approximately the same | size and resolution for the most part back then. That is no | longer the case today when there is pressure to support | everything from a smart watch all the way up to a UHD 4K | monitor or TV. Fixed layouts are also much more difficult to | localize and translate to other languages than modern layout | systems. | Cthulhu_ wrote: | And yet, I found Apple's Interface Builder to work pretty | well, for apps that should work on phones and tablets in | both portrait and landscape mode. | | Mind you, this was a long time ago now. | nathancahill wrote: | Apple's IB used a constraint-based layout by default. It | was a fairly novel idea at the time. HTML was ill-suited | for that until flexbox/grid came along. | pcl wrote: | Yeah, it's stunning how many UIs fit within their struts | and springs model, and how well they model scales to | resolution changes. | WorldMaker wrote: | It's one of those "grass is greener on the other side" | situations. | | 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. | Shorel wrote: | The grid system of wxWidgets also works like that. | | 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. | jalk wrote: | And you can search/diff the pure text representation which | is a major plus as well. I absolutely hate the workflow of | constantly moving the mouse back and forth between the | visual components and some gigantic property panel sitting | at the edge of the window (index-finger programming). | Floating windows are even worse, as they always seem to get | in the way, so now also spend time on window ceremony | (moving / resizing the "floaters"). In graphics | tools(InkScape for instance) I almost always move objects | around using the cursor keys as my mouse based positioning | skills are just not accurate enough (and I know that I'm | not the only one) | | Anybody have good examples of tools (graphics editors for | instance) that has a good alternative to that clunky | property pane? | rcme wrote: | Have you tried WebFlow? | holoduke wrote: | I worked with many different UI kits. From native windows to | Ubuntu to automotive to embedded to Android to Apple. I find | HTML and css by far the most convenient UI toolkit there is. | Never have creating UIs been so easy as with css. A relief it | is. | kamikaz1k wrote: | you can use drag and drop GUI builders on top of react. | there's been a lot of attempts at that. a significant recent | effort from Wix: https://www.codux.com/ | Alifatisk wrote: | I am both afraid and impressed. | vanjajaja1 wrote: | same, I can't decide if this clever and going in the right | direction, or solving the wrong problem the wrong way. very | unique, either way | brabel wrote: | Check the list of apps using it. | | 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. | [deleted] | nitwit005 wrote: | It's sort of impressive, but feels like it'd take more time to | figure out than to make your app work using the "raw" nodejs | tty and readline APIs. | lost_tourist wrote: | Honestly react seems a bit heavy for this when a lot of much | lighter alternatives are out there | dingosity wrote: | kill it. kill it with fire. | | though to be fair, ncurses isn't a joy to work with. | robertoandred wrote: | Why kill it? What's wrong with CLI interfaces? | retrocryptid wrote: | There's nothing wrong with CLIs. Emulating the idiocy of HTML | in the terminal window is... suboptimal. | | (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.) | jitl wrote: | This seems to be much nicer than ncurses, since it's a | declarative interface rather than an imperative one. | Outside of Flexbox, there's nothing HMTL-specific in the | API. An XML-like syntax is used because UI on most | platforms is conceived as an ordered tree structure, such | as Windows (XAML), Apple (XIB), Android, and Web (HTML). | | The built-in components are all conceived as TTY-native | ideas, not as HTML concepts: <Text> | <Box> <Newline> <Spacer> <Static> | <Transform> | robertoandred wrote: | React isn't HTML. | lwansbrough wrote: | Holy semantics. JSX is based on XML, which HTML is also | based on. I think GP just hates React and JSX, which is | valid. ___________________________________________________________________ (page generated 2023-05-08 23:00 UTC)