Mastodon
Menu
home
start
about
me
links
reach out
journal
writings
social
posts
bookmarks
saves
photos
memories
news
breaking
podcasts
listening
uses
tools & stack
startyparty
homepage
Contact & Social
© 2008 - 2026 Marko Bajlovic
Version5.18.5

Terminal Tooling

May 1, 2026

The terminal is pretty much my second home. It's where code gets written, systems get debugged, files get wrangled, and ideas get shipped. Over the past several years, I've spent a lot of time curating a set of tools that genuinely make me faster, happier, and more productive. If there's a CLI way to do something, I'll use it.

This isn't just a list of "cool CLI tools you should know about." Every single one of these is something I actively use on a weekly—often daily—basis. Some replace built-in Unix commands with dramatically better alternatives. Others unlock entirely new workflows that weren't possible before. A few have become so integral to how I work that I'd genuinely struggle without them.

The philosophy behind this collection is simple: good tools amplify your capabilities.

This guide covers installation via Homebrew, what each tool actually does, and the specific ways I use it in practice. Think of this as both a reference guide and an invitation to level up your terminal game.


Table of Contents

  1. Shell & Environment
  2. Navigation & Discovery
  3. Search & Find
  4. File Viewing & Processing
  5. Git Workflow
  6. System Monitoring
  7. Media Processing
  8. Window Management (macOS)
  9. Text Editors
  10. AI-Powered Tools

Shell & Environment

zsh + Oh My Zsh

Repository: https://ohmyz.sh
Github: https://github.com/ohmyzsh/ohmyzsh What it is: A modern shell with an intelligent framework for configuration

Before you install anything else, you need a solid shell foundation. zsh is a powerful shell that succeeds bash with better completion, better globbing, and more intuitive scripting. But what transforms it from "a better bash" into something genuinely enjoyable is Oh My Zsh—an open-source framework that manages your Zsh configuration and provides thousands of plugins, themes, and helper functions.

Installation:

brew install zsh sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

What I get out of it:

  • Smart tab completion that understands git branches, npm scripts, and context
  • Syntax highlighting that shows invalid commands before you press Enter
  • A massive ecosystem of plugins that extend functionality
  • Hotkeys and aliases that become second nature

Preferred Plugins

# In ~/.zshrc, I enable these plugins: plugins=(git z fzf nvm zsh-syntax-highlighting ripgrep)

This is a deep rabbit hole — I'd recommend exploring all the customizations and commonly used configs. I keep a very simple layout that shows me the active git branch, current directory, user, and whether there are any staged or unstaged changes.


nvm (Node Version Manager)

Repository: https://github.com/nvm-sh/nvm
What it is: Version manager for Node.js

Anyone who works across multiple Node.js projects knows the pain of version conflicts. You're on a legacy project that needs Node 16, then jump to a modern one that requires Node 20. Without nvm, this becomes a nightmare of manual version switching.

Installation:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # Then add to ~/.zshrc: export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

What I get out of it:

  • Install any Node.js version with a single command
  • Switch between versions instantly
  • Automatically switch versions based on .nvmrc files in project roots
  • Per-project version pinning without conflict
  • Works seamlessly with all npm tools

Practical usage:

# Install the latest LTS version nvm install --lts # Install a specific version nvm install 18.16.0 # Switch to a specific version nvm use 18 # See all installed versions nvm list # Set a default version nvm alias default 20 # Pin version in a project (creates .nvmrc) echo "18" > .nvmrc nvm use # Automatically switches to version 18

Pro tip: Add this to your .zshrc for automatic version switching:

# Automatically switch Node versions based on .nvmrc autoload -U add-zsh-hook load-nvmrc() { local node_version="$(nvm version)" local nvmrc_path="$(nvm_find_nvmrc)" if [ -n "$nvmrc_path" ]; then local nvmrc_node_version=$(cat "$nvmrc_path") if [ "$nvmrc_node_version" != "$node_version" ]; then nvm use fi fi } add-zsh-hook chpwd load-nvmrc load-nvmrc # or to Lazyload NVM — only loads when you first call node, npm, nvm, etc. export NVM_DIR="$HOME/.nvm" nvm() { unfunction nvm node npm npx pnpm yarn [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh" nvm "$@" } node() { nvm; node "$@" } npm() { nvm; npm "$@" } npx() { nvm; npx "$@" }

mackup (Dotfile Manager)

Repository: https://github.com/lra/mackup
What it is: Synchronizes application settings and dotfiles to cloud storage

Setting up a new machine used to take an entire day. Manually restoring .zshrc, copying over SSH keys, reconfiguring the editor, reinstalling preferences. With mackup, that process takes minutes.

mackup symlinks your application configurations, and I track the mackup directory with Git so I can restore my entire setup on a new machine with a single command.

Installation:

brew install mackup

What I get out of it:

  • Never lose your configurations again
  • Automatic backup to cloud storage
  • Supports 500+ applications out of the box
  • One command to restore everything on a new machine
  • Your setup becomes portable and version-controlled

Practical usage:

# Back up all supported application configs mackup backup # On a new machine, restore everything instantly mackup restore # See which applications are supported mackup list # Uninstall (reverses symlinks) mackup uninstall

