My final and correct opinions
2025-01-02
The real purpose of this note is to provide a dumping ground to accelerate forgetting: Hacker News endlessly supplies projects that look very cool and potentially useful, and if I spent time with all of them it would fill my life. Instead, they’re noted here, so that next time I see the thing on the front page, I can remind myself that I already thought about it, and forget it again.
Of course, a few make it through the filter, and a few of those turn out to be great.
See also mhoye/moderntools.
This is written by someone who grew up in the 1980s using MS-DOS and Windows, finally realized what unbelievable trash they are around 2006 and bought himself a Mac, and has never looked back. The personal computer has run macOS since then, and work has been some combination of macOS and Linux.
Here are two reasons for strongly preferring the default tooling that comes with your system (like Zsh) over nicer alternatives (like fish).
Default tooling is an almost universal baseline in the Posix-compatible world, and even increasingly on Windows. Fluency with Zsh, GNU coreutils, vim, and friends mean that you can be immediately productive on any random system or remote server you get dropped in to. (Also an argument for limiting your configurations and customizations.)
Most tools don’t pay off the cognitive overhead involved in learning them and figuring out how to use them regularly. “A better version of X” is nice, but unless it’s an order of magnitude better, I’m skeptical of the real payoff. There are exceptions: tmux really is that much better than screen; ripgrep than grep; htop than top. And there are examples where the cognitive overhead is low and the absence of the tool is low impact: eza instead of ls.
The lists below come with verdicts, which are very much just my opinion about whether I’d get value out of the thing. Generally the thing only gets a check if I currently actively use it or it would be my immediate go-to for solving that problem. A lot of these verdicts come from trying it once in 2016 or so. Don’t take me too seriously.
Homebrew(☑), a thousand times yes.
Apple’s Terminal.app(☑) is more than good enough for everything I do. It also has many quality-of-life features that are not clearly documented; I bet many nerds would benefit more from learning the built-in emulator than goofing around with iTerm 2(☒), Alacritty(☒), Kitty(☒), or Ghostty(☒), as cool as all of those projects are.
Use Bash or Zsh(☑), whichever is the default on your system. Don’t use a plugin manager; almost no plugins for Bash or Zsh pay off the cognitive overhead. When you suffer the temptation to customize your prompt, read the manual. When it comes to fancy features like right-handed prompts, bear in mind the importance of easy copy-pasting of shell transcripts.
A number of projects seek to provide, basically, “Bourne-style shell but not as irritating.” Of these, Fish(☑) is just great and gets a check even though I don’t use it. Nushell(☒) stands out for giving serious thought and effort to how commands and process can ergonomically share data types that are more complicated that a byte buffer. For me, it doesn’t answer, “why should I use this instead of Python libraries?” but I like where it’s going the most. Other surprisingly long-lived projects in this space include Xonsh(☒) and Elvish(☒). But coming back to the introduction, it’s difficult for me to see how any of these projects could become a tool, rather than a fun toy — other people and computers will not be familiar with these, and for your own personal system, lower-effort affordances like LaunchBar / Alfred / Raycast seem much more suited.
Oils(☒) gets its own paragraph as the “modern shell” project that makes the most sense to me. It has a different goal: make system configuration and administration more reliable by providing an on-ramp to a modern scripting environment while obsessing about compatibility with in-the-wild sh scripts. If I were in systems administration, packaging, or anything around software infrastructure I’d be paying more attention to it.
Mosh(☑) remains the clear winner for maintaining remote sessions over a flaky connection. The disadvantage is needing to install something on the remote, but the advantage is that there’s really nothing to learn because it relies on the standard SSH tooling for connection configuration and authentication.
tmux(☑) is the other indispensable tool for remote CLI work. Some people also use this locally, which does not make sense to me. The tmux-xpanes project is a wrapper, and heinous added complexity, on top of tmux, but it’s been steadily developed since 2015 (?) and can be useful in situations where you need to, for example, wrangle clusters of machines in some way that’s not worth automating.
Git(☑). Ubiquitous, indispensable, and a fundamentally Good Idea, even if Git’s early competitors like Mercurial(☒) or Darcs(☒) were better in principle. VHS won again, but the world is still better than it was in 2006.
Github has had at least two iterations of a Github-specific CLI: hub(☒) (still online in 2025, but I guess the project is dead?) and Github CLI(☒). I don’t collaborate through Github for work, and am skeptical about such bespoke tooling.
Some projects seek to provide a better CLI experience than stock git. I think Magit(☒) is the best of these, but since I moved away from Emacs it’s no longer in regular rotation. Another example is tig(☒). By and large these types of things don’t provide much added value above your editor’s built-in Git integration, and it’s going down over time.
Other interesting projects in this space are:
Editing text files is a primary activity in the TUI/CLI space. My own journey here: Eclipse (!!!) briefly and sporadically as an undergraduate; TextMate in graduate school; Sublime Text in the first job; throughout, brief flirtations with Emacs and Vim. In the second job, a deliberate head-first commitment to Emacs.
But now I just use VSCode, because I need to actually work.
VSCode is the apotheosis of Emacs.
Others:
sed and awk; not evaluated yet.As someone working in the ML/AI/DS space, Python has been an enormous part of my professional life. 2024 was the year that I could finally breathe a huge sigh of relief.
Use uv(☑). Do not use conda(☒), pyenv(☒), pipenv(☒), poetry(☒).
eza(☑) is a drop-in, strictly superior version of ls, and supersedes tree(☒). Haven’t looked at lsd yet. fd(☑) is a drop-in, strictly superior version of find. ripgrep(☑) is a strictly superior Silver Searcher(☒) and grep.
If I had a need for a TUI file explorer, I’d use broot, nnn, or xplr, and not Midnight Commander(☒).
hexyl(☒) is a nicer viewer than xxd, but I’m not sure the cognitive overhead is worth it. bat(☒) is definitely bike shedding; at that point just use a text editor.
htop(☑) is not only a strictly superior version of top, using it and reading the man page is a great way to learn more about the POSIX process model. Glances(☒) is way too complicated and way too slow.
watchexec(☑) for triggering actions on filesystem events.
just(☒) (source) is very popular and gets a lot of good press on HN. It’s a “command runner” — a place to put a bunch of commands that you might want to run while working on a project. Sort of like a shell script with functions, but it has many nice affordances. It “avoids much of make’s complexity and idiosyncrasies” by not solving the same problem as make — one wonders why they then compare the two. Recipes may be parametrized, imported from submodules, … much like a programming language. I dunno. It’s popular; I’m probably not the target audience.
direnv(☒) is a tool for managing shell environment variables. And also, by extension, a loose standard for files that declare project-specific environment variables and many associated tooling integrations. I’m ambivalent; the problem seems real, and having a standard like a .env file seems not crazy. Do we need a tool like direnv though? Isn’t this what process environment inheritance is for?