# 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 "; 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 [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 "; 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 [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 "; return 1; } size -A "$1" | sort -k2 -n } # disassemble a function from a binary disas() { bin="$1"; func="$2" [ -z "$func" ] && { echo "Usage: disas "; 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 "; return 1; } sudo insmod "$mod" && echo "[+] Loaded $mod" && dmesg | tail -5 } # unload module kunload() { mod="$1" [ -z "$mod" ] && { echo "Usage: kunload "; 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 "; 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 "; 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 "; 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 "; 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 "; 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 "; 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 "; return 1; } tar -czf "${1%/}.tar.gz" "$1" } # ============================================================================ # NETWORK # ============================================================================ # what is using a port whatsport() { port="$1" [ -z "$port" ] && { echo "Usage: whatsport "; 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 "; 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 "; 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 "; return 1; } mkdir -p "$name/src" cat > "$name/src/main.c" << 'CEOF' #include #include 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 "; 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 "; 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 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 "; 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 "; 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 "; 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 "; 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 [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 " 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 [port2] ... fip() { [ $# -lt 2 ] && echo "Usage: fip [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 [port2] ... dip() { [ $# -eq 0 ] && echo "Usage: dip [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 "; 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 & }