Alternatives to mackup:

  • chezmoi
  • rcm
  • homesick
  • stow

Navigation & Discovery

eza (Modern ls)

Repository: https://github.com/eza-community/eza
What it is: A modern, maintained replacement for ls with colors, icons, and git integration

ls is ancient. Its syntax is cryptic, output is monochrome, and it provides no context about file changes. eza modernizes the whole experience with sensible defaults and powerful options.

Installation:

brew install eza

What I get out of it:

  • Beautiful colored output by default
  • Shows git status per file (modified, staged, untracked)
  • Renders file icons
  • Tree view for understanding directory structures
  • Actively maintained

My aliases:

alias ls="eza" alias ll="eza -la --icons" alias lt="eza --tree --level=2 --icons" # this is something i do but i typically don't recommend overwriting commands unalias ls alias ls="eza -lhaGF --icons --git"

Practical usage:

# List files with git status eza -la --icons --git # Show git status and sort by size eza -la --icons --git --sort=size # Beautiful tree view (2 levels deep) eza --tree --level=2 --icons # Show all files including hidden eza -a --icons # Sort by modification time (find recent changes) eza -la --sort=modified # Extended attributes eza -la --extended
# Quickly understand a new project's structure eza --tree --level=3 --icons --git # src/ # ├── components/ # │ ├── Header.tsx (git status shown) # │ └── Footer.tsx # ├── pages/ # └── utils/

z (Directory Jumping)

Repository: https://github.com/rupa/z
What it is: Tracks your most-used directories for instant navigation

z is deceptively simple but absolutely essential. It learns which directories you visit most often and lets you jump to them by typing just a fragment of the path.

Visit ~/projects/my-app/src/components once, and from then on z components takes you there instantly. The more you use it, the smarter it gets — it builds a "frecency" score (frequency + recency) per directory.

Installation:

brew install z echo '. /opt/homebrew/etc/profile.d/z.sh' >> ~/.zshrc

What I get out of it:

  • Eliminates repetitive directory navigation
  • Learns from your actual workflow
  • Incredibly fast — just a few keystrokes
  • Works across sessions
  • Pairs beautifully with other tools

Practical usage:

# Jump to the most frecent directory matching "proj" z proj # Jump to specific subdirectory z proj components # List all directories matching a pattern with scores z -l api # Recent directories only z -r proj # Print the path without changing directory z -e proj
# Your frecency database builds automatically: cd ~/projects/my-app cd ~/projects/my-app/src cd ~/projects/my-app/src/components cd ~/projects/other-project # Now you can jump with minimal typing: z comp # Takes you to ~/projects/my-app/src/components z my-app # Takes you to ~/projects/my-app z other # Takes you to ~/projects/other-project

Search & Find

fd (User-Friendly find)

Repository: https://github.com/sharkdp/fd
What it is: A simple, fast alternative to find with sensible defaults

find is powerful but notoriously painful to use. The syntax is cryptic, it's slow, and it shows you everything including directories you don't care about. fd is what find should have been: fast, intuitive, and respecting .gitignore by default.

Installation:

brew install fd

What I get out of it:

  • Dramatically faster than find
  • Respects .gitignore automatically (no node_modules noise)
  • Sane, intuitive syntax
  • Beautiful colored output
  • Excellent regex and glob support

Practical usage:

# Find all .env files (respects .gitignore) fd .env # Find all TypeScript files in src/ fd -e ts -e tsx src/ # Find files modified in the last 24 hours fd --changed-within 24h # Find files by exact name match fd -x config.json # Find directories only fd -t d src # Find files only fd -t f src/ # Combine with other tools fd -e ts | xargs prettier --write # Find and delete (careful!) fd -t f ".DS_Store" -x rm

Integration with fzf:

# Fuzzy search all files and open in editor fd -t f | fzf | xargs nvim # Find and preview before opening fd -t f | fzf --preview 'bat --color=always {}'
fd -e conf -e config -e cfg -e toml -e yaml -e yml -e json | sort # Instantly find all configuration files across your project

fzf (Fuzzy Finder)

Repository: https://github.com/junegunn/fzf
What it is: A command-line fuzzy finder (I abuse this one)

fzf is hard to describe because it's less a tool and more a fundamental building block. At its core: pipe any list of items into it, and you get an interactive interface to filter and select. The real power comes from composing it with everything else.

Installation:

brew install fzf $(brew --prefix)/opt/fzf/install # Enable shell integrations

What I get out of it:

  • Interactive fuzzy search over any list
  • Beautiful keyboard-driven interface
  • Excellent preview capabilities
  • Integrates with shell history, env vars, and custom lists
  • Composable with any pipeline

Shell integrations (enabled automatically):

# Ctrl+R: Fuzzy search shell history Ctrl+R # Ctrl+T: Fuzzy search files in current directory Ctrl+T # Alt+C: Fuzzy search and change directory Alt+C

Practical usage:

# Interactive branch checkout git branch | fzf | xargs git checkout # Kill a process interactively ps aux | fzf | awk '{print $2}' | xargs kill -9 # Search and open with your editor fzf | xargs nvim # Fuzzy search npm scripts cat package.json | jq -r '.scripts | keys[]' | fzf | xargs npm run # Search git log git log --oneline | fzf | cut -d' ' -f1 | xargs git show

