After years of using the same old Unix utilities, I decided it was time to modernize my shell environment. The result? A terminal setup that feels like upgrading from a bicycle to a sports car. Every command is faster, every interaction is smoother, and I've reclaimed hours of my day that I used to spend fighting with outdated tools.
In this post, I'll walk you through the modern CLI tools that transformed my development workflow—from version management to file searching, from directory navigation to shell history. These aren't just shiny new toys; they're productivity multipliers that make working in the terminal a genuine pleasure.
mise: The Version Manager That Does Everything
Let's start with mise (formerly rtx), which sits at the foundation of this setup. Think of it as nvm, pyenv, rbenv, and asdf all rolled into one, but faster and more intuitive.
mise allows you to manage versions of tools and languages across projects without the version manager chaos. Instead of juggling multiple version managers, I define all my tool versions in a .mise.toml file (or via environment-specific configurations), and mise handles the rest. It's incredibly fast, written in Rust, and supports everything from Node.js to kubectl.
What makes mise special is its automatic tool installation and version resolution. When I cd into a project directory, mise automatically switches to the correct versions of Python, Node.js, or any other tool that project needs. No manual activation required—it just works. mise also supports project-specific tasks, letting you define common scripts in your .mise.toml that team members can run with mise run.
Zim Framework: The Fast Zsh Setup
While Oh My Zsh is great, Zim Framework offers similar functionality with significantly faster startup times. It's a minimal, modular framework for Zsh that loads only what you need, when you need it.
With Zim, I've configured essential plugins like:
- zsh-autosuggestions: Suggests commands as you type based on your history
- zsh-syntax-highlighting: Colors commands to show if they're valid before you press Enter
- zsh-history-substring-search: Navigate history by typing parts of previous commands
The framework itself is lightweight, but the real magic comes from pairing it with the tools below.
Directory Navigation with zoxide
Remember typing cd over and over again to navigate deep directory structures? zoxide eliminates that pain. It's a smarter cd command that learns your habits.
After using it for a while, z myproject might take you directly to ~/projects/github.com/username/myproject, even if you're currently several directories deep. It uses a "frecency" algorithm (frequency + recency) to rank directories, so the places you visit most often become easiest to reach.
The shell integration provides zi for interactive directory selection and keeps track of every directory you visit. It's one of those tools that becomes essential after just a few days of use.
File Searching: fd and ripgrep
When it comes to finding files and searching their contents, the standard find and grep utilities are showing their age. fd and ripgrep are their modern replacements, written in Rust for speed. Both can be installed via system package managers or through mise.
fd ignores .git directories by default, follows symlinks intelligently, and uses regex patterns naturally. A simple fd "\.yml$" finds all YAML files recursively, and fd config finds files or directories matching "config" without needing complex flags.
ripgrep (rg) searches file contents with similar intelligence. It respects .gitignore, automatically skips binary files, and is dramatically faster than grep -r on large codebases. The default output is also beautifully colored and easy to read.
File Viewing: bat and delta
Speaking of beautiful output, bat replaces cat with syntax highlighting, Git integration, and automatic paging. It shows line numbers, highlights code, and indicates changes in Git-controlled files.
Similarly, delta enhances git diff output with side-by-side views, syntax highlighting, and better merge conflict display. Configure it as git's default pager in your .gitconfig, and every git diff, git show, and git log -p benefits automatically. If you spend time reviewing code changes, delta makes the process significantly more pleasant.
Directory Listing: eza
eza is the community-maintained successor to exa (which is no longer actively developed), providing a modern replacement for ls. It shows Git status, file icons, and uses colors intelligently. With icons enabled, directory listings become instantly scannable.
I've configured aliases so that ls and ll use eza by default, which means the improved experience is always available. The --tree flag is particularly useful for getting a quick overview of a project's structure.
Fuzzy Finding: fzf
fzf is a fuzzy finder that integrates throughout the shell experience. Press Ctrl+R to search command history, Ctrl+T to find files, or Alt+C to change directories—all with fuzzy matching.
But fzf's real power comes from its integration with other tools. It can preview files (using bat for syntax highlighting), search through Git commits, or even create interactive menus for complex commands. Pair it with zoxide's zi command for interactive directory jumping with fuzzy search. Once you start using it, you'll wonder how you ever worked without it.
System Monitoring: btop and procs
For monitoring system resources, btop replaces top and htop with a beautiful, informative interface. It shows CPU, memory, network, and disk usage in an easy-to-read format.
procs is a more readable ps replacement. It colors output, shows process trees, and makes finding the process you're looking for much easier than parsing traditional ps output.
Disk Usage: dust
dust provides a better du experience by showing directory sizes in a tree format, sorted by size. Want to know what's eating your disk space? dust shows it visually, making it obvious where to start cleaning.
Prompt: starship
starship is a cross-shell prompt written in Rust that's fast and highly customizable. It shows Git branch status, Python virtual environment, Node.js version, and Kubernetes context—all automatically, based on your current directory.
The default configuration is beautiful, but starship's real strength is its customizability. I've configured it to show only relevant information, keeping the prompt clean while providing essential context when needed.
YAML Processing: yq
Working with YAML files? yq is like jq for YAML. It's indispensable when dealing with Kubernetes manifests, Docker Compose files, or CI/CD configurations. Query, modify, or extract data from YAML with powerful expressions.
Shell History: atuin
Traditional shell history is frustrating. You press Ctrl+R and hope you can remember the exact command you're looking for. atuin fixes this by providing SQLite-backed history with fuzzy search, statistics, and optional cloud sync.
With atuin, I can search my history by any part of a command, see when and where I ran it, and even sync history across multiple machines. The atuin search command is particularly powerful for finding that command I ran last week but can't quite remember.
The fuzzy search mode makes finding commands natural—just type what you remember, and atuin finds it. With optional encryption and sync, your command history becomes a searchable knowledge base of your work.
Development Languages and Package Managers
Via mise, I manage multiple language runtimes:
- Node.js 22 (LTS) with pnpm for fast, disk-efficient package management
- Python 3.12 for modern Python development
- Java 25 with Maven for JVM-based projects
- Go (latest) for systems programming
- Rust (latest) for performance-critical tools
Having all these available without version conflicts is a game-changer. Each project can specify its required versions, and mise handles the isolation automatically.
DevOps Tools
The setup includes a comprehensive set of Kubernetes and infrastructure tools, all managed via mise:
- kubectl for cluster interaction
- helm for package management
- k9s for interactive cluster exploration
- kubectx/kubens for context and namespace switching
- stern for multi-pod log tailing
- istioctl for Istio service mesh management
- argo for ArgoCD GitOps operations
-
opentofu (via
tofucommand) as an open-source Terraform alternative - vault for secrets management
- kafkactl for Kafka cluster interaction
- mc (MinIO Client) for object storage
All of these tools integrate with shell completion, making their complex CLIs more discoverable and less error-prone.
AWS Tools
For cloud operations, I use:
- aws-cli (latest) for comprehensive AWS interaction
- aws-vault for secure credential management with MFA support
aws-vault is particularly useful for managing multiple AWS accounts and profiles securely. It stores credentials encrypted and supports role assumption and MFA seamlessly.
Aliases: Shortcuts for Common Tasks
A well-configured set of aliases saves countless keystrokes. Here are some categories I've found useful:
Modern Tool Aliases: The traditional cat, ls, find, grep commands are aliased to their modern replacements (bat, eza, fd, rg), so the improvements are always available.
Git Shortcuts: gst for status, gcm for commit, gp for push. These become muscle memory quickly.
Kubernetes Quick Access: kx for context switching (kubectx), kns for namespace switching (kubens), ke to edit the kubeconfig file.
Package Manager Shorthands: p for pnpm, pi for pnpm install, pr for pnpm run. For Maven, m instead of mvn.
AWS Operations: awswho shows current identity, awsls lists profiles, awsl logs into SSO. For aws-vault, av, avl, ave provide quick access to common operations.
Directory Navigation: .., ..., .... for going up one, two, or three directory levels quickly.
Safety Aliases: rm, cp, and mv are aliased with -i flags to prevent accidental overwrites.
These aliases work together with the modern tools to create a fluent command-line experience. The combination means less typing, fewer mistakes, and faster workflows.
Additional Configuration
A few environment variables enhance the experience:
-
BAT_THEMEsets the syntax highlighting theme for bat -
FZF_DEFAULT_COMMANDusesfdfor fzf's file search, respecting.gitignoreautomatically -
FZF_DEFAULT_OPTSconfigures fzf's appearance and preview behavior - Shell completions are enabled for most tools, providing tab completion for complex CLIs
The Result
After setting up these tools, working in the terminal feels fundamentally different. Commands are faster, output is clearer, and navigation is intuitive. What used to require remembering complex find expressions or scrolling through thousands of history entries now happens with a few keystrokes or natural language searches.
The investment in learning these tools pays off quickly. Most have excellent documentation and sensible defaults, so you can start benefiting immediately while gradually discovering advanced features.
If you're still using the default Unix utilities from the 1970s, consider giving some of these modern alternatives a try. Your future self will thank you for the time saved and the improved terminal experience.
Want to see these tools in action? Check out the project repositories linked throughout this post. Each tool has excellent documentation and active communities for support.
Top comments (0)