Awesome-Bash-Aliases: A 2,101-line README That Pant’s Your Dotfiles
The repo at vikaskyadav/awesome-bash-alias contains a yaml file (as a publishing config) and a single README.md that is ~two-thousand lines which describes a spec and implementation for the spiffiest shell aliases setup I’ve ever seen.
Since I try my bestest to avoid any resources with a CLAUDE.md (etc.) or commits by coding agents, I’ve been scouring past and new finds to feature in these ‘will eventually be daily again’ Drops. Finding this one was pure gold: 49 code blocks, 143 alias declarations, 44 function definitions, organized across 66 sections with careful attention to cross-platform behaviour, and guard conditions.
We’ll cover what’s in the README and then feature a few of the more notable parts of this massive shell level-up.
The README’s Proposed Layout
The diagram at the top of the file in the repo prescribes thirteen modules:
| File | Purpose |
|---|---|
modules/core.sh | has() helper, AWESOME_ALIAS_OS detection |
modules/navigation.sh | .., ..., mkcd(), croot(), up() |
modules/files.sh | ls variants, safe cp/mv/rm, extract(), disk usage |
modules/git.sh | Prefix-g aliases, gpristine(), gclone() |
modules/docker.sh | Prefix-d aliases, dsh(), dstop-all(), dprune() |
modules/kubernetes.sh | Prefix-k aliases, kuse(), knamespace(), kdebug() |
modules/networking.sh | publicip(), localip(), portcheck(), killport() |
modules/system.sh | mem, psmem, psgrep(), systemd/journalctl wrappers |
modules/packages.sh | apt, dnf, pacman, apk, brew wrappers |
modules/development.sh | Node.js (npm/pnpm/bun), Python, Go, Rust, Java |
modules/infrastructure.sh | tf/terraform, hm/helm, Ansible aliases |
modules/cloud.sh | AWS, Azure, GCP identity/profile helpers |
modules/macos.sh | finder, flushdns, .DS_Store cleanup |
Two optional/ modules sit outside the default load path: modern-cli.sh (eza, bat, ripgrep, fd, btop, lazygit, zoxide) and dangerous.sh (the confirm() helper plus docker-remove-stopped, docker-prune-all). Two completions/ files reattach tab completion to short aliases like k and d. A tests/aliases.bats directory is referenced for ShellCheck/Bats validation.
None of these files are checked into the repo. The README is the sole source. The module boundaries are so clean that copying sections into files yourself is a ~15-minute job.
These aliases do not stand alone. Two bits are defined at the top of the file that prop up everything else.
has() checks whether a command exists:
has() { command -v "$1" >/dev/null 2>&1}
Every block that depends on an external tool is wrapped in if has X; then ... fi. Roughly 25 guards exist: has docker, has kubectl, has helm, has brew, has jq, has yq, has eza, has bat, has rg, has fd, has btop, has htop, has lazygit, has lazydocker, has dust, has procs, has delta, has zoxide, has openssl, has aws, has az, has gcloud, has nvidia-smi, has systemctl, plus the package managers (has apt, has dnf, has pacman, has apk).
Source this on macOS without kubectl installed and you get zero k* aliases.
Source it on a stripped-down Debian container and you get ls -lah --color=auto and not much else.
AWESOME_ALIAS_OS splits on uname -s:
case "$(uname -s)" in Darwin) export AWESOME_ALIAS_OS="macos" ;; Linux) export AWESOME_ALIAS_OS="linux" ;; *) export AWESOME_ALIAS_OS="other" ;;esac
Every OS-specific block checks this variable. ls gets -G on macOS and --color=auto on Linux. du -h gets -d 1 on macOS and --max-depth=1 on Linux. mem maps to vm_stat on macOS and free -h on Linux. localip uses ipconfig getifaddr en0 on macOS and hostname -I | awk '{print $1}' on Linux. (You get the idea.)
The README’s principle of “avoid duplicate or conflicting aliases” is enforced by these two helpers and nothing more.
Prefix conventions form a namespace. g for git, d for docker, dc for docker compose, k for kubectl, hm for helm, tf for terraform, a for ansible, aws/az/gc for the three clouds. The README flags collisions explicitly: mvi could be mvn install or interactive mv; grb could be git rebase or gradle build. The answer is to disambiguate (mvni, gradleb) rather than pick a winner. hm was chosen for helm instead of h because h is also the history alias. But, nobody who reads these Drops would ever dabble in K8s’s. (Right, Anakin…Right?)
Destructive commands use a confirmation pattern. optional/dangerous.sh defines:
confirm() { local prompt="${1:-Continue?}" local expected="${2:-YES}" local answer printf '%s Type %s to continue: ' "$prompt" "$expected" read -r answer [ "$answer" = "$expected" ]}
The rule: you cannot merely keystroke a y to confirm “big” things.
docker-remove-stopped requires REMOVE-STOPPED. docker-prune-all requires PRUNE-DOCKER. gpristine (in the git section) requires PRISTINE. It’s a solid pattern: show the affected resources, ask for a phrase that cannot be a typo, then act. You might think this is all for the sake of “security”, but it’s really about preventing an errant key hit from causing twenty undoable seconds.
Eight Idioms I’ve Adopted From This Repo