Advanced preview:

# File preview with bat syntax highlighting fd -t f | fzf --preview 'bat --color=always {}' # Git branch preview git branch | fzf --preview 'git log -1 --color=always {}' # Process preview with details ps aux | fzf --preview 'ps -p {2} -o pid,cmd,user,%cpu,%mem' # FZF Tab Completion # https://github.com/lincheney/fzf-tab-completion for installation instructions source ~/Git/fzf-tab-completion/zsh/fzf-zsh-completion.sh bindkey '^I' fzf_completion

Custom fzf wrapper:

# In your ~/.zshrc fe() { local file file=$(fd -t f | fzf --preview 'bat --color=always {}') [ -n "$file" ] && $EDITOR "$file" } # Now use: fe to open files with fuzzy search

My personal settings for fzf:

# FZF Options export FZF_CTRL_T_OPTS="--height 60% \ --border sharp \ --layout reverse \ --prompt '∷ ' \ --pointer ▶ \ --marker ⇒" export FZF_CTRL_R_OPTS=" --preview 'echo {}' --preview-window up:3:hidden:wrap --bind 'ctrl-/:toggle-preview' --bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort' --color header:italic --header 'Press CTRL-Y to copy command into clipboard'" # tomasr/molokai export FZF_DEFAULT_OPTS='--color=bg+:#293739,bg:#1B1D1E,border:#808080,spinner:#E6DB74,hl:#7E8E91,fg:#F8F8F2,header:#7E8E91,info:#A6E22E,pointer:#A6E22E,marker:#F92672,fg+:#F8F8F2,prompt:#F92672,hl+:#F92672' export FZF_DEFAULT_OPTS=$FZF_DEFAULT_OPTS' --color=fg:-1,fg+:#d0d0d0,bg:-1,bg+:#040404 --color=hl:#5f87af,hl+:#5fd7ff,info:#afaf87,marker:#d7005f --color=prompt:#87ff00,spinner:#d7005f,pointer:#d7005f,header:#87afaf --color=border:#262626,label:#aeaeae,query:#d9d9d9 --border="rounded" --border-label="" --preview-window="border-rounded" --prompt="> " --marker=">" --pointer="◆" --separator="─" --scrollbar="│"'

Custom functions I use with fzf:

############### ##### FZF ##### ############### # fd - cd into the selected directory fd() { DIR=`find * -maxdepth 0 -type d -print 2> /dev/null | fzf --height 40% \ --border sharp \ --layout reverse \ --prompt '∷ ' \ --pointer ▶ \ --marker ⇒ ` \ && cd "$DIR" } # fds - preview files fds() { find . -type f | fzf --style full \ --preview 'fzf-preview.sh {}' \ --bind 'focus:transform-header:file --brief {}' } # fdr - cd to selected parent directory fdr() { local declare dirs=() get_parent_dirs() { if [[ -d "${1}" ]]; then dirs+=("$1"); else return; fi if [[ "${1}" == '/' ]]; then for _dir in "${dirs[@]}"; do echo $_dir; done else get_parent_dirs $(dirname "$1") fi } local DIR=$(get_parent_dirs $(realpath "${1:-$PWD}") | fzf --height 40% \ --border sharp \ --layout reverse \ --prompt '∷ ' \ --pointer ▶ \ --marker ⇒ --tac) cd "$DIR" } # fcd - cd into the directory of the selected file fcd() { local file local dir file=$(fzf --height 40% \ --border sharp \ --layout reverse \ --prompt '∷ ' \ --pointer ▶ \ --marker ⇒ +m -q "$1") && dir=$(dirname "$file") && cd "$dir" } # fh - repeat command history fh() { eval $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf --height 40% \ --border sharp \ --layout reverse \ --prompt '∷ ' \ --pointer ▶ \ --marker ⇒ +s --tac | sed -E 's/ *[0-9]*\*? *//' | sed -E 's/\\/\\\\/g') } # fkill - kill processes - list only the ones you can kill. fkill() { local pid if [ "$UID" != "0" ]; then pid=$(ps -f -u $UID | sed 1d | fzf --height 40% \ --border sharp \ --layout reverse \ --prompt '∷ ' \ --pointer ▶ \ --marker ⇒ -m | awk '{print $2}') else pid=$(ps -ef | sed 1d | fzf --height 60% \ --border sharp \ --layout reverse \ --prompt '∷ ' \ --pointer ▶ \ --marker ⇒ -m | awk '{print $2}') fi if [ "x$pid" != "x" ] then echo $pid | xargs kill -${1:-9} fi } # fbr - checkout git branch (including remote branches) fbr() { local branches branch branches=$(git branch --all | grep -v HEAD) && branch=$(echo "$branches" | fzf-tmux -d $(( 2 + $(wc -l <<< "$branches") )) +m) && git checkout $(echo "$branch" | sed "s/.* //" | sed "s#remotes/[^/]*/##") } # smite - delete command history smite() { setopt LOCAL_OPTIONS ERR_RETURN PIPE_FAIL local opts=( -I ) if [[ $1 == '-a' ]]; then opts=() elif [[ -n $1 ]]; then print >&2 'usage: smite [-a]' return 1 fi fc -l -n $opts 1 | \ fzf --no-sort --tac --multi | \ while IFS='' read -r command_to_delete; do printf 'Removing history entry "%s"\n' $command_to_delete local HISTORY_IGNORE="${(b)command_to_delete}" fc -W fc -p $HISTFILE $HISTSIZE $SAVEHIST done } # fcoc - checkout git commit fcoc() { local commits commit commits=$(git log --pretty=oneline --abbrev-commit --reverse) && commit=$(echo "$commits" | fzf --tac +s +m -e) && git checkout $(echo "$commit" | sed "s/ .*//") } # fshow - git commit browser (& view commit contents) fshow() { git log --graph --color=always \ --format="%C(auto)%h%d %s %C(black)%C(bold)%cr" "$@" | fzf --ansi --no-sort --reverse --tiebreak=index --bind=ctrl-s:toggle-sort \ --bind "ctrl-/:execute: (grep -o '[a-f0-9]\{7\}' | head -1 | xargs -I % sh -c 'git show --color=always % | less -R') << 'FZF-EOF' {} FZF-EOF" } # rmf - delete file from fzf rmf() { if [[ "$#" -eq 0 ]]; then local files files=$(find . -maxdepth 1 -type f | fzf --multi) echo $files | xargs -I '{}' rm {} else command rm "$@" fi } # aliases - browse and run aliases aliases() { CMD=$( ( (alias) (functions | grep "()" | cut -d ' ' -f1 | grep -v "^_" ) ) | fzf | cut -d '=' -f1 ); eval $CMD } # envs - search env vars envs() { local out out=$(env | fzf) echo $(echo $out | cut -d= -f2) } # z - smarter cd unalias z 2> /dev/null z() { [ $# -gt 0 ] && _z "$*" && return cd "$(_z -l 2>&1 | fzf --height 40% --nth 2.. --reverse --inline-info +s --tac --query "${*##-* }" | sed 's/^[0-9,.]* *//')" } bindkey "${key[Up]}" fzf-history-widget

