# core -- base aliases and functions (always loaded)
# Curated from: mathiasbynens, paulirish, jessfraz, holman, thoughtbot,
# brendangregg, and years of collective shell wisdom.
# ============================================================================
# EDITOR
# ============================================================================
alias v='nvim'
alias vi='nvim'
alias vim='nvim'
alias e='$EDITOR'
alias vd='nvim -d' # diff mode
alias vr='nvim -R' # read-only
alias sv='sudo nvim'
# Nvim profiles
alias write='NVIM_APPNAME=write nvim'
alias code='NVIM_APPNAME=code nvim'
# ============================================================================
# MODERN REPLACEMENTS (install: pacman -S eza bat fd ripgrep dust duf procs)
# ============================================================================
alias ls='eza --icons --classify=auto --color=auto --group-directories-first'
alias la='eza -la --icons --git --group-directories-first'
alias ll='eza -l --icons --git --group-directories-first'
alias lt='eza --tree --icons --level=3'
alias lta='eza --tree --icons -a --level=3'
alias lm='eza -l --sort=modified --reverse'
alias lk='eza -l --sort=size --reverse'
alias cat='bat -P'
alias grep='rg --smart-case'
alias find='fd'
alias du='dust'
alias df='duf'
alias ps='procs'
alias top='btop'
alias htop='btop'
alias wc='tokei'
# ============================================================================
# NAVIGATION
# ============================================================================
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'
# `alias -- -` is bash-only; mksh has `cd -` builtin natively
[ -n "$BASH_VERSION" ] && alias -- -='cd -'
alias cdg='cd $(git rev-parse --show-toplevel 2>/dev/null || echo .)'
# ============================================================================
# GIT -- SPEED
# ============================================================================
alias g='git'
alias gs='git status -sb'
alias ga='git add'
alias gaa='git add -A'
alias gap='git add -p'
alias gc='git commit'
alias gcm='git commit -m'
alias gca='git commit --amend --no-edit'
alias gcam='git commit --amend'
alias gco='git checkout'
alias gcb='git checkout -b'
alias gsw='git switch'
alias gswc='git switch -c'
alias gd='git diff'
alias gds='git diff --staged'
alias gdw='git diff --word-diff'
alias gdn='git diff --name-only'
alias gl='git log --oneline -20'
alias glo='git log --oneline --graph --all --decorate -30'
alias glp='git log -p -5'
alias gls='git log --stat -10'
alias glf='git log --follow -p'
alias gb='git branch -vv'
alias gbd='git branch -d'
alias gbD='git branch -D'
alias gf='git fetch --all --prune'
alias gp='git push'
alias gpu='git push -u origin HEAD'
alias gpf='git push --force-with-lease'
alias gpl='git pull --rebase'
alias grb='git rebase'
alias grbi='git rebase -i'
alias grbc='git rebase --continue'
alias grba='git rebase --abort'
alias gst='git stash'
alias gstp='git stash pop'
alias gstl='git stash list'
alias gstd='git stash drop'
alias gsts='git stash show -p'
alias gcp='git cherry-pick'
alias gcpc='git cherry-pick --continue'
alias gcpa='git cherry-pick --abort'
alias grs='git reset'
alias grsh='git reset --hard'
alias grss='git reset --soft HEAD~1'
alias grl='git reflog -20'
alias gbl='git blame -w -C -C -C'
alias gwt='git worktree'
alias gwta='git worktree add'
alias gwtl='git worktree list'
alias gwtr='git worktree remove'
alias gbis='git bisect'
alias gclean='git clean -fd'
alias gtag='git tag -a'
# GIT -- LOG FORMATS
alias glog='git log --graph --abbrev-commit --decorate --all --format=format:"%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)"'
alias glogd='git log --graph --abbrev-commit --decorate --all --format=format:"%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n %C(white)%s%C(reset) %C(dim white)- %an%C(reset)"'
alias gwho='git shortlog -sn --all'
# GIT -- MAINTENANCE
alias gprune='git remote prune origin'
alias gcleanup='git branch --merged main | grep -v "main\|master\|\*" | xargs -r git branch -d'
alias gorphan='git fsck --unreachable --no-reflogs'
alias ggc='git gc --aggressive --prune=now'
# ============================================================================
# BUILD -- C / SYSTEMS
# ============================================================================
alias mk='make -j$(nproc)'
alias mkc='make clean'
alias mki='sudo make clean install'
alias mkd='make DEBUG=1 -j$(nproc)'
alias mkv='make V=1 -j$(nproc)'
alias cc99='cc -std=c99 -Wall -Wextra -Wpedantic'
alias cc11='cc -std=c11 -Wall -Wextra -Wpedantic'
alias cc23='cc -std=c23 -Wall -Wextra -Wpedantic'
alias ccd='cc -std=c11 -Wall -Wextra -Wpedantic -g -O0 -fsanitize=address,undefined'
alias ccr='cc -std=c11 -O3 -march=native -flto -DNDEBUG'
alias ccp='cc -std=c11 -Wall -Wextra -Wpedantic -pg -g'
alias cppcheck='cppcheck --enable=all --suppress=missingIncludeSystem'
alias splint='splint +posixlib'
alias scan='scan-build make'
# ============================================================================
# BUILD -- GO
# ============================================================================
alias gor='go run .'
alias gob='go build .'
alias got='go test ./...'
alias gotv='go test -v ./...'
alias gotr='go test -race ./...'
alias gotc='go test -cover ./...'
alias gof='go fmt ./...'
alias gov='go vet ./...'
alias gol='golangci-lint run'
alias gom='go mod tidy'
alias god='go doc'
# ============================================================================
# BUILD -- RUST
# ============================================================================
alias cr='cargo run'
alias crr='cargo run --release'
alias cb='cargo build'
alias cbr='cargo build --release'
alias ct='cargo test'
alias ctv='cargo test -- --nocapture'
alias cf='cargo fmt'
alias cl='cargo clippy'
alias cdoc='cargo doc --open'
alias cbench='cargo bench'
alias cwat='cargo watch -x check'
# ============================================================================
# BUILD -- NODE / JS / TS
# ============================================================================
alias ni='npm install'
alias nid='npm install --save-dev'
alias nr='npm run'
alias nrd='npm run dev'
alias nrb='npm run build'
alias nrt='npm run test'
alias nrl='npm run lint'
alias nx='npx'
alias pi='pnpm install'
alias pr='pnpm run'
alias prd='pnpm dev'
alias prb='pnpm build'
alias prt='pnpm test'
alias px='pnpm dlx'
# ============================================================================
# BUILD -- PYTHON
# ============================================================================
alias py='python3'
alias pip='python3 -m pip'
alias venv='python3 -m venv .venv'
alias va='. .venv/bin/activate'
alias pyserv='python3 -m http.server'
alias pyt='python3 -m pytest'
alias pytv='python3 -m pytest -v'
alias pyf='python3 -m black .'
alias pyl='python3 -m ruff check .'
# ============================================================================
# DOCKER / CONTAINERS
# ============================================================================
alias d='docker'
alias dc='docker compose'
alias dcu='docker compose up -d'
alias dcd='docker compose down'
alias dcr='docker compose restart'
alias dcl='docker compose logs -f'
alias dcp='docker compose ps'
alias dcb='docker compose build'
alias dce='docker compose exec'
alias di='docker images'
alias dps='docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"'
alias dpsa='docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"'
alias drm='docker rm'
alias drmi='docker rmi'
alias dprune='docker system prune -af --volumes'
alias dlog='docker logs -f'
alias dex='docker exec -it'
alias dstop='docker stop $(docker ps -q)'
# ============================================================================
# DEBUGGING / TRACING
# ============================================================================
alias gdb='gdb -q'
alias val='valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes'
alias valmem='valgrind --tool=massif'
alias valcache='valgrind --tool=cachegrind'
alias stf='strace -f -e trace=file'
alias stn='strace -f -e trace=%net'
alias stp='strace -f -e trace=%process'
alias stw='strace -f -e trace=write'
alias ltr='ltrace -c'
alias perf-top='perf top'
alias perf-stat='perf stat'
alias perf-record='perf record -g'
alias perf-report='perf report'
# ============================================================================
# KERNEL DEVELOPMENT
# ============================================================================
alias kmake='make -j$(nproc) 2>&1 | tail -20'
alias kmod='lsmod | sort'
alias klog='dmesg -wH'
alias klogc='sudo dmesg -c'
alias klogf='dmesg --follow --level=err,warn'
alias kconfig='make menuconfig'
alias kdefconfig='make defconfig'
alias kclean='make mrproper'
# ============================================================================
# TMUX
# ============================================================================
alias t='tmux'
alias ta='tmux new -A -s'
alias tl='tmux list-sessions'
alias td='tmux detach'
alias tk='tmux kill-session -t'
alias tka='tmux kill-server'
alias ts='tmux split-window'
alias tv='tmux split-window -h'
alias tw='tmux new-window'
# ============================================================================
# NETWORK
# ============================================================================
alias myip='curl -s ifconfig.me'
alias myip6='curl -s ifconfig.me/ip6'
alias ports='ss -tlnp'
alias portsa='ss -tlunp'
alias pingg='ping -c 3 1.1.1.1'
alias header='curl -sI'
alias weather='curl -s wttr.in/?format=3'
# ============================================================================
# SYSTEM
# ============================================================================
alias reload='exec $SHELL'
alias path='echo $PATH | tr ":" "\n"'
alias now='date +"%Y-%m-%d %H:%M:%S"'
alias epoch='date +%s'
alias h='history | tail -30'
alias j='jobs -l'
alias mkdir='mkdir -pv'
alias cp='cp -iv'
alias mv='mv -iv'
alias ln='ln -iv'
alias rm='rm -Iv'
alias chmod='chmod -v'
alias chown='chown -v'
alias cls='clear'
alias q='exit'
alias ka='killall'
alias logout='pkill -KILL -u krisyotam'
alias lock='slock'
alias shutdown='sudo shutdown now'
alias restart='sudo reboot'
# ============================================================================
# SEARCH / FIND
# ============================================================================
alias rgf='rg --files-with-matches'
alias rgc='rg --count'
alias rgl='rg -l'
alias fdf='fd --type f'
alias fdd='fd --type d'
alias fdh='fd --hidden'
# ============================================================================
# PACKAGE MANAGEMENT (Arch)
# ============================================================================
alias pac='sudo pacman -S'
alias pacu='sudo pacman -Syu'
alias pacr='sudo pacman -Rns'
alias pacs='pacman -Ss'
alias pacq='pacman -Qi'
alias pacl='pacman -Ql'
alias paco='pacman -Qtdq'
alias pacclean='sudo pacman -Rns $(pacman -Qtdq)'
alias yay='paru'
alias sp='sudo pacman'
# ============================================================================
# GENTOO / PORTAGE
# ============================================================================
alias sync='sudo emerge --sync'
alias eup='sudo emerge -uUD @world'
alias eupq='sudo emerge -uUDq @world'
alias epv='emerge -pv'
alias eav='emerge -av'
alias esearch='emerge -sS'
alias eins='sudo emerge'
alias erms='sudo emerge -Rns'
alias edeselect='sudo emerge --deselect'
alias edeps='emerge -c'
alias revdep='sudo revdep-rebuild -v'
alias emodrebuild='sudo emerge @module-rebuild'
alias dconf='sudo dispatch-conf'
alias eqf='equery f'
alias eqb='equery b'
alias eql='equery l'
alias eqd='equery d'
alias equ='equery uses'
alias eqhasuse='equery hasuse'
alias eqk='equery check'
alias eclean='sudo eclean-dist && sudo eclean-pkg'
alias ecleandist='sudo eclean-dist'
alias ecleanpkg='sudo eclean-pkg'
alias emaint='sudo emaint -a'
alias genlop='genlop -l'
alias qlist='qlist -IRv'
alias qcheck='qcheck -v'
alias eix='eix'
alias euse-info='euse -i'
alias euse-set='euse -E'
alias euse-unset='euse -D'
# ============================================================================
# SOURCEHUT
# ============================================================================
alias sg='hut git'
alias sb='hut builds'
alias st='hut todo'
alias sl='hut lists'
alias sgl='hut git list'
alias sbl='hut builds list'
alias sbf='hut builds show -f'
alias sbssh='hut builds ssh'
alias stl='hut todo ticket list'
alias sll='hut lists list'
alias sgql='hut graphql'
alias spatch='git send-email'
# ============================================================================
# BENCHMARKING
# ============================================================================
alias bench='hyperfine'
alias benchw='hyperfine --warmup 3'
# ============================================================================
# ENCODING / HASHING
# ============================================================================
alias b64e='base64'
alias b64d='base64 -d'
alias md5='md5sum'
alias sha1='sha1sum'
alias sha256='sha256sum'
alias sha512='sha512sum'
alias hex='xxd'
# ============================================================================
# PLAN 9
# ============================================================================
alias 9mk='mk'
alias 9mkc='mk clean'
alias 9mki='mk install'
alias 9c='9c'
alias 9l='9l'
alias 9p='9p'
alias plumb='plumber'
# ============================================================================
# SUCKLESS
# ============================================================================
alias cdwm='cd ~/src/dwm'
alias cst='cd ~/src/st'
alias cdmenu='cd ~/src/dmenu'
alias cblocks='cd ~/src/dwmblocks'
# ============================================================================
# SSH / REMOTE
# ============================================================================
alias sshkey='cat ~/.ssh/id_ed25519.pub'
alias scpd='scp -r'
alias rsync='rsync -avhP --partial'
# ============================================================================
# CLIPBOARD
# ============================================================================
alias clip='xclip -selection clipboard'
alias clipo='xclip -selection clipboard -o'
# ============================================================================
# SYSTEMD
# ============================================================================
alias sc='systemctl'
alias scs='systemctl status'
alias scr='systemctl restart'
alias sce='systemctl enable'
alias scd='systemctl disable'
alias scl='systemctl list-units --type=service --state=running'
alias jl='journalctl -e'
alias jlf='journalctl -f'
alias jlu='journalctl -u'
# ============================================================================
# FILE PERMISSIONS
# ============================================================================
alias cx='chmod +x'
alias perm644='chmod 644'
alias perm755='chmod 755'
alias perm700='chmod 700'
alias own='sudo chown -R $(whoami):$(whoami)'
# ============================================================================
# QUICK EDITS
# ============================================================================
alias fishrc='$EDITOR ~/.config/fish/config.fish'
alias mkshrc='$EDITOR ~/.mkshrc'
alias planrc='$EDITOR ~/.planrc'
alias vimrc='$EDITOR ~/.config/nvim/init.lua'
alias tmuxrc='$EDITOR ~/.tmux.conf'
alias gitrc='$EDITOR ~/.gitconfig'
alias nvimrc='$EDITOR ~/.config/nvim/init.lua'
# ============================================================================
# DISK / HARDWARE
# ============================================================================
alias lsblk='lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,LABEL'
alias temps='sensors 2>/dev/null || cat /sys/class/thermal/thermal_zone*/temp'
alias mem='free -h'
alias cpuinfo='lscpu | head -20'
# ============================================================================
# TAILSCALE
# ============================================================================
alias tss='tailscale status'
alias tsip='tailscale ip -4'
alias tsup='sudo tailscale up'
# ============================================================================
# DISK / FILESYSTEM
# ============================================================================
alias btrfs-sub='sudo btrfs subvolume'
alias btrfs-snap='sudo btrfs subvolume snapshot'
alias btrfs-list='sudo btrfs subvolume list'
alias btrfs-usage='sudo btrfs filesystem usage'
alias btrfs-scrub='sudo btrfs scrub'
alias zfs-snap='sudo zfs snapshot'
alias zfs-list='sudo zfs list'
alias zpool-status='sudo zpool status'
alias smartall='sudo smartctl -a'
alias smartquick='sudo smartctl -t short'
alias hdtest='sudo hdparm -Tt'
alias blkid='sudo blkid'
alias findmnt='findmnt -l'
# ============================================================================
# MEDIA / DOWNLOADS
# ============================================================================
alias yt='yt-dlp --embed-metadata -i'
alias yta='yt-dlp -x -f bestaudio/best'
alias ytp='yt-dlp --yes-playlist'
alias ytv='yt-dlp -f "bestvideo[ext=mp4]+bestaudio"'
alias ytsub='yt-dlp --write-auto-subs'
alias ffcopy='ffmpeg -hide_banner -c copy'
alias ffconcat='ffmpeg -hide_banner -f concat -safe 0 -i'
alias ffinfo='ffprobe -hide_banner -show_format -show_streams'
alias ffthumb='ffmpeg -hide_banner -ss 00:05:00 -i'
alias mpvloop='mpv --loop'
alias mpvnosub='mpv --no-sub'
alias gd='gallery-dl'
alias aria='aria2c -x 4'
# ============================================================================
# IRC / CHAT
# ============================================================================
alias irc='catgirl'
# ============================================================================
# LATEX / TYPESETTING
# ============================================================================
alias ltx='latexmk -pdf'
alias ltxw='latexmk -pdf -pvc'
alias ltxc='latexmk -c'
alias ltxC='latexmk -C'
alias pdflatex='pdflatex -interaction=nonstopmode -shell-escape'
alias xelatex='xelatex -interaction=nonstopmode'
alias lualatex='lualatex -interaction=nonstopmode'
alias groff='groff -Tpdf'
alias mandoc='mandoc -Tpdf'
alias pandoc-pdf='pandoc -t pdf -f markdown'
alias pandoc-html='pandoc -t html5 -f markdown'
# ============================================================================
# COMPRESSION
# ============================================================================
alias tarbz='tar -cjvf'
alias tarxz='tar -cJvf'
alias tarzstd='tar --zstd -cvf'
alias zipmax='zip -9 -r'
alias 7zmax='7z a -mx=9'
alias untar='tar -zxvf'
# ============================================================================
# SAFETY NETS
# ============================================================================
alias wget='wget -c'
# ============================================================================
# APPLICATIONS
# ============================================================================
alias browser='$BROWSER &'
alias z='zathura'
alias bin='nnn ~/.local/bin'
alias mutt='neomutt'
alias rss='sfeed_curses ~/.sfeed/feeds/*'
alias torrent='rtorrent'
alias warp='warp-terminal >/dev/null 2>&1 &'
alias mouse='mouseless >/dev/null 2>&1 &'
alias ff='fastfetch'
alias claude='claude --dangerously-skip-permissions'
alias nsxiv-thumb='nsxiv -t'
alias cmatrix='cmatrix -b'
# Criterion CLI
alias cc="$HOME/src/criterion-cli/criterion"
# Maritime Monitoring (Monarch Suite)
alias ssta='sea-surface-temperature-anomaly'
alias ohci='ocean-heat-content-index'
alias ssm='subsea-seismic-monitor'
alias svm='supervolcano-monitor'
alias kpi='kaiju-probability-index'
alias mc='maritime-charts'
# Corpus directories
alias content='cd $HOME/.corpus/content'
alias til='cd $HOME/.corpus/til'
# Tome shortcuts
alias tc='tome -nnn -create'
alias te='tome -nnn -edit'
alias td='tome -nnn -data'
# Directory shortcuts
alias cdrice='cd ~/src/srice'
alias cdsite='cd ~/src/krisyotam.com'
# ============================================================================
# MISC
# ============================================================================
alias sdn='sudo shutdown -h now'
alias delpyc='find . -type f -name "*.pyc" -delete && find . -type d -name __pycache__ -delete'
alias find-todos='rg "TODO|FIXME|HACK|XXX"'
alias diffo='diff -y --width=80'
alias diffq='diff -q'
# ============================================================================
# core functions
# ============================================================================
# ============================================================================
# NAVIGATION
# ============================================================================
# mkdir + cd in one step
mkd() {
mkdir -p "$@" && cd "$_"
}
# cd to git root
cdr() {
cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
}
# go up N directories
up() {
local d=""
local limit="${1:-1}"
for i in $(seq 1 "$limit"); do
d="../$d"
done
cd "$d" || return 1
}
# create dir and cd into it
take() {
mkdir -p "$1" && cd "$1"
}
# ============================================================================
# FZF INTEGRATIONS
# ============================================================================
# fuzzy open file in editor
fe() {
file=$(fd --type f --hidden --exclude .git | fzf \
--preview 'bat --color=always --style=numbers --line-range=:500 {}' \
--preview-window 'right:60%' \
--bind 'ctrl-/:toggle-preview')
[ -n "$file" ] && ${EDITOR:-nvim} "$file"
}
# fuzzy grep + open at line
fg() {
result=$(rg --column --line-number --no-heading --color=always --smart-case "${1:-}" |
fzf --ansi \
--color "hl:-1:underline,hl+:-1:underline:reverse" \
--delimiter : \
--preview 'bat --color=always {1} --highlight-line {2} --line-range {2}:+50' \
--preview-window 'up,60%,border-bottom')
if [ -n "$result" ]; then
file=$(echo "$result" | cut -d: -f1)
line=$(echo "$result" | cut -d: -f2)
${EDITOR:-nvim} "+$line" "$file"
fi
}
# fuzzy cd into subdirectory
fcd() {
dir=$(fd --type d --hidden --exclude .git | fzf \
--preview 'eza --tree --icons --level=2 --color=always {}' \
--preview-window 'right:50%')
[ -n "$dir" ] && cd "$dir"
}
# fuzzy git checkout branch
fbr() {
branch=$(git branch -a --sort=-committerdate |
sed 's/^..//' | sed 's#remotes/origin/##' | sort -u |
fzf --preview 'git log --oneline --graph --color=always {} -- | head -30')
[ -n "$branch" ] && git checkout "$branch"
}
# fuzzy git log browser
fgl() {
git log --oneline --graph --color=always --all --decorate |
fzf --ansi --no-sort \
--preview 'echo {} | grep -o "[a-f0-9]\{7,\}" | head -1 | xargs git show --color=always' \
--preview-window 'right:60%' \
--bind 'enter:execute(echo {} | grep -o "[a-f0-9]\{7,\}" | head -1 | xargs git show --color=always | less -R)'
}
# fuzzy git stash browser
fgs() {
stash=$(git stash list |
fzf --preview 'echo {} | cut -d: -f1 | xargs git stash show -p --color=always' \
--preview-window 'right:60%' |
cut -d: -f1)
[ -n "$stash" ] && git stash pop "$stash"
}
# fuzzy process kill
fkill() {
pid=$(ps aux |
fzf --header-lines=1 \
--preview 'echo {}' \
--preview-window 'down:3:wrap' |
awk '{print $2}')
[ -n "$pid" ] && kill "${1:--9}" "$pid"
}
# fuzzy man page
fman() {
man -k . 2>/dev/null | sort |
fzf --preview 'echo {} | awk "{print \$1}" | xargs man 2>/dev/null | head -80' |
awk '{print $1}' | xargs man
}
# fuzzy env vars
fenv() {
var=$(printenv | sort |
fzf --preview 'echo {} | cut -d= -f2-' \
--preview-window 'down:3:wrap')
[ -n "$var" ] && echo "$var"
}
# fuzzy docker container exec
fdex() {
container=$(docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}' |
fzf --preview 'echo {} | awk "{print \$1}" | xargs docker logs --tail 20 2>&1')
[ -n "$container" ] && docker exec -it "$(echo "$container" | awk '{print $1}')" "${1:-/bin/sh}"
}
# fuzzy tmux session switcher
fts() {
session=$(tmux list-sessions -F '#S' 2>/dev/null |
fzf --preview 'tmux list-windows -t {} -F " #{window_index}: #{window_name} (#{pane_current_path})"')
[ -n "$session" ] && tmux switch-client -t "$session"
}
# fuzzy history search
fh() {
cmd=$(history | sort -rn | awk '{$1=""; print substr($0,2)}' | sort -u |
fzf --preview 'echo {}' --preview-window 'down:3:wrap')
[ -n "$cmd" ] && eval "$cmd"
}
# fuzzy SSH host connect
fssh() {
host=$(grep -E '^Host\s' ~/.ssh/config 2>/dev/null | awk '{print $2}' | grep -v '\*' |
fzf --preview 'grep -A5 "Host {}" ~/.ssh/config')
[ -n "$host" ] && ssh "$host"
}
# ============================================================================
# GIT POWER FUNCTIONS
# ============================================================================
# git commit browser
gshow() {
git log --oneline -20 | fzf --preview 'git show --color=always {1}' | cut -d' ' -f1 | xargs git show
}
# find when a string was introduced (pickaxe search)
gwhen() {
[ -z "$1" ] && { echo "Usage: gwhen <string>"; return 1; }
git log -p -S "$1" --all
}
# show all files changed between two branches
gbetween() {
base="${2:-main}"
git diff --name-status "$base"..."${1:-HEAD}"
}
# interactive fixup
gfixup() {
commit=$(git log --oneline -20 |
fzf --preview 'git show --color=always {1}' |
cut -d' ' -f1)
if [ -n "$commit" ]; then
git commit --fixup="$commit" && git rebase -i --autosquash "$commit"~1
fi
}
# WIP commit
gwip() {
git add -A && git commit -m "WIP: $(date +%H:%M)"
}
# undo last commit but keep changes
gundo() {
git reset --soft HEAD~1
}
# show what I did today
gtoday() {
git log --since="midnight" --author="$(git config user.name)" --oneline
}
# show what I did this week
gweek() {
git log --since="1 week ago" --author="$(git config user.name)" --oneline --stat
}
# diff with delta side-by-side
gdelta() {
git diff "$@" | delta --side-by-side
}
# interactive branch delete (safe, skips main/master)
gbdel() {
branches=$(git branch --sort=-committerdate |
sed 's/^..//' | grep -v "main\|master" |
fzf -m --preview 'git log --oneline --graph --color=always {} | head -20')
[ -n "$branches" ] && echo "$branches" | xargs git branch -d
}
# git contributors
gcontrib() {
git shortlog -sn --all --no-merges
}
# diff stat between current branch and base
gdiffstat() {
base="${1:-main}"
git diff --stat "$base"...HEAD
}
# amend + force push (feature branches only)
gpatch() {
git add -A && git commit --amend --no-edit && git push --force-with-lease
}
# show git remote URL and open in browser
grepo() {
url=$(git config --get remote.origin.url)
url=${url%.git}
url=$(echo "$url" | sed 's|git@github.com:|https://github.com/|')
echo "$url"
command -v xdg-open >/dev/null && xdg-open "$url" 2>/dev/null
}
# ============================================================================
# C / SYSTEMS DEVELOPMENT
# ============================================================================
# compile and run C file
crun() {
file="$1"; shift
[ -z "$file" ] && { echo "Usage: crun <file.c> [args...]"; return 1; }
out="${file%.c}"
cc -std=c11 -Wall -Wextra -Wpedantic -g -O0 -fsanitize=address,undefined "$file" -o "$out" && "./$out" "$@"
}
# compile C with full warnings (treat as errors)
cstrict() {
file="$1"; shift
[ -z "$file" ] && { echo "Usage: cstrict <file.c>"; return 1; }
out="${file%.c}"
cc -std=c11 -Wall -Wextra -Wpedantic -Werror -Wshadow -Wconversion \
-Wdouble-promotion -Wformat=2 -Wundef -fno-common \
-g -O0 -fsanitize=address,undefined "$file" -o "$out"
}
# run valgrind with full leak check
memcheck() {
[ -z "$1" ] && { echo "Usage: memcheck <binary> [args...]"; return 1; }
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \
--verbose "$@" 2>&1
}
# generate compile_commands.json for clangd/LSP
compdb() {
if [ -f Makefile ]; then
bear -- make -j"$(nproc)" 2>/dev/null || compiledb make -j"$(nproc)"
elif [ -f CMakeLists.txt ]; then
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -B build .
ln -sf build/compile_commands.json .
else
echo "No Makefile or CMakeLists.txt found"
return 1
fi
}
# size of each section in a binary
secsize() {
[ -z "$1" ] && { echo "Usage: secsize <binary>"; return 1; }
size -A "$1" | sort -k2 -n
}
# disassemble a function from a binary
disas() {
bin="$1"; func="$2"
[ -z "$func" ] && { echo "Usage: disas <binary> <function>"; return 1; }
objdump -d "$bin" | awk "/^[0-9a-f]+ <$func>:/,/^$/"
}
# ============================================================================
# KERNEL DEVELOPMENT
# ============================================================================
# build kernel modules in current directory
kbuild() {
make -C /lib/modules/"$(uname -r)"/build M="$(pwd)" modules
}
# load module from current directory
kload() {
mod="$1"
[ -z "$mod" ] && { echo "Usage: kload <module.ko>"; return 1; }
sudo insmod "$mod" && echo "[+] Loaded $mod" && dmesg | tail -5
}
# unload module
kunload() {
mod="$1"
[ -z "$mod" ] && { echo "Usage: kunload <module_name>"; return 1; }
sudo rmmod "$mod" && echo "[+] Unloaded $mod" && dmesg | tail -5
}
# trace a kernel function with ftrace
ktrace() {
func="$1"
[ -z "$func" ] && { echo "Usage: ktrace <function_name>"; return 1; }
echo "[*] Tracing $func (Ctrl+C to stop)..."
sudo sh -c "
echo nop > /sys/kernel/debug/tracing/current_tracer
echo function > /sys/kernel/debug/tracing/current_tracer
echo $func > /sys/kernel/debug/tracing/set_ftrace_filter
echo 1 > /sys/kernel/debug/tracing/tracing_on
cat /sys/kernel/debug/tracing/trace_pipe
"
}
# quick perf profile and flamegraph
kperf() {
[ -z "$1" ] && { echo "Usage: kperf <command>"; return 1; }
perf record -g -- "$@"
perf script | stackcollapse-perf.pl | flamegraph.pl > flamegraph.svg
echo "[+] Flamegraph: flamegraph.svg"
}
# ============================================================================
# WEB DEVELOPMENT
# ============================================================================
# kill whatever is on a port
killport() {
port="$1"
[ -z "$port" ] && { echo "Usage: killport <port>"; return 1; }
pid=$(lsof -ti ":$port" 2>/dev/null || ss -tlnp "sport = :$port" | awk 'NR>1{print $6}' | grep -oP 'pid=\K\d+')
if [ -n "$pid" ]; then
kill -9 "$pid" && echo "[+] Killed PID $pid on port $port"
else
echo "[-] Nothing on port $port"
fi
}
# quick local HTTP server
serve() {
port="${1:-8000}"
echo "[*] Serving $(pwd) on http://localhost:$port"
python3 -m http.server "$port" --bind 127.0.0.1
}
# JSON pretty print
jqp() {
if [ -n "$1" ]; then
python3 -m json.tool "$1"
else
python3 -m json.tool
fi
}
# ============================================================================
# DOCKER HELPERS
# ============================================================================
# shell into a running container
dsh() {
container="$1"
[ -z "$container" ] && { echo "Usage: dsh <container>"; return 1; }
docker exec -it "$container" /bin/sh -c "command -v bash >/dev/null && exec bash || exec sh"
}
# follow logs with timestamps
dlogs() {
container="$1"
[ -z "$container" ] && { echo "Usage: dlogs <container>"; return 1; }
docker logs -f --timestamps "$container"
}
# docker stats (formatted)
dstats() {
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"
}
# remove stopped containers, dangling images, unused volumes
dcleanup() {
docker container prune -f
docker image prune -f
docker volume prune -f
echo "[+] Docker cleaned"
}
# list images sorted by size
dimages() {
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | sort -k3 -h
}
# ============================================================================
# FILE UTILITIES
# ============================================================================
# extract anything
extract() {
if [ -f "$1" ]; then
case "$1" in
*.tar.bz2) tar xjf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*.tar.xz) tar xJf "$1" ;;
*.tar.zst) tar --zstd -xf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar x "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.7z) 7z x "$1" ;;
*.xz) xz -d "$1" ;;
*.zst) zstd -d "$1" ;;
*) echo "Don't know how to extract '$1'" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
# file/dir size (human readable)
fsize() {
du -sh "${1:-.}" | cut -f1
}
# count files recursively
fcount() {
fd --type f "${1:-.}" | wc -l
}
# diff two directories
dirdiff() {
typeset a=$(mktemp) b=$(mktemp)
(cd "$1" && find . -type f | sort) > "$a"
(cd "$2" && find . -type f | sort) > "$b"
diff "$a" "$b"
rm -f "$a" "$b"
}
# backup a file
bak() {
[ -z "$1" ] && { echo "Usage: bak <file>"; return 1; }
cp -a "$1" "${1}.bak.$(date +%Y%m%d%H%M%S)"
}
# side-by-side diff
sdiff() {
diff --side-by-side --suppress-common-lines "$1" "$2"
}
# find files larger than a given size
findlarge() {
local size="${1:-100M}"
fd --type f --size "+$size" | xargs ls -lhS 2>/dev/null
}
# create a tar.gz from a directory
tgz() {
[ -z "$1" ] && { echo "Usage: tgz <dir>"; return 1; }
tar -czf "${1%/}.tar.gz" "$1"
}
# ============================================================================
# NETWORK
# ============================================================================
# what is using a port
whatsport() {
port="$1"
[ -z "$port" ] && { echo "Usage: whatsport <port>"; return 1; }
ss -tlnp "sport = :$port" 2>/dev/null || lsof -i ":$port"
}
# quick DNS lookup
dig1() {
dig +nocmd "$1" any +multiline +noall +answer
}
# test HTTP endpoint response time
httptime() {
url="$1"
[ -z "$url" ] && { echo "Usage: httptime <url>"; return 1; }
curl -o /dev/null -s -w "\
DNS: %{time_namelookup}s\n\
Connect: %{time_connect}s\n\
TLS: %{time_appconnect}s\n\
Start: %{time_starttransfer}s\n\
Total: %{time_total}s\n\
Size: %{size_download} bytes\n\
Status: %{http_code}\n" "$url"
}
# ============================================================================
# SUCKLESS WORKFLOW
# ============================================================================
# edit suckless config and remind about deploy steps
sledit() {
prog="$1"
[ -z "$prog" ] && { echo "Usage: sledit <dwm|st|dmenu|dwmblocks>"; return 1; }
dir="$HOME/src/$prog"
[ ! -d "$dir" ] && { echo "No directory: $dir"; return 1; }
${EDITOR:-nvim} "$dir/config.h"
echo "---"
echo "To deploy to laptop:"
echo " cd $dir && git add -A && git commit -m 'config update' && git push"
echo " ssh server 'cd ~/.local/src/$prog && git pull && sudo make clean install'"
}
# ============================================================================
# PROJECT SCAFFOLDING
# ============================================================================
# init a minimal C project
cinit() {
name="$1"
[ -z "$name" ] && { echo "Usage: cinit <project-name>"; return 1; }
mkdir -p "$name/src"
cat > "$name/src/main.c" << 'CEOF'
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
(void)argc;
(void)argv;
return 0;
}
CEOF
cat > "$name/Makefile" << 'MKEOF'
CC = cc
CFLAGS = -std=c11 -Wall -Wextra -Wpedantic -g
LDFLAGS =
SRC = src/main.c
OBJ = $(SRC:.c=.o)
BIN = $(notdir $(CURDIR))
all: $(BIN)
$(BIN): $(OBJ)
$(CC) $(LDFLAGS) -o $@ $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(OBJ) $(BIN)
.PHONY: all clean
MKEOF
cd "$name"
git init -q
echo "[+] C project '$name' initialized"
}
# ============================================================================
# PLAN 9
# ============================================================================
# mk wrapper
p9mk() {
if command -v mk >/dev/null 2>&1; then
mk "$@"
else
echo "mk not found. Install plan9port."
fi
}
# plumb a file (Plan 9 style)
p9plumb() {
[ -z "$1" ] && { echo "Usage: p9plumb <file>"; return 1; }
if command -v 9 >/dev/null 2>&1; then
9 plumb "$1"
elif command -v plumb >/dev/null 2>&1; then
plumb "$1"
else
echo "plan9port not installed"
fi
}
# open file with appropriate handler (Plan 9 style plumb for Linux)
p9open() {
file="$1"
[ -z "$file" ] && { echo "Usage: p9open <file>"; return 1; }
case "$file" in
*.pdf) zathura "$file" & ;;
*.png|*.jpg|*.jpeg|*.gif) sxiv "$file" & ;;
*.mp4|*.mkv|*.webm) mpv "$file" & ;;
*.mp3|*.flac|*.ogg) mpv --no-video "$file" & ;;
*.html) $BROWSER "$file" & ;;
http://*|https://*) $BROWSER "$file" & ;;
*) ${EDITOR:-nvim} "$file" ;;
esac
}
# ============================================================================
# SOURCEHUT
# ============================================================================
# send patches to a sr.ht mailing list
srht_send() {
list="${1:-$(git config sendemail.to)}"
[ -z "$list" ] && { echo "Usage: srht_send <list@lists.sr.ht> or set sendemail.to"; return 1; }
base=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master)
git send-email --to="$list" "$base"..HEAD
}
# send revision (v2, v3, etc.)
srht_resend() {
list="${1:-$(git config sendemail.to)}"
version="${2:-2}"
[ -z "$list" ] && { echo "Usage: srht_resend <list> <version>"; return 1; }
base=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master)
git send-email --annotate -v"$version" --to="$list" "$base"..HEAD
}
# apply patches from sr.ht mbox URL
srht_apply() {
[ -z "$1" ] && { echo "Usage: srht_apply <mbox-url>"; return 1; }
curl -s "$1" | git am -3
}
# quick GraphQL query to any sr.ht service
srht_gql() {
service="$1"; shift
echo "$*" | hut graphql "$service"
}
# poll build status until completion
srht_wait() {
job_id="$1"
[ -z "$job_id" ] && { echo "Usage: srht_wait <job-id>"; return 1; }
token=$(cat ~/.config/srht/token)
while true; do
status=$(curl -s --oauth2-bearer "$token" -H 'Content-Type: application/json' \
-d "{\"query\": \"{ job(id: $job_id) { status } }\"}" \
https://builds.sr.ht/query | python3 -c "import json,sys; print(json.load(sys.stdin)['data']['job']['status'])")
printf "\r[%s] Job %s: %s" "$(date +%H:%M:%S)" "$job_id" "$status"
case "$status" in
SUCCESS|FAILED|TIMEOUT|CANCELLED) echo; return ;;
esac
sleep 10
done
}
# ============================================================================
# NNN
# ============================================================================
# nnn with cd on exit
n() {
if [ -n "$NNNLVL" ] && [ "$NNNLVL" -ge 1 ]; then
echo "nnn is already running"
return
fi
NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
export NNN_TMPFILE
nnn -Q "$@"
if [ -f "$NNN_TMPFILE" ]; then
. "$NNN_TMPFILE"
rm -f "$NNN_TMPFILE"
fi
}
# Script editor -- pick and edit scripts in ~/.local/bin
se() {
choice=$(find ~/.local/bin -mindepth 1 -printf '%P\n' | fzf)
[ -n "$choice" ] && [ -f "$HOME/.local/bin/$choice" ] && $EDITOR "$HOME/.local/bin/$choice"
}
# search repo names in ~/src/
reposearch() {
[ -z "$1" ] && { echo "usage: reposearch <pattern>"; return 1; }
pattern=$(echo "$*" | tr '[:upper:]' '[:lower:]')
matches=""
count=0
for d in "$HOME"/src/*/; do
name=${d%/}
name=${name##*/}
lower=$(echo "$name" | tr '[:upper:]' '[:lower:]')
case "$lower" in
*"$pattern"*) matches="$matches$name
"; count=$((count + 1)) ;;
esac
done
if [ "$count" -eq 0 ]; then
printf '\n \033[2mno matches for\033[0m \033[1m%s\033[0m\n\n' "$*"
return 1
fi
printf '\n \033[2m%d match(es) for\033[0m \033[1m%s\033[0m\n\n' "$count" "$*"
echo "$matches" | while IFS= read -r m; do
[ -n "$m" ] && printf ' \033[36m>\033[0m %s\n' "$m"
done
printf '\n'
}
lp() { cd "$HOME/edu/craft/learn"; }
fcc() { cd "$HOME/edu/craft/freecodecamp"; }
# ============================================================================
# DRIVE FORMATTING (adapted from omarchy, MIT license)
# ============================================================================
# write iso to sd card
iso2sd() {
if [ $# -lt 1 ]; then
echo "Usage: iso2sd <input_file> [output_device]"
echo "Example: iso2sd ~/dl/archlinux.iso /dev/sda"
return 1
fi
local iso="$1"
local drive="$2"
if [ -z "$drive" ]; then
echo "Available drives:"
lsblk -dpno NAME,SIZE,MODEL | grep -E '/dev/sd'
printf "Select drive: "
read drive
[ -z "$drive" ] && echo "No drive selected" && return 1
fi
sudo dd bs=4M status=progress oflag=sync if="$iso" of="$drive"
sudo eject "$drive"
}
# format entire drive as single exFAT partition
format-drive() {
if [ $# -ne 2 ]; then
echo "Usage: format-drive <device> <name>"
echo "Example: format-drive /dev/sda 'My Stuff'"
echo ""
echo "Available drives:"
lsblk -d -o NAME -n | awk '{print "/dev/"$1}'
return 1
fi
echo "WARNING: This will completely erase all data on $1 and label it '$2'."
printf "Are you sure? (y/N): "
read confirm
case "$confirm" in
[Yy])
sudo wipefs -a "$1"
sudo dd if=/dev/zero of="$1" bs=1M count=100 status=progress
sudo parted -s "$1" mklabel gpt
sudo parted -s "$1" mkpart primary 1MiB 100%
sudo parted -s "$1" set 1 msftdata on
case "$1" in
*nvme*) partition="${1}p1" ;;
*) partition="${1}1" ;;
esac
sudo partprobe "$1" || true
sudo udevadm settle || true
sudo mkfs.exfat -n "$2" "$partition"
echo "Drive $1 formatted as exFAT and labeled '$2'."
;;
esac
}
# ============================================================================
# SSH PORT FORWARDING (adapted from omarchy, MIT license)
# ============================================================================
# forward ports: fip <host> <port1> [port2] ...
fip() {
[ $# -lt 2 ] && echo "Usage: fip <host> <port1> [port2] ..." && return 1
local host="$1"
shift
for port in "$@"; do
ssh -f -N -L "$port:localhost:$port" "$host" && echo "Forwarding localhost:$port -> $host:$port"
done
}
# stop forwarding: dip <port1> [port2] ...
dip() {
[ $# -eq 0 ] && echo "Usage: dip <port1> [port2] ..." && return 1
for port in "$@"; do
pkill -f "ssh.*-L $port:localhost:$port" && echo "Stopped forwarding port $port" || echo "No forwarding on port $port"
done
}
# list active port forwards
lip() {
pgrep -af "ssh.*-L [0-9]+:localhost:[0-9]+" || echo "No active forwards"
}
# ============================================================================
# SYSTEM
# ============================================================================
# show listening ports with process names
portsinfo() {
ss -tlnp | awk 'NR>1 {print $4, $6}' | column -t
}
# quick system overview
sysoverview() {
echo "Hostname: $(hostname)"
echo "Kernel: $(uname -r)"
echo "Uptime: $(uptime -p)"
echo "CPU: $(nproc) cores"
echo "Memory: $(free -h | awk '/Mem:/ {print $3 "/" $2}')"
echo "Disk: $(df -h / | awk 'NR==2 {print $3 "/" $2 " (" $5 ")"}')"
echo "Load: $(cut -d' ' -f1-3 /proc/loadavg)"
}
# pipe to clipboard (wayland, X, or macOS)
clipfn() {
if command -v wl-copy >/dev/null 2>&1; then
wl-copy
elif command -v xclip >/dev/null 2>&1; then
xclip -selection clipboard
elif command -v pbcopy >/dev/null 2>&1; then
pbcopy
else
echo "No clipboard tool found"
return 1
fi
}
# deduplicate PATH entries
pathdedup() {
PATH=$(echo "$PATH" | tr ':' '\n' | awk '!seen[$0]++' | tr '\n' ':' | sed 's/:$//')
export PATH
echo "PATH deduplicated"
}
# ============================================================================
# ENCODING / DATA
# ============================================================================
# percent-encode a string
urlencode() {
python3 -c "import urllib.parse; print(urllib.parse.quote('$*'))"
}
# decode a percent-encoded string
urldecode() {
python3 -c "import urllib.parse; print(urllib.parse.unquote('$*'))"
}
# minify JSON from stdin
jqmin() {
python3 -c "import json,sys; json.dump(json.load(sys.stdin),sys.stdout,separators=(',',':'))"
}
# ============================================================================
# MISC UTILITIES
# ============================================================================
# quick note
note() {
echo "$(date +%Y-%m-%d\ %H:%M) -- $*" >> "$HOME/.notes"
}
# show notes
notes() {
[ -f "$HOME/.notes" ] && cat "$HOME/.notes" || echo "No notes yet"
}
# weather
wttr() {
curl -s "wttr.in/${1:-}?format=v2"
}
# cheat.sh
cheat() {
curl -s "cheat.sh/$1"
}
# count lines of code
loc() {
if command -v tokei >/dev/null 2>&1; then
tokei "${1:-.}"
else
find "${1:-.}" -name '*.c' -o -name '*.h' -o -name '*.go' -o -name '*.py' \
-o -name '*.js' -o -name '*.ts' -o -name '*.tsx' -o -name '*.rs' |
xargs wc -l | tail -1
fi
}
# benchmark a command N times
benchn() {
n="${1:-10}"; shift
[ -z "$1" ] && { echo "Usage: benchn <N> <command...>"; return 1; }
hyperfine --runs "$n" "$*"
}
# quick timer
timer() {
start=$(date +%s)
echo "Timer started. Press Enter to stop."
read -r _
elapsed=$(( $(date +%s) - start ))
printf "Elapsed: %02d:%02d:%02d\n" $((elapsed/3600)) $((elapsed%3600/60)) $((elapsed%60))
}
# colorized man pages
man() {
LESS_TERMCAP_md=$'\e[01;31m' \
LESS_TERMCAP_me=$'\e[0m' \
LESS_TERMCAP_so=$'\e[01;44;33m' \
LESS_TERMCAP_se=$'\e[0m' \
LESS_TERMCAP_us=$'\e[01;32m' \
LESS_TERMCAP_ue=$'\e[0m' \
command man "$@"
}
# feedsync -- sync kris.opml into sfeedrc
feedsync() {
opml="$HOME/src/krisyotam.com/public/kris.opml"
if [ ! -f "$opml" ]; then
echo "feedsync: $opml not found" >&2
return 1
fi
sfeed_opml_import <"$opml" >"$HOME/.sfeed/sfeedrc"
echo "sfeedrc updated from kris.opml"
}
# Launch Google Earth Pro (detached)
earth() {
setsid google-earth-pro >/dev/null 2>&1 &
}