Photo by Gabriel Heinzer on Unsplash
For as long as I can remember as a developer, I’ve been told:
Master the command line — it unlocks a whole new level of productivity.
I always neglected that advice, thinking it was meant for people with extraordinary memory. How can a normal person memorize all the ls
arguments? How do you remember the order of parameters in find
? And how on earth do you get used to the quirky syntax of bash
?
About a year ago, I read The Pragmatic Programmer, 20th Anniversary Edition, which once again strongly urged me to master the command line. Since I otherwise liked the book, I decided to give the shell one more try. Quickly I discovered two fascinating things that completely changed my attitude toward it:
You don’t have to memorize everything. Instead of fixating on specific commands, focus on your workflow. What routine operations do you repeat day to day? Maybe you’re searching for certain files, or opening a browser with a specific URL. Script that once, and forget the internals.
You don’t have to learn bash syntax. Write your scripts in your favorite language. These days most languages can run in interpreter mode with just a proper shebang line. If your language of choice doesn’t support it — compile your utilities instead.
Under the impression of these two discoveries, I started building a small collection of scripts I use in my everyday work — cli-bits. I’m happy to share it. Use it as inspiration to create your own scripts; and if you happen to find some of mine useful as they are, that would make me even happier. Let’s see what’s inside!
Note: The utilities are written primarily for macOS, but many should also work on Linux. The JS scripts may also run on Windows, though they haven’t been tested there.
gitb — print the current Git branch
Trivial yet very useful — this was the first script I wrote for the collection. I use it as a part of pipelines, like pulling from the corresponding remote branch:
gitb | xargs git pull origin
# Or:
git pull origin $(gitb)
youtrack — open a bug tracker issue
I use YouTrack a lot. One day I realized I kept typing YouTrack URLs by hand, composing them from https://youtrack.jetbrains.com/issue/
and the current feature branch name, which is named after the issue. So I wrote the youtrack
command which automates this for me:
~/my-project $ gitb
ABC-1234
~/my-project $ gitb | youtrack
The util reads from stdin, extracts the issue name, and opens the corresponding URL — in this case https://youtrack.jetbrains.com/issue/ABC-1234
. Of course, the same approach can be applied to GitHub, Jira, or any other bug tracker.
lastDown — print the N most recently downloaded files
Downloading files has always been a mess for me. I had to remember the names and paths of my downloads, but if I chose a destination each time, it interrupted my browsing and I lost track of why I was on the page in the first place. After years of this hassle, I adopted the following approach:
- Always download to the default folder (
~/Downloads
on most systems) - Use scripts to query and move recently downloaded files
lastDown
takes care of the “query” part of this routine:
~/Pictures $ lastDown 2
/Users/me/Downloads/PXL_20250404_190924.jpg
/Users/me/Downloads/PXL_20250404_191358.jpg
Looks like I downloaded a couple of photos I took during the Web Developer Day celebration 🙂 Note that the paths are absolute — no relative-path confusion possible.
moveHere — move files to the current directory
This is the second part of the downloading routine:
~/Pictures $ lastDown 2 | moveHere
~/Pictures $ ls
PXL_20250404_190924.jpg PXL_20250404_191358.jpg
Both files were moved to the current directory — ~/Pictures
in this case. The downloading riddle is solved!
trash — move files to the Trash
I’ve always feared rm
because of its unforgiving irreversibility. It feels too harsh, especially since most systems already have a Trash bin. Strangely, though, there’s no standard utility to move files there — so I wrote this simple one myself. It supports passing files either as arguments or via a pipe.
~/Pictures $ trash PXL_20250404_*
Using it is much less stressful than rm
— any mistake is reversible.
getLine — select line(s) from stdin
I often list a lot of files with ls
or find
, and sometimes I only need a few of them. I could try to adjust the command arguments, but I don't remember them, so I wrote a getLine
util to select lines by number:
~/logs $ ls
log_2025-09-03.log
log_2025-09-04.log
log_2025-09-08.log
log_2025-09-12.log
(...and many more files)
~/logs $ ls | getLine 1
log_2025-09-03.log
~/logs $ ls | getLine 1 3
log_2025-09-03.log
log_2025-09-04.log
log_2025-09-08.log
The indices are one-based to match less -N
. Negative indices are supported as well.
lless — select a line and open the file
This is simply a shortcut for getLine
+ less
. The utility interprets the first argument as a line number and passes any remaining arguments directly to less
.
~/logs $ ls | lless 2 -S
This opens the 2nd file from the ls
listing in less
, log_2025-09-04.log
in the previous example, passing the -S
option which turns off lines wrapping.
today — or tomorrow, or yesterday
It’s a simplified version of date
, which outputs the current date, or a date relative to it by a given offset. I use it for organising downloaded logs.
~ $ date
Mon Sep 16 06:50:52 CEST 2025
~ $ mkdir $(today -1) && cd $(today -1)
~/2025-09-15 $ lastDown 3 | moveHere
This moves last three downloaded files to a freshly created 2025-09-15
directory.
codeDebug — open a project in VS Code and debug the TS service
As you probably know, you can open a project with the code
command:
~/my-project $ code .
This opens my-project
in VS Code. Sometimes I need to debug the TypeScript language service, which requires setting the TSS_DEBUG variable. I found it convenient to script this so I can open a project in TS server debug mode with a single command:
~/my-project $ codeDebug .
Now I'm ready to connect to the node
process with the debugger and start exploring TypeScript intricacies.
What's more?
There are some additional commands to enumerate, quote, and search specific files. It’s not rocket science, nor a framework — just small, practical bits I use daily.
I hope you see it the same way now. May this approach save you friction and keep your head clear for actual work!
Top comments (0)