ripgrep (Fast Search)

Repository: https://github.com/BurntSushi/ripgrep
What it is: Recursively searches directories for regex patterns (at warp speed)

ripgrep (rg) searches through directory trees for regex patterns. It's not just "a faster grep" — it's orders of magnitude faster. It automatically respects .gitignore, skips .git and node_modules, shows context beautifully, and handles massive codebases without breaking a sweat.

Installation:

brew install ripgrep alias grep="rg" # In ~/.zshrc

What I get out of it:

  • Extraordinarily fast (typically 5-10x faster than grep)
  • Automatically skips ignored files and directories
  • Beautiful colored output with context lines
  • Excellent for searching large codebases
  • Supports Unicode and complex patterns
  • Used by many editors and tools under the hood

Practical usage:

# Simple search rg "useEffect" src/ # List only filenames (no line output) rg -l "TODO" # Search only specific file types rg -t ts "interface.*Props" # Show context (3 lines before/after) rg -C 3 "error" logs/ # Case-insensitive search rg -i "debug" src/ # Regex pattern matching rg "function\s+(\w+)" -o # Show line numbers rg -n "import React" # Exclude specific patterns rg "password" --glob '!*.env' # Count matches rg "TODO" --count
# Find all imports in a project rg "^import" -t ts -t tsx # Locate where a function is called rg "processPayment\(" --glob '*.js' # Find potential security issues rg "eval\(|exec\(" --glob '*.js' # Search with context in config files rg "timeout" -C 2 --glob '*.conf'

Integration with fzf and editor:

# Search and open in editor at the match line rg "TODO" | fzf | cut -d: -f1,2 | xargs -I {} nvim +{} {}

File Viewing & Processing

bat (Syntax-Highlighted cat)

Repository: https://github.com/sharkdp/bat
What it is: A cat clone with syntax highlighting and line numbers

bat is cat with superpowers. It automatically detects file types and applies syntax highlighting, shows line numbers, indicates git changes, and integrates perfectly with fzf for previewing.

Installation:

brew install bat alias cat="bat" # In ~/.zshrc

What I get out of it:

  • Syntax highlighting for 100+ languages
  • Line numbers by default
  • Git diff indicators
  • Beautiful output that's actually readable
  • Perfect for use with fzf --preview
  • Drop-in replacement for cat

Practical usage:

# View a file with syntax highlighting bat src/index.ts # Show non-printable characters bat -A file.txt # Force a specific language (useful for unknown extensions) bat --language json config # Show only specific line numbers bat --line-range 10:20 file.ts # Theme customization (list themes) bat --list-themes # Use specific theme bat --theme="Dracula" file.ts

Integration with fzf:

# In ~/.zshrc preview() { fzf --preview 'bat --color=always {}' } fd -t f | preview # Browse files with syntax highlighting

mdcat (Markdown Viewer)

Repository: https://github.com/lunaryorn/mdcat
What it is: A cat clone specialized for Markdown files

mdcat renders Markdown in your terminal with proper formatting — headers look like headers, bold is bold, code blocks are highlighted, links are styled. Reading a README directly in the terminal without the noise of raw Markdown is a much better experience.

