Terminal Optimization: A 2026 Refresh
After years of accumulating cruft in my terminal configuration, I finally did a complete audit and optimization. Here’s what I found and fixed.
The Problems
A quick audit of my .zshrc revealed several issues:
1. Exposed API Keys (Critical!)
# DON'T DO THIS - keys visible to anyone with file access
export GEMINI_API_KEY="sk-..."
export GOOGLE_API_KEY="sk-..."API keys sitting in plaintext in a dotfile that might get committed to a dotfiles repo or shared. Not good.
2. Dead Code from Deprecated Tools
# Fig was sunset in 2023 - these do nothing
[[ -f "$HOME/.fig/shell/zshrc.pre.zsh" ]] && source "$HOME/.fig/shell/zshrc.pre.zsh"Fig (now Amazon Q) was deprecated, but these references were still cluttering the config.
3. Redundant Conda Initialization
I had conda init blocks in both .zshrc (for mambaforge) and .bash_profile (for miniconda3). Since switching to uv for Python environment management, neither was needed.
4. Missing Tool Integrations
I had installed modern CLI tools but never configured them: - fzf - installed but not integrated - zoxide - installed but not activated - bat, fd, eza - not aliased
5. Slow Prompt
The agnoster theme in oh-my-zsh, while pretty, adds noticeable startup latency.
The Solutions
Secure API Key Management
Created a separate secrets file with restricted permissions:
# ~/.zsh_secrets (chmod 600)
export GEMINI_API_KEY="your-key-here"
export GOOGLE_API_KEY="your-key-here"Then in .zshrc:
[ -f ~/.zsh_secrets ] && source ~/.zsh_secretsThe secrets file should be: - Added to .gitignore_global - Set to mode 600 (owner read/write only) - Never committed to version control
Starship Prompt
Replaced oh-my-zsh’s agnoster theme with Starship:
brew install starshipIn .zshrc:
ZSH_THEME="" # Disable oh-my-zsh theme
eval "$(starship init zsh)"Starship is: - Written in Rust (fast) - Cross-shell compatible - Highly configurable - Shows only what’s relevant
My ~/.config/starship.toml:
add_newline = false
command_timeout = 1000
format = """
$directory\
$git_branch\
$git_status\
$python\
$cmd_duration\
$line_break\
$character"""
[character]
success_symbol = "[❯](bold green)"
error_symbol = "[❯](bold red)"
[directory]
truncation_length = 3
truncate_to_repo = true
[git_status]
ahead = "⇡${count}"
behind = "⇣${count}"
staged = "+${count}"
modified = "!${count}"Modern CLI Tool Aliases
Replaced legacy commands with modern alternatives:
# In ~/.zshrc
# Modern ls with icons and git status
alias ls='eza --icons'
alias ll='eza -la --icons --git'
alias lt='eza --tree --level=2 --icons'
# Better cat with syntax highlighting
alias cat='bat --paging=never'Tools installed: - eza - modern ls replacement with git integration - bat - cat with syntax highlighting - fd - faster, friendlier find - ripgrep - faster grep - zoxide - smarter cd
Before vs After: Real Examples
Let’s see these tools in action on a sample Python ML project:
dummy-project/
├── config.yaml
├── data/
│ └── readings.csv
├── docs/
├── README.md
├── src/
│ ├── model.py
│ └── train.py (modified)
└── tests/
└── test_model.py
ls → eza: Directory Listing
Before (/bin/ls -la):
total 16
drwxr-xr-x@ 9 nipun staff 288 4 Jan 06:54 .
drwxr-xr-x@ 3 nipun staff 96 4 Jan 06:54 ..
drwxr-xr-x@ 12 nipun staff 384 4 Jan 07:01 .git
-rw-r--r--@ 1 nipun staff 104 4 Jan 06:54 config.yaml
drwxr-xr-x@ 3 nipun staff 96 4 Jan 06:54 data
drwxr-xr-x@ 2 nipun staff 64 4 Jan 06:54 docs
-rw-r--r--@ 1 nipun staff 235 4 Jan 06:54 README.md
drwxr-xr-x@ 4 nipun staff 128 4 Jan 06:54 src
drwxr-xr-x@ 3 nipun staff 96 4 Jan 06:54 tests
After (eza -la --git):
drwxr-xr-x@ - nipun 4 Jan 07:01 -I .git
.rw-r--r--@ 104 nipun 4 Jan 06:54 -- config.yaml
drwxr-xr-x@ - nipun 4 Jan 06:54 -- data
drwxr-xr-x@ - nipun 4 Jan 06:54 -- docs
.rw-r--r--@ 235 nipun 4 Jan 06:54 -- README.md
drwxr-xr-x@ - nipun 4 Jan 06:54 -M src ← Modified!
drwxr-xr-x@ - nipun 4 Jan 06:54 -- tests
Notice the -M flag showing the src/ directory contains modified files. Git status at a glance!
ls -R → eza --tree: Tree View
Before (/bin/ls -laR): Nested, hard to read output spanning many lines.
After (eza --tree --git-ignore):
dummy-project/
├── config.yaml
├── data
│ └── readings.csv
├── docs
├── README.md
├── src
│ ├── model.py
│ └── train.py
└── tests
└── test_model.py
Clean, visual hierarchy. Automatically ignores .git/ and other gitignored files.
cat → bat: Syntax Highlighting
Before (/bin/cat src/model.py):
"""Neural network model for energy prediction."""
import torch
import torch.nn as nn
class EnergyPredictor(nn.Module):
def __init__(self, input_dim=10, hidden_dim=64):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(hidden_dim, 1)
)
def forward(self, x):
return self.layers(x)
After (bat src/model.py): Same content but with: - Syntax highlighting (keywords, strings, classes colored) - Line numbers - Git integration (shows modified lines) - Automatic paging for long files
find → fd: Finding Files
Before (find . -name "*.py" -not -path "./.git/*"):
./tests/test_model.py
./src/model.py
./src/train.py
After (fd -e py):
src/model.py
src/train.py
tests/test_model.py
fd is: - ~5x faster on large codebases - Ignores .git/, node_modules/, etc. by default - Cleaner output (no ./ prefix) - Colored output in terminal
grep → rg: Searching Content
Before (grep -r "torch" . --include="*.py"):
./tests/test_model.py:import torch
./tests/test_model.py: x = torch.randn(8, 10)
./src/model.py:import torch
./src/model.py:import torch.nn as nn
./src/train.py:import torch
./src/train.py: optimizer = torch.optim.Adam(model.parameters(), lr=lr)
After (rg "torch"):
README.md:pip install torch pandas numpy
tests/test_model.py:import torch
tests/test_model.py: x = torch.randn(8, 10)
src/train.py:import torch
src/train.py: optimizer = torch.optim.Adam(model.parameters(), lr=lr)
src/model.py:import torch
src/model.py:import torch.nn as nn
ripgrep is: - ~10x faster than grep - Respects .gitignore automatically - Searches all file types by default (found the README match!) - Smart case sensitivity
fzf Integration
Finally configured fzf properly:
# Install shell integration
$(brew --prefix)/opt/fzf/install
# Configure in .zshrc
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git'Key bindings: - Ctrl+T - fuzzy find files - Ctrl+R - fuzzy search command history - Alt+C - fuzzy cd to directory
Ghostty Configuration
Updated my Ghostty terminal emulator config:
# ~/.config/ghostty/config
# Font
font-family = "JetBrains Mono"
font-size = 16
font-thicken = true
# Appearance
theme = GruvboxDark
background-opacity = 0.95
window-padding-x = 10
window-padding-y = 10
macos-titlebar-style = tabs
# Performance
scrollback-limit = 50000
cursor-style-blink = false
# Keybindings
keybind = super+k=clear_screen
keybind = super+shift+enter=new_split:right
keybind = super+alt+enter=new_split:down
# Shell integration
shell-integration = zsh
shell-integration-features = cursor,sudo,titleThe Final .zshrc
Here’s the cleaned up configuration (~85 lines vs ~160 before):
# Oh My Zsh
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME=""
DISABLE_UNTRACKED_FILES_DIRTY="true"
plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
source $ZSH/oh-my-zsh.sh
# Starship prompt
eval "$(starship init zsh)"
# PATH (consolidated, with duplicate removal)
typeset -U PATH
export PATH="$HOME/.local/bin:$PATH"
export PATH="$HOME/.local/share/uv/python/shims:$PATH"
export PATH="/opt/homebrew/opt/ruby/bin:$PATH"
export PATH="$HOME/Library/TinyTeX/bin/universal-darwin:$PATH"
# Tool integrations
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
eval "$(zoxide init zsh)"
# Aliases
alias ls='eza --icons'
alias ll='eza -la --icons --git'
alias cat='bat --paging=never'
# uv environment
[ -f ~/.uv/base/bin/activate ] && source ~/.uv/base/bin/activate
# Secrets (API keys)
[ -f ~/.zsh_secrets ] && source ~/.zsh_secretsResults
| Metric | Before | After |
|---|---|---|
| Lines in .zshrc | ~160 | ~85 |
| Shell startup time | ~800ms | ~300ms |
| Exposed secrets | 3 | 0 |
| Dead code blocks | 4 | 0 |
| Modern tools integrated | 0 | 6 |
TL;DR Checklist
If you want to optimize your terminal:
- Security audit: Move all API keys to
~/.zsh_secretswithchmod 600 - Remove dead code: Delete Fig, old conda init, unused PATH entries
- Install modern tools:
brew install starship eza bat fd ripgrep zoxide fzf - Configure integrations: fzf keybindings, zoxide init, starship prompt
- Add useful aliases: Replace
lswitheza,catwithbat - Clean PATH: Use
typeset -U PATHto deduplicate - Update terminal emulator: Ghostty has great defaults, just needs minor config
Happy terminal-ing!