These are the aliases and functions from the README that landed in my dotfiles. In order from “doh! why didn’t I have this?!?!” to “Huh…I would not have thought of this.”
1. mkcd <dir> – mkdir -p && cd (batteries included)
mkcd() { if [ "$#" -ne 1 ]; then printf 'Usage: mkcd <directory>\n' >&2 return 2 fi mkdir -p -- "$1" && cd -- "$1"}
The -- prevents mkcd -f from being interpreted as a flag to mkdir. Most homegrown versions of this function miss it. I combined it with two others from the same section: croot() which jumps to the git root via git rev-parse --show-toplevel, and up N which goes up N directories. Together they mean I, now, almost never type a full path.
2. serve [<port> [<dir>]] – (an — ugh — python HTTP server, bound to loopback)
serve() { local port="${1:-8000}" local directory="${2:-.}" if ! has python3; then printf 'python3 is required.\n' >&2 return 1 fi printf 'Serving %s at http://127.0.0.1:%s\n' "$directory" "$port" python3 -m http.server "$port" --bind 127.0.0.1 --directory "$directory"}
The --bind 127.0.0.1 is the detail. Stock python3 -m http.server binds to 0.0.0.0 and exposes the directory to every machine on your LAN. A companion serve-lan swaps the bind for when you actually want that. The README is SUPER explicit: “intended for local development and file sharing, not production hosting.”
3. extract <archive> – one rin^wcommand to rule every archive format you will encounter
The function dispatches on suffix using a case statement. Ten branches: tar.bz2, tar.gz, tar.xz, tar.zst (the one most snippets miss), bare tar, bz2, gz, xz, zip, 7z, rar. It validates the file exists, validates the suffix is known, and gives a clear error on unknown formats. The *.tar.zst branch is the reason this version is worth copying over any other – zstd-compressed tarballs are becoming common in package distribution, and most extract() functions from 2018 do not handle them.
4. killport <port> – stop whatever is listening on a port (after you see it)
killport() { if [ "$#" -ne 1 ]; then printf 'Usage: killport <port>\n' >&2 return 2 fi local pids pids="$(lsof -tiTCP:"$1" -sTCP:LISTEN)" if [ -z "$pids" ]; then printf 'Nothing is listening on port %s.\n' "$1" return 0 fi printf 'Processes listening on port %s:\n%s\n' "$1" "$pids" printf 'Terminate these processes? [y/N] ' local answer read -r answer case "$answer" in y|Y|yes|YES) kill $pids ;; *) printf 'Cancelled.\n' ;; esac}
Two things: it shows the PIDs before asking, and it tells you if nothing is listening. Most one-liners (kill -9 $(lsof -t -i:3000)) skip both. The confirmation is [y/N], not [Y/n] – the capitalized letter is the default if you press Enter. Defaulting to cancel for a destructive command is the same pattern as dstop-all and dprune.
5. dstop-all – stop every running container (after listing them)
dstop-all() { local containers containers="$(docker ps -q)" if [ -z "$containers" ]; then printf 'No running containers.\n' return 0 fi printf '%s\n' "$containers" printf 'Stop all running containers? [y/N] ' local answer read -r answer case "$answer" in y|Y|yes|YES) docker stop $containers ;; *) printf 'Cancelled.\n' ;; esac}
Note the # shellcheck disable=SC2086 comment on docker stop $containers. The line intentionally splits the container ID list on whitespace – ShellCheck correctly flags it, and the comment explains why. This is the function that replaces the too-dangerous-to-alias docker stop $(docker ps -q) on the “Commands Intentionally Excluded” list. It stops everything, but you see the list first and you have to say yes.
6. tlscheck <host[:port]> – cert info in one line
tlscheck() { if [ "$#" -ne 1 ]; then printf 'Usage: tlscheck <hostname[:port]>\n' >&2 return 2 fi local host="${1%%:*}" local port="${1##*:}" if [ "$host" = "$port" ]; then port=443 fi openssl s_client -connect "${host}:${port}" -servername "$host" \ </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -fingerprint}
Port defaults to 443 when not specified. The ${1%%:*} / ${1##*:} split is parameter expansion – no external tools needed to parse host:port. The </dev/null closes stdin so s_client exits after the handshake; 2>/dev/null suppresses the certificate chain dump. Output looks like:
subject=CN = *.example.comissuer=C = US, O = Let's Encrypt, CN = R11notBefore=Jun 15 00:00:00 2026 GMTnotAfter=Sep 13 23:59:59 2026 GMTSHA256 Fingerprint=AB:CD:...
One function call replaces opening a browser, clicking the padlock, and drilling through three Chrome security panels.
7. gpristine – git reset --hard && git clean -fd (guarded)
gpristine() { printf 'This will discard tracked changes and remove untracked files.\n' git status --short printf 'Type PRISTINE to continue: ' local confirmation read -r confirmation [ "$confirmation" = "PRISTINE" ] || { printf 'Cancelled.\n' return 1 } git reset --hard HEAD && git clean -fd}
The README’s “Commands Intentionally Excluded” section lists git reset --hard && git clean -df as another pattern too dangerous to alias. gpristine is the answer to “but what if I really, really need to?”. It shows git status --short first so you see the carnage before you authorize it. y is not enough; the required string is PRISTINE. Copy-paste won’t cut it either – typing an 8-character all-caps word forces you to look at what you are about to destroy.
8. gpf – git push --force-with-lease
Not a function. Just alias gpf='git push --force-with-lease'. The README does not alias git push -f. There is no gpf that maps to the bare --force. --force-with-lease refuses the push if the remote has moved since your last fetch, which is what you actually want in every situation where you reach for -f. That the project ships only the safer spelling and refuses to provide the dangerous shows how consistent the design philosophy is applied throughout.
Three things the README does that are not aliases
The “Commands Intentionally Excluded” section lists one-liners the project refuses to ship, with reasons: docker stop $(docker ps -q), docker system prune -af, git reset --hard && git clean -df, rm -rf *, kubectl delete all --all, terraform destroy -auto-approve. The README’s comment: “They may be valid in controlled automation, but they are too destructive for short, easily mistyped interactive aliases.” That paragraph is more valuable than any single alias in the collection.
The conflict-detection helpers at the end are alias-exists and alias-check. They accept a list of names and tell you which ones would collide with your existing shell. This is an admission that the project cannot declare a namespace – your shell is already full of things. The README’s answer is a one-liner: alias-check h c l ll gs k d dc tf. Run it, see the collisions, pick the ones you keep.
The philosophy paragraph: predictable, memorable, safe, discoverable, portable, easy to remove, clear about its operational impact. Every alias that survived review satisfies all seven. The excluded list is what happens when one fails.
If you want a starter set, copy the two helper blocks (has, AWESOME_ALIAS_OS), then copy the sections for the tools on your machine. The whole file is at vikaskyadav/awesome-bash-alias. Skip optional/dangerous.sh unless you are braver (or dafter?) than I am.
FIN
Remember, you can follow and interact with the full text of The Daily Drop’s free posts on:
- 🐘 Mastodon via
@dailydrop.hrbrmstr.dev@dailydrop.hrbrmstr.dev - 🦋 Bluesky via
https://bsky.app/profile/dailydrop.hrbrmstr.dev.web.brid.gy
☮️
Leave a Reply