Installation:

brew install mdcat

What I get out of it:

  • Renders headers, emphasis, and lists properly
  • Syntax highlights code blocks
  • Shows links in a readable format
  • Perfect for reading documentation quickly
  • Much cleaner than viewing raw Markdown

Practical usage:

# View README with proper formatting mdcat README.md # Page through long documentation mdcat CHANGELOG.md | less # View documentation directly from projects mdcat /path/to/project/docs/setup.md

jq (JSON Processor)

Repository: https://github.com/stedolan/jq
What it is: A lightweight, flexible command-line JSON processor

jq is indispensable for working with JSON data. It parses, filters, transforms, and formats JSON with a powerful query language. If you work with APIs, config files, or any JSON data, jq becomes second nature.

Installation:

brew install jq

What I get out of it:

  • Powerful query language for JSON manipulation
  • Pretty-prints by default
  • Filters, maps, and transforms data elegantly
  • Perfect for exploring API responses
  • Chain operations for complex transformations

Practical usage:

# Pretty-print JSON curl https://api.example.com/data | jq '.' # Extract a specific field cat data.json | jq '.user.name' # Extract array of objects cat data.json | jq '.users[] | .email' # Filter with conditions cat data.json | jq '.items[] | select(.status == "active")' # Map over arrays cat data.json | jq '.users | map(.name)' # Group and count cat data.json | jq 'group_by(.category) | map({category: .[0].category, count: length})' # Transform structure cat data.json | jq '{names: [.users[].name], count: (.users | length)}' # Output raw strings (no quotes) cat data.json | jq -r '.url' # Iterate with keys cat data.json | jq '.dependencies | keys[]'
# Check API response structure curl https://api.github.com/users/torvalds | jq 'keys' # Extract specific fields from GitHub API curl https://api.github.com/repos/torvalds/linux | jq '{name, stars: .stargazers_count, forks: .forks_count, language}' # Parse and extract from config jq '.database.host, .database.port' config.json

ncdu (Disk Usage Tool)

Repository: https://dev.yorhel.nl/ncdu
What it is: An interactive disk usage analyzer

ncdu shows you what's consuming disk space with an interactive terminal UI. Far more useful than du -sh * — you navigate it like a file explorer, drilling into directories to find the culprits.

Installation:

brew install ncdu

What I get out of it:

  • Interactive navigation of disk usage
  • Shows which directories are the biggest
  • Can delete files directly from the interface
  • Fast and responsive
  • Instantly identify storage hogs

Practical usage:

# Analyze home directory ncdu ~ # Full system analysis ncdu / # Exclude certain directories ncdu --exclude=/.cache --exclude=/.local # Analyze and export results ncdu -o results.txt / # Interface commands: # Arrow keys: Navigate # Enter: Enter/exit directories # d: Delete files # q: Quit # ?:Help

Git Workflow

lazygit (Terminal UI for Git)

Repository: https://github.com/jesseduffield/lazygit
What it is: A simple terminal UI for git commands

Git's command-line interface is powerful but unintuitive for complex operations. Interactive rebasing, staging hunks, cherry-picking — these are painful in vanilla git. lazygit is a full terminal UI that makes these operations visual and fast.

Installation:

brew install lazygit alias lg="lazygit" # In ~/.zshrc

What I get out of it:

  • Visual staging and unstaging at hunk level
  • Interactive rebasing made intuitive
  • Merge conflict resolution with editor integration
  • Branch visualization and navigation
  • Extremely responsive and keyboard-driven
  • No graphical UI clutter — pure terminal

Key bindings (essential operations):

lazygit # Launch the TUI # Inside lazygit: space # Stage/unstage file or hunk c # Commit p # Push P # Pull m # Merge r # Rebase d # Discard changes e # Edit in external editor (for conflicts) S # Stash changes g # Reset to commit n # Create new branch o # Check out branch
# Instead of: git add -p # Interactive add git commit -m "message" git rebase -i HEAD~3 # Interactive rebase git merge branch-name git stash # Just use: lg # Navigate with arrow keys, press space, commit, done.

Where it really shines:

  • Visual staging: See exactly what you're staging with diff preview
  • Hunk staging: Stage individual lines, not just files
  • Rebase visualization: See the entire rebase tree
  • Merge conflicts: Resolve with your editor, see the result live
  • Branch switching: Visual branch list, search, switch instantly

System Monitoring

btop (Beautiful Resource Monitor)

Repository: https://github.com/aristocratos/btop
What it is: A resource monitor showing CPU, memory, disk, network, and process usage

btop is a modern replacement for top and htop. It displays all system resources in a clean terminal interface with real-time graphs and easy navigation.

Installation:

brew install btop

What I get out of it:

  • Gorgeous, real-time graphs
  • Shows all system resources at a glance
  • Keyboard-driven process management
  • Full customization via configuration
  • More intuitive than traditional system monitors

Usage:

btop # Launch the monitor # Inside btop: # Use arrow keys to navigate # F2: Settings # q: Quit # K: Kill process # E: Tree # R: Reverse sort # Shift + M: Sort by memory usage # Shift + C: Sort by CPU usage

