mkcd: The missing shell shortcut
It seems like you often cd
to a new directory. How often?
I have analyzed my fish shell history on a Linux machine where it spans from 2019 to 2025 and has just over 100K entries. If you have seen a fish history file, it looks like a subset of YAML:
- cmd: add-apt-repository ppa:zfs-native/stable
when: 1342217584
- cmd: nvim dir.sha256
when: 1614189938
paths:
- dir.sha256
However, it is not valid YAML. With this in mind, I wrote a script to analyze history line-by-line using Python’s helpful fileinput
module.
#! /usr/bin/env python3
import fileinput
mkdir = 0
cd_after_mkdir = 0
after_mkdir = None
for line in fileinput.input(errors="surrogateescape"):
args = line.split() # Ignore quoting.
if args[:2] != ["-", "cmd:"]:
continue
match args[2:]:
case ["mkdir", path, *_] | ["sudo", "mkdir", path, *_]:
path = path.rstrip("/")
mkdir += 1
after_mkdir = path
continue
case ["cd", path, *_]:
path = path.rstrip("/")
if path == after_mkdir:
cd_after_mkdir += 1
case _:
pass
after_mkdir = None
print(f"{mkdir = }\n{cd_after_mkdir = }")
You can download the script and try it on your history. Here is what I get on my machine:
> ./analyze.py ~/.local/share/fish/fish_history
mkdir = 1244
cd_after_mkdir = 213
213 ÷ 1244 × 100% ≈ 17% of mkdir
commands are immediately followed by changing to the new directory. This is for my user account; for root, I have mkdir = 30
and cd_after_mkdir = 3
, respectively. The numbers are approximate. The script ignores argument quoting, and my shell history covers time after I replaced mkdir
followed by cd
. Still, this seems like a lot. Why is there no standard shortcut to perform mkdir
followed by cd
? It doesn’t seem any prominent shell includes one. By contrast, ll
for ls -l
and la
for ls -la
are standard in fish.
I know I didn’t invent mkcd
and only adopted it years after reading the first Internet comment that described it. This leads me to suspect the friction isn’t obvious. You realize the standard workflow is tiresome after you start using mkcd
. (This means you adopt mkcd
at your peril.)
Where does mkcd
come from? Multiple discovery is likely because the core idea is so simple. I have searched Hacker News with the official Algolia search and Reddit and textfiles.com using DuckDuckGo and Google. The earliest instances I found were a January 2008 comment by HN user dreish and an April 2010 post “mkcd” by Jack Mottram on the Tumblr blog One Thing Well. The dreish comment uses mkdir -p
, but Jack Mottram only replaced mkdir
with mkdir -p
in May 2010 follow-up “mkcd improved” after a message from a reader, suggesting he didn’t borrow from the HN comment. Searching Usenet Archives finds a linux.debian.user.german post from 2003 by Robert Michel asking how to implement mkcd
as a Bash alias. Other discussions that match “mkcd” on Usenet Archives are about burning optical media.
After seeing the recommendation for mkcd
enough times, in 2024 I decided to try it. I implemented it for fish and quickly became a fan. Over a year later, I can definitely recommend it. To try it yourself, you can install mkcd.fish
to your fish functions directory (likely ~/.config/fish/functions/
).
# From https://dbohdan.com/mkcd
# License: MIT
# https://dbohdan.mit-license.org/@2025/license.txt
function mkcd --argument name --description "Create a directory and 'cd' to it"
if test (count $argv) -ne 1
printf 'usage: mkcd name\n' >&2
return 2
end
mkdir -p $name
cd $name
end