Let's begin with a goal: determine the commands which you type most frequently. To solve this problem we will iteratively interact with the terminal.

1: Locate the data

history 1

2: Extract relevant data

awk '{print $2}' | awk 'BEGIN {FS="|"} {print $1}'

3: Count occurrences

sort | uniq -c

4: Format Output

sort -r | head -n 10


$ history 1                       |
  awk '{print $2}'                |
  awk 'BEGIN {FS="|"} {print $1}' |
  sort                            |
  uniq -c                         |
  sort -r                         |
  head -n 10

2132 g
 774 ls
 721 fg
 312 cd
 288 cat
 216 make
 177 rm
 150 vim
 114 rackup
 110 p
 107 man
 101 pass
  72 twa
  72 mv
  65 twd
  62 twn
  62 mkdir
  62 brew
  61 ssh
  61 ll

Above is the output of the history pipeline on my machine. Two general observations are a direct consequence of my dot files. Most commands are four letters or less and many commands are custom aliases. One oddity is the disproportionate frequency of g. g is my alias for git. The pipeline discussed above lumps all git commands together under one count due to the first awk command. I have a slight variation of this pipeline which only looks at git subcommands.

Characterizing the process

In every iteration there are three basic steps: deciding what you want the computer to do, telling the computer what to do, and waiting for the computer to finish the task. Of these three steps thinking is the most challenging to shorten, so I'll leave that as an exercise for the reader. Improving execution time is also difficult. However, execution is a minuscule portion of the total time for an iteration. Thinking and execution also represent the time where work is being done. While instructing the computer is complete waste; both your brain and CPU are idle during this stage. Therefore I will focus on reducing the time spent instructing the computer.

The solution is to reduce the number of keys typed for each instruction. This has two effects which both shrink the instructing time. First, each key press takes time. Time to physically move a finger to the key and time to press the key. The number of key presses is directly proportional to the instructing time, thus by removing keys the time shrinks. Second, each key press is a chance for error. An erroneous key press will at best cause a syntax error, causing you to backtrack and try again. More wasted time.

Implementing a Solution

Now that you are convinced that removing key presses is the correct approach, the logical question is "How?". The answer is simple, aliases. All of my favorite tools (zsh, git, vim, mutt, and tmux) support custom aliases.

For example, I have aliased the history parsing pipeline to h.


This example shows how to reduce the friction when using the terminal. When I think of this process my mind immediately jumps to the image of an ax head casting sparks across a dark room while being sharpened (hence the title of this post). While I framed this discussion in the context of terminal programs, I use this approach for everything including GUIs and social interactions.

P.S. A brief note about programming style

The primary goal of source code is to communicate ideas, algorithms, and workflows with other developers and secondarily with the computer. Language is ambiguous; a problem which is exacerbated use of shortcuts and abbreviations. By combining these two facts it is obvious that my argument for customization and aliases does not apply to programming languages.