Key features:

  • CPU: Per-core usage visualization
  • Memory: Detailed memory and swap usage
  • Disk: Read/write speed and usage
  • Network: Upload/download speeds and totals
  • Processes: Sortable by CPU, memory, or I/O

Media Processing

ffmpeg (Multimedia Swiss Army Knife)

Repository: https://github.com/FFmpeg/FFmpeg
What it is: A comprehensive multimedia framework for audio and video

ffmpeg is the universal tool for audio and video processing. Converting formats, trimming clips, extracting audio, compressing video, recording screen — if it involves multimedia, ffmpeg can do it.

Installation:

brew install ffmpeg

What I get out of it:

  • Supports virtually every audio/video format
  • Powerful encoding and compression options
  • Incredibly flexible and scriptable
  • Used by every major video tool (YouTube, VLC, etc.)
  • Free and open source

Practical usage:

# Convert .mov to compressed .mp4 ffmpeg -i input.mov -c:v libx264 -crf 23 output.mp4 # Extract audio from video ffmpeg -i video.mp4 -vn -acodec copy audio.aac # Cut a clip (10 seconds starting at 30 seconds) ffmpeg -i input.mp4 -ss 00:00:30 -t 00:00:10 clip.mp4 # Extract one frame per second as images ffmpeg -i video.mp4 -vf fps=1 frames/%03d.jpg # Create video from images ffmpeg -framerate 30 -i frame_%03d.jpg output.mp4 # Compress video (reduce file size) ffmpeg -i input.mp4 -c:v libx265 -crf 28 compressed.mp4 # Convert audio format ffmpeg -i input.mp3 -ab 192k output.aac # Add subtitle to video ffmpeg -i movie.mp4 -i subtitles.srt output.mp4 # Resize video ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4 # Batch convert multiple files for file in *.mov; do ffmpeg -i "$file" -c:v libx264 "${file%.mov}.mp4"; done

Pro tips:

  • -crf (constant rate factor): 0-51 for quality (lower = better, 18-28 is typical)
  • -c:v specifies video codec (libx264, libx265, etc.)
  • -c:a specifies audio codec (aac, mp3, etc.)
  • Use -y to automatically overwrite output files

yt-dlp (Video Downloader)

Repository: https://github.com/yt-dlp/yt-dlp
What it is: Download videos from YouTube and hundreds of other sites

yt-dlp is an actively maintained fork of youtube-dl, supporting downloads from virtually any video platform. You can specify quality, extract audio only, batch-download playlists, and customize output naming.

Installation:

brew install yt-dlp

What I get out of it:

  • Supports 1000+ websites
  • Download any quality level
  • Extract audio to MP3, M4A, or other formats
  • Batch operations on playlists
  • Flexible output naming
  • Keeps up with site changes

Practical usage:

# Download best quality (video + audio merged) yt-dlp "https://www.youtube.com/watch?v=..." # Download specific quality yt-dlp -f "bestvideo+bestaudio" URL # Extract audio as MP3 yt-dlp -x --audio-format mp3 URL # Download entire playlist yt-dlp -f bestvideo "https://www.youtube.com/playlist?list=..." # List available formats before downloading yt-dlp --list-formats URL # Custom output filename yt-dlp -o "%(title)s-%(id)s.%(ext)s" URL # Batch download with custom naming yt-dlp -o "%(uploader)s/%(title)s.%(ext)s" URL1 URL2 URL3 # Download subtitles yt-dlp --write-subs --sub-lang en URL # Download audio + subtitles yt-dlp -x --write-subs URL

mpv (Terminal Video Player)

Repository: https://github.com/mpv-player/mpv
What it is: A minimalist, scriptable video player for the command line

mpv is my go-to video player, especially on Linux. It plays virtually any format, has excellent hardware acceleration, and is entirely keyboard-controlled.

Installation:

brew install mpv # macOS sudo apt install mpv # Ubuntu/Debian

What I get out of it:

  • Plays everything (codec support is excellent)
  • Fast startup time
  • Minimal interface, keyboard-driven
  • Configurable and scriptable
  • Perfect for piping streams

Practical usage:

# Play a local file mpv video.mp4 # Stream from URL mpv "https://example.com/video.mp4" # Play with custom options mpv --fullscreen --loop=inf video.mp4 # Stream from yt-dlp directly yt-dlp -o - "https://youtube.com/watch?v=..." | mpv - # Keyboard controls: # space: Play/pause # arrows: Seek # f: Fullscreen # esc: Exit fullscreen # q: Quit # : Open command palette

Window Management (macOS)

yabai (Tiling Window Manager)

Repository: https://github.com/koekeishiya/yabai
What it is: A tiling window manager for macOS

yabai brings tiling window management to macOS. If you've used i3 or sway on Linux, you know the power: windows automatically fill space without overlapping, navigation is entirely keyboard-driven, and you can build an incredibly efficient workflow.

Installation:

brew install koekeishiya/formulae/yabai yabai --start-service

What I get out of it:

  • No more manual window arrangement
  • Keyboard-driven navigation
  • Automatic space management
  • Highly customizable
  • Never touch the mouse for window management again

Essential commands:

