The command line still provides vastly more power and flexibility than GUIs for numerous tasks. Comfort on the command line is often one of the things that distinguishes great engineers and data scientists I know.
I’m often shocked when I look at other peoples’ desktops and see a bazillion icons in their docks and taskbars. A GUI app for every conceivable eventuality. Many of them, just shiny wrappers around very simple programs. This contrasts rather sharply with my own minmalist philosophy which has been as simple as three program icons in the Dock: Finder, iTerm, and Firefox (and in Solus, just Firefox since Guake is tucked out of the way, see below.).
By necessity, gui’s simplify complexity through presenting only the minimum interface or most common operational elements required. This means that a lot of the power of more complex programs or the shell and OS itself is either buried in hard to get menus out of the way, or not present at all in the sacrifice to streamlining. However, as developers and data scientists, having sharp knives and being able to use heavy lifting machinery is part of our metiér, so becoming better means rolling up your sleeves and getting comfortable with the power that operating proficiently on the command line gives you. I’d even go as far to say that I only think you can be a good engineer or data scientist if you have decent command line fu.
And it’s not just about speed, interoperability, access to internals, and low resource usage. CLI tools have come an incredibly long way as people have simplified, standardized, and beautified in order to get just the essence of what is required from their CLI computing. In fact, in numerous cases, command line tools are much more efficient, faster, and vastly cheaper to use (especially in data science - I highly recommend this book by the way) than spinning up expensive and inappropriate Spark clusters, cloud clusters, or using advanced graphical tooling (What are those 16GB of memory on your i9 chipped Macbook Pro for if you’re just using it to connect cloud resources anyway?). In fact, GUI or cloud based tools in these cases are often a blunt, oversized mallet being applied to the task where clear thinking and more precision might get you further. Add the ability to use various small, task-specific, super-efficient tools in chainable, programmatic ways and you can do things that put GUIs to shame and in ways that will make you faster, stronger, and cheaper.
While I’m not quite as fanatic as others who call GUIs bloated and useless, and insist on trying to do everything on the command line or in vim, I find the main reason people shy away from the command line is inaccessibility and a lack of guides showing them how to make it a good environment and how to string a lot of simple tools together into a coherent stack. That, and perhaps the bleak, existential void of a blinking prompt and blank screen with little other help looking you in the face, some demonstrably better programs than your shiny gui interface, and, well… a little less ugliness to your terminal.
Here’s a place to start on a better environment to inhabit on the command line:
- Upgrade your terminal
- Fish shell
- Package Managers
- A terminal editor
1. Upgrade your terminal
I have to admit one of the biggest problems with the terminal is the fact on most operating systems, even Linux, it is largely a naked shell to access the underlying programs and systems. Intimidating and ugly, it is no wonder people avoid it. On OSX, you need to dig to find Terminal.app and in Windows, most people never, ever even touch it, it is so reviled.
On OSX I’d recommend swapping out the basic Terminal.app for iTerm2 which is a free download. To be honest, iTerm2 just kicks up the niceness of the terminal a bit, adding anti-aliasing of text, ligatures, and a number of other nice features that make it a way nicer experience visually for a user. There are other niceties in there, that were absent from Terminal.app for a long time, though Terminal.app has closed the gap on many of those since the initial release of iTerm2. However, better display in iTerm2 (and the fact it is GPLed) should put it over the top for you, though personally I’d love it if Guake was available on OSX. For me, I generally use iTerm2 full screen and then use full screen shipping to shift into it (or full screen emacs) with a simple key combo (CTRL-➜).
On Linux, I highly recommend the excellent Guake terminal. If you ever played Quake back in the day, there was a cool roll-down HUD terminal you could invoke to get cheat codes. This kinda works the same way and where it gets it’s name from. On my Solus system, I have Guake hotkeyed to rolldown instantly when
is invoked. Heart this. Keeps the terminal tucked out of the way but instantly available and Guake is very low on resources. The only thing I wish is that Guake added the ability for Alt-Tab` to be able to access Guake when you’re switching windows in Linux. It is annoying not having it.
Let’s face it. Terminals don’t get a lot of love on the pretty. While there are colours and themes available for terminal to make your life a lot better, it seems a lot more time gets spent theming GUI text editors like Sublime, Atom, and Visual Studio Code. We can change that, and it makes for such a much nicer experience all-round, for you, our newly converted CLI user.
Themes and colour schemes are a very personal thing but I tend to focus on ones that are low contrast and darker (to avoid eye fatigue), and possess well-designed and well-thought colour palettes. For the terminal I am a big fan of Arctic Ice Studio’s Nord colour scheme (while in emacs I use the now-venerable Doom theme Spacegrey outside of the cli.).
Getting Nord for the terminal is pretty easy and a simple import and change of Default settings. You can
git clone the repo at https://github.com/arcticicestudio/nord-terminal-app or simply download the Nord.terminal from in the xml directory in the Github repo. Import that into Terminal or iTerm2 and off you go. The sister repo to change iTerm2 exists here: https://github.com/arcticicestudio/nord-iterm2. For Guake, you’re in luck as there also exists https://github.com/arcticicestudio/nord-guake and a simple bash script to install it.
Fonts make a big difference to your command line experience. A well-designed monospace font is key to making things look good, line up, and make your terminal experience more orderly and productive. Numerous fonts now can also be patched with powerline, a way to have emojis and icons inline in the font files and make the experience of using the terminal just, well… better. Also, make your font larger. Especially with today’s screens, the defaults for the terminal that generally ship make the experience too squinty.
There is a long list of Powerline patched fonts here on github you can use and experiment with. On Ubuntu and Debian system you can just
sudo apt-get install fonts-powerline to get them but if you’re on OSX you’ll most likely need to
git clone the repo and then use the Font Manager app in OSX to install them. Experiment with till you find something to your tastes. Just about any font though can be patched, so googling will generally get you what you want, or you can go through the process yourself of doing the patch.
PLay and tweak this a little till you find something that is aesthetically pleasing. I personally have settled on a 14pt Fira Mono font though was using Hack and Inconsolata for a long time before that. In iTerm2 you’ll need to change the font in the Default profile and fo through a similar process for the Nord default profile in Terminal.app, but it’s fairly straightforward.
3. Fish shell
I personally find one of the biggest impediments to people getting comfy on the command line is the choice of shell itself. Even people who are amazing at vim and on the command line every day will probably be hard pressed to admit they are powerusers of the shells zsh or bash. I find both bash (the default for almost everyone) and zsh (said to be the default in the next version of OSX btw) mired in a dark, incomprehensible past that, while POSIX compliant (don’t worry about it), really does not lend itself to people getting comfortable and productiveusing the shell. Even for experts, the shells tend to be difficult to use, script, and debug.
So, a while back, I changed my default to the Fish shell, the “Friendly Interactive SHell” much to the horror of my zsh-loving cadre of developers. I have not regretted it since. It made me much more productive and understanding of what my shell was doing within a day or two.
The fact the web site says “Finally, a command line shell for the 90s” should give you an indication of the state-of-the-art previously, but the fact is it does autocompletions, has history, scripting that makes sense, and has a whole host of niceties that just will make it easier to bend to your indomitable will. It also supports 24-bit colour, and things like syntax highlighting are built-in which means you get a much nicer user experience. There are a host of fish package managers out there for it to take advantage of other peoples’ contributions to the community, and just in general, switching over was shockingly painless. Problems I thought I might have, never materialized (and if you do ever need bash for a script or to run something, you can always just type
bash at the command line to get that shell temporarily, though I’ve needed that so rarely I hesitated to write that parenthetical down.).
Afaik, Fish is available for every existing linux system from their package manager (so,
sudo apt-get install fish or
sudo eopkg fish), and a simple
brew install fish from OSX homebrew package (which I definitely suggest using.).
Once installed, fish will be added to the shells list on your operating system, so you’ll also need to issue the following command if you want to switch to it as your default
chsh -s /usr/local/bin/fish (if you just want to experiment at first and keep bash as your default, just type
fish in the bash prompt and you’ll be using it till you type
Customization is easy compared to other shells like bash and zsh and a little reading will have you bending fish to your will with not a lot of effort. Moving off my old command line prompts from bash (which, I have to admit I copied mostly from blog posts, and poked at modifying, though rarely truly understood), after a bit of reading of fish’s well documented manual, I was already easily creating my own Cousteau theme which takes advantage of the Nord colour scheme and riffs off another design from Chris Morell. You can check out and grab the Cousteau fish theme here (and would love suggestions on how to improve it.).
4. Package Managers
Ther eis al ong history on Managing the myriad applications individually that are going to make your life better on the terminal would be madness. The philosophy of connecting lots of small, specialized tools means that you tend to have more of them. This is where package managers come in. If you’re on Linux, you’re probably using one already of either
On OSX, since it is focused much more on the GUI and installing that way, there is no native package manager, though the de facto choice these days is homebrew. It will allow you to install, delete, stay updated, and handle the dependencies behind the myriad programs you are going to start taking advantage of with your new life on the command line (it will also manage many binary programs in Apps via its
Installing is as easy as pasting the following into your terminal on OSX:
1 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install and friends are now at your command and you have a ridiculous choice of being able to easily install things which were once difficult.
Besides package managers for applications, you’ll notice package managers come up a lot wherever simple programs can be enhanced or have functionality added to, which happens quite a bit in CLI land. In particular, text editors like vim, emacs, and Visual Studio all have package or plugin managers and shells like zsh and fish do as well. They’re a good thing to use actually since they keep things cleanly configured and allow a high degree of interoperability with other programs without conflicts between adds, software versions, or config conflicts.
With Fish shell, I use the excellent Fisher, which also works with the
Oh My Fish package manager and is a riff off zsh’s ubiquitous “Oh My Zsh”. Easy to install and understand, with a simple, terse command set, it let’s you manage things easily and gets out of your way. Very handy.
Back in the day, when you used to have to dial up over a line to get into your Uni’s mainframe (yeah, I did that), you’d often need to do more than one terminal would allow. Combining multiple terminal sessions into one apparent terminal window session (multiplexing them) was the job of the venerable
screen terminal multiplexer which would also make sure if your line dropped, your session continued on without you (
Screen was very long in the tooth, and had its issues, so
tmux was written which was a more modern take on the terminal multiplexer. While most people now use it merely to create “screen tabs” for their terminal sessions, it is much more powerful than that.
Basically, it allows you to create new terminal sessions, switch between them and use them at will. Super handy if you need to multitask or have a preference for running apps in the background rather than one at a time. I would personally say that tmux is what makes the terminal truly useful as someplace to do a lion’s share of your work in, rather than as something you just switch into to run a simple command to get somethign done.
Installing tmux is a simple
apt install tmux or whatever your package manager is. On OSX, just use the homebrew again to get it via
brew install tmux.
Diving even deeper, you can save specific tmux configurations via tools like
tmuxp to launch setup series of tmux tabs which allows you to have an instant setup every time you want to develop or, as I do in my case, launch a set of programs ready for instant use or availability by tab.
The other fantastic thing about tmux is the fact that is handles session state for you, so even if your terminal goes kaboom, you can issues a command to reattach to your tmux session and everything should be precisely where it was when things went sideways. This is so handy, in fact, a lot of people use a session saving plugin that persists startups since this is very handy if you’re on a laptop or zipping around between meetings, cafes, or co-working spaces. So handy, in fact, I’ve got this setup as a startup command to fire off whenever I fire up the terminal with a
tmux attach -t C || tmuxp load ~/.tmuxp/c.yaml which checks for the existence of my “C” session (the default setup I have for Cousteau under my tmuxp configuration) and then if it can’t find it, fires off tmuxp which loads up a standard set of panes that I use all the time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 session_name: C windows: - panes: - h log window_name: hab - panes: - nb window_name: nb - panes: - cd ~/Code/whatevs window_name: code - panes: - cd ~/Code/blog/ window_name: blog - panes: - cd ~ && neofetch window_name: sh
Note that I use tmuxp which is a python version of the ruby utility tmuxinator. Both simply take a yaml config file and sets up your tmux sessions for you so you don’t need to do it manually. Both work fine, though I personally liked tmuxp a little better, but do be aware that it requires python 3.7 these days which is an issue on some linux distros that haven’t completely switched over from 3.6 (including my fave, Solus).
What this does though for me, is bring up 5 terminals for me to use, the first contains my super handy CLI habit tracker,
habitctl and displays how I am doing. The second brings up
newsboat which is a super speedy rss/atom feed reader which allows me to shred through my newsfeeds at a speed most normal gui clients can only dream of. The 3rd and 4th windows are simply places for me to start coding in-pane, or to work on my blog posts, and the last one simply brings up a handy reminder of the system, but I use it mostly for doing things like
brew updates and the like.
6. Terminal editors
Being able to fire up an editor in your terminal and being roficient in editing with it will *drastically shorten the mental loop between thinking and acting. It is surprising how a ridiculously short startup time between firing something up and taking care of it on your machine adds hyper-efficiency and getting things done. There is a satisfaction to speed and being able to move without context switching that makes terminal editors, and the time you need to sink into getting a bit proficient on them, worth the effort.
Blog posts on vim-fandom are legion, but the fact of the matter is, being able to edit directly from the terminal without switching, and particularly with the efficiency of vim’s text editing (which, I have to admit, if you’re manipulating text an an expert in it, is astonishing in the hands of people who have mastered it.). Personally, I find vim always a bit problematic, even though I’ve invested a lot of time in getting better at it, and because I consider myself more of a writer than a text editor, but for people like devs or data scientists, it may be the right choice for you if you need to zip in and out of files and edit them with lightning speed. I think it’s telling that just about every modern GUI editor has some sort of key binding mode available for vim even to this day. While your opinion on modal editors is most likely polarized, the fact of the matter is vim does seem to make you a hyper efficient text manipulator. A lot of people have switched over to using Neovim though the latest vim, imho has now closed the gap with where the neo version is. After some time with neovim where I really didn’t see much of a difference, I switched back to standard vim as my plugins seemed fine, but YMMV.
Your other choice in this space is, of course, emacs, which I personally have switched over to using about a year and a half ago. It is not a modal editor, for which I am grateful (and which means many of my files have stopped having random
:wq’s scatttered throughout them.).
Controversially, when I started using emacs, I eschewed the gui client for the terminal version which was great. Fast, out of the way, and just as useful with plugins as the gui version (the only difference being you can’t control font faces or get some gui based plugins like all-the-icons to work, which is highly unfortunate). Another side effect was the fact that, for some reason, emacs themes often don’t cooperate with the terminal colour schemes for reasons I still can’t quite fathom, so picking up a colour scheme and having it look like what you expect in-terminal can be a slight challenge.
That said though, getting emacs working as a service on your machine via
brew services start emacs and then connecting to it via an emacs client with
emacs -nw gives you a suprising amount of raw speed and as my preferred mode of operation for ages before switching over to a gui client (for reasons I’m still not entirely sure were valid as they were mostly cosmetic due to nicer theming, font faces, and things like all-the-icons.).
Either emacs or vim, and some invested time, will also give you even grater degree on the command line since the command line is all about manipulating or modifying text files or streams in many cases.
Fundamentally, this post is just about making getting started on the command line nicer for you (or, if you’re already a pro, possibly considering some tweaks to make life more pleasant.). Minor changes in crafting your environment can go a long, long way to making life on the command line vastly more enjoyable.
Future posts I’m planning will talk about some nice CLI tools you should seriously consider adding to your arsenal, as well as how to be more productive and efficient. Tune back in then.cli tools howto