# Focus windows yabai -m window --focus west yabai -m window --focus east yabai -m window --focus north yabai -m window --focus south # Move windows yabai -m window --swap west yabai -m window --move rel:20:0 # Resize windows yabai -m window --resize right:20:0 # Toggle float yabai -m window --toggle float # Toggle fullscreen yabai -m window --toggle zoom-fullscreen # Layout management yabai -m space --layout bsp # Binary space partitioning yabai -m space --layout float # Floating layout

Here's the config I use currently for yabai:

#!/usr/bin/env sh yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa" # bar settings yabai -m config status_bar off yabai -m config status_bar_text_font "Helvetica Neue:Bold:12.0" yabai -m config status_bar_icon_font "FontAwesome:Regular:12.0" yabai -m config status_bar_background_color 0xff202020 yabai -m config status_bar_foreground_color 0xffa8a8a8 yabai -m config status_bar_space_icon_strip I II III IV V VI VII VIII IX X yabai -m config status_bar_power_icon_strip yabai -m config status_bar_space_icon yabai -m config status_bar_clock_icon # yabai -m config window_animation_duration 1.0 # global settings yabai -m config window_placement second_child yabai -m config window_opacity off yabai -m config window_opacity_duration 0.0 yabai -m config window_shadow float yabai -m config window_border off yabai -m config window_border_placement inset yabai -m config window_border_width 4 yabai -m config window_border_radius -1.0 yabai -m config active_window_border_topmost off yabai -m config active_window_border_color 0xff775759 yabai -m config normal_window_border_color 0xff505050 yabai -m config insert_window_border_color 0xffd75f5f yabai -m config active_window_opacity 1.0 yabai -m config normal_window_opacity 1.0 yabai -m config split_ratio 0.50 yabai -m config auto_balance off yabai -m config focus_follows_mouse autoraise yabai -m config mouse_follows_focus off yabai -m config mouse_modifier ctrl yabai -m config mouse_action1 move yabai -m config mouse_action2 resize yabai -m config window_topmost off # general space settings yabai -m config layout bsp yabai -m config top_padding 41 yabai -m config bottom_padding 20 yabai -m config left_padding 20 yabai -m config right_padding 20 yabai -m config window_gap 20 # Float Windows yabai -m rule --add app="^Finder$" manage=off yabai -m rule --add app="^System Preferences$" manage=off yabai -m rule --add app="^The\ Unarchiver$" manage=off yabai -m rule --add app="^System\ Preferences$" manage=off yabai -m rule --add app="^1Password\ 7$" manage=off yabai -m rule --add app="^1Password 7$" manage=off yabai -m rule --add app="^Raycast$" manage=off yabai -m rule --add app="^Raycast Settings$" manage=off yabai -m rule --add app="^1Password$" manage=off yabai -m rule --add app="^1Password$" manage=off yabai -m rule --add app="^Bitwarden$" manage=off yabai -m rule --add app="Bitwarden" manage=off yabai -m rule --add app="^Surfshark$" manage=off yabai -m rule --add app="^Calculator$" manage=off yabai -m rule --add app="NepTunes" manage=off yabai -m rule --add app="Firefox Developer Edition" title="^Opening .*$" manage=off yabai -m rule --add app="Firefox Developer Edition" title="^Extension: (Metamask) - Metamask Notification$" manage=off yabai -m rule --add app="Firefox Developer Edition" title="^Extension Notification$" manage=off yabai -m rule --add app="Firefox Developer Edition" title="^Extension$" manage=off yabai -m rule --add app="Firefox Developer Edition" title="Extension: (Metamask) - Metamask Notification" manage=off yabai -m rule --add app="Firefox Developer Edition" title="^Extension$" manage=off yabai -m rule --add app="Firefox Developer Edition" title="^MetaMask$" manage=off yabai -m rule --add app="Firefox Developer Edition" title="^Extension$" manage=off yabai -m rule --add app="Firefox Developer Edition" title="^Library$" manage=off yabai -m rule --add app="ImageOptim" manage=off yabai -m rule --add app="VirtualBox" manage=off yabai -m rule --add app="iPhone Mirroring" manage=off yabai -m rule --add app="VirtualBox VM" manage=off yabai -m rule --add app="Windows10" manage=off yabai -m rule --add app="Windows10 [Running]" manage=off yabai -m rule --add app="Stats" manage=off yabai -m rule --add app="^Finder$" title="(Co(py|nnect)|Move|Info|Pref)" manage=off yabai -m rule --add app="^System Preferences$" title=".*" manage=off yabai -m rule --add app="^Calculator$" manage=off yabai -m rule --add app="Software Update" manage=off yabai -m rule --add app="System Information" manage=off yabai -m rule --add app="^Dictionary$" manage=off yabai -m rule --add app="^IINA$" manage=off yabai -m rule --add app="^System Settings$" manage=off yabai -m rule --add app="^Picture in Picture$" manage=off yabai -m signal --add event=space_changed action="sketchybar --trigger space_change" echo "yabai configuration loaded.."

skhd (Hotkey Daemon)

Repository: https://github.com/koekeishiya/skhd
What it is: A simple hotkey daemon for macOS with live config reloading

skhd lets you define keyboard shortcuts in a plain text config file. Hotkeys can be edited and reloaded live while skhd is running — no restart required.

Installation:

brew install koekeishiya/formulae/skhd skhd --start-service

The config I use (~/.skhdrc):

# Navigation #alt - h : yabai -m window --focus west #alt - j : yabai -m window --focus south #alt - k : yabai -m window --focus north #alt - l : yabai -m window --focus east # Moving windows #shift + alt - h : yabai -m window --warp west #shift + alt - j : yabai -m window --warp south€ #shift + alt - k : yabai -m window --warp north #shift + alt - l : yabai -m window --warp east # Focus Recent Window # alt - tab : yabai -m space --focus next # alt + shift - tab : yabai -m space --focus prev # cmd - tab : yabai -m window --focus next # cmd + tab : yabai -m window --focus next # cmd - shift - tab : yabai -m window --focus last # cmd - shift + tab : yabai -m window --focus last cmd + shift - tab : yabai -m window --focus last # Equalize size of windows alt - e : yabai -m space --balance # alt + e : yabai -m space --balance # Toggle Split alt - w : yabai -m window --toggle split # Rotate windows clockwise and anticlockwise alt - r : yabai -m space --rotate 270 shift + alt - r : yabai -m space --rotate 90 # Toggle Audio Source alt - 1 : SwitchAudioSource -n | terminal-notifier -title $(SwitchAudioSource -c) | afplay /System/Library/Sounds/Blow.aiff # send window to a space shift + alt - 1 : yabai -m window --space 1 shift + alt - 2 : yabai -m window --space 2 shift + alt - 3 : yabai -m window --space 3 shift + alt - 4 : yabai -m window --space 4 shift + alt - 5 : yabai -m window --space 5 shift + alt - 6 : yabai -m window --space 6 # Restart Yabai shift + lctrl + alt - r : yabai --restart-service shift + lctrl + cmd - r : skhd --restart-service # Sleep Computer # lctrl - f15 : afplay /System/Library/Sounds/Ping.aiff && pmset displaysleepnow

Text Editors

neovim (Modern Vim)

Repository: https://neovim.io
What it is: A fork of Vim focused on extensibility and usability

neovim is Vim reimagined for the modern era. With a Lua-based configuration system, built-in LSP support, and an active plugin ecosystem, it becomes an IDE-level editor that starts in milliseconds.

Installation:

brew install neovim

What I get out of it:

  • IDE features (LSP, completion, diagnostics)
  • Starts instantly (~10ms)
  • Powerful Lua configuration
  • Exceptional plugin ecosystem
  • Works everywhere (local, SSH, containers)
  • True modal editing once muscle memory develops

Essential keybindings:

# Navigation h/j/k/l # Left/down/up/right w/b # Next/previous word ^/$ or 0/$ # Start/end of line gg/G # Start/end of file # Editing i/a # Insert before/after cursor o/O # New line below/above dd # Delete line yy # Yank (copy) line p/P # Paste after/before cursor ciw # Change inner word # Navigation in normal mode /pattern # Search forward ?pattern # Search backward n/N # Next/previous match

Modern Neovim setup:

# Use a package manager like lazy.nvim # Install plugins: telescope, nvim-lspconfig, nvim-cmp, nvim-treesitter # Configure LSP for your languages # You get: # - Fuzzy file finding # - Go to definition # - Code completion # - Diagnostics # - Syntax highlighting

AI-Powered Tools

Claude Code

Repository: https://claude.com/product/claude-code
What it is: AI-powered development tool for your terminal, IDE, and web

Claude Code lets you work with Claude directly in your codebase. Describe what you need, and Claude handles the coding, testing, debugging, and iteration.

Installation:

brew install claude-code # or npm install -g @anthropic-ai/claude-code

Why it transforms development:

  • Understand unfamiliar codebases instantly
  • Write boilerplate and scaffolding in seconds
  • Fix bugs with context from your entire project
  • Refactor code safely
  • Generate tests automatically
  • Debug complex issues with AI reasoning

Wrote a detailed guide here: /journal/coding-with-claude


Conclusion

Every tool on this list earned its place. None of them are here because they're trendy — they're here because I reach for them constantly and would notice immediately if they were gone.

The investment framing matters: spending an hour learning ripgrep or fd pays off every single day. fzf feels like overhead until it doesn't, and then you can't imagine working without it. Start with one tool, build the muscle memory, then add another. The compounding effect is real.


Links

Shell & Environment

  • Homebrew
  • Oh My Zsh — GitHub
  • nvm
  • mackup
  • chezmoi
  • rcm
  • homesick
  • stow

Navigation & Discovery

  • eza
  • z

Search & Find

  • fd
  • fzf
  • fzf-tab-completion
  • ripgrep

File Viewing & Processing

  • bat
  • mdcat
  • jq
  • ncdu

Git Workflow

  • lazygit

System Monitoring

  • btop

Media Processing

  • ffmpeg
  • yt-dlp
  • mpv

Window Management

  • yabai
  • skhd

Text Editors

  • Neovim

AI-Powered Tools

  • Claude Code
  • Coding with Claude — my guide
tags
SoftwareCLICommand LineCodingProgramming