# Every Tool in My Terminal-First Dev Setup

> Neovim, Wezterm, Tmux, and the rest — what survived two years of daily use and why I picked each one over the obvious alternatives.

- Author: Aayush Bharti
- Published: 2025-10-19
- Updated: 2026-10-04
- Reading time: 12 min
- Tags: developer-tools, terminal, neovim, workflow
- URL: https://aayushbharti.in/blog/terminal-first-dev-setup

---
I switched to a terminal-first workflow two years ago and never looked back. The trigger was embarrassingly mundane: VS Code hit 2.4GB of RAM during a Next.js debugging session while I had Chrome DevTools open, and my laptop froze for thirty seconds mid-demo. That same week, I watched a coworker navigate a monorepo in Neovim faster than I could open the file picker in VS Code.

I felt slow. Not "I should optimize this" slow — "I'm fighting my own tools" slow. So I committed to replacing every GUI developer tool with a terminal-native equivalent and gave myself three months to get productive. Everything in this list survived a regular purge — if a tool doesn't make me measurably faster, it doesn't make the cut. Here's what stayed.

## The core four: editor, terminal, shell, multiplexer

These are load-bearing walls. Swap out anything else and the system still works. Remove one of these and the whole workflow collapses.

### Neovim

[Neovim](https://github.com/neovim/neovim) is the center of gravity. I moved from VS Code because I was tired of Electron eating memory and the constant extension update churn breaking my setup every few weeks. With native LSP support and Treesitter for syntax highlighting, I get the same intelligence features — autocomplete, go-to-definition, inline diagnostics — but startup takes 40ms instead of four seconds.

The real unlock was modal editing. Once you internalize that `ciw` replaces a word and `dd` deletes a line without reaching for the mouse, you stop thinking about text manipulation and start thinking about code. I use [lazy.nvim](https://github.com/folke/lazy.nvim) for plugin management with about 35 plugins — telescope for fuzzy finding, nvim-cmp for completion, and conform.nvim for formatting on save.

The honest limitation: the learning curve is brutal for the first two weeks. You will be slower. You will want to quit. That investment in [learning your tools deeply](/blog/what-i-wish-i-knew-before-learning-to-code) pays compound interest, but nobody tells you how bad week one feels.

### Wezterm

[Wezterm](https://github.com/wez/wezterm) is a GPU-accelerated terminal emulator configured entirely in Lua. I tried Kitty first — solid performance, terrible config syntax. Alacritty flickered on Wayland and had no tab support. Wezterm nails both. The killer feature is scriptable keybindings: I have a Lua function that opens a new tab, `cd`s into a project directory, and attaches the matching Tmux session in one keystroke. The config is a real programming language, not YAML or TOML, so conditionals and loops work naturally.

```lua title="~/.config/wezterm/wezterm.lua"
local wezterm = require("wezterm")
local config = wezterm.config_builder()

config.font = wezterm.font("JetBrains Mono", { weight = "Medium" })
config.font_size = 13.5
config.window_background_opacity = 0.95
config.hide_tab_bar_if_only_one_tab = true
config.window_padding = { left = 8, right = 8, top = 8, bottom = 8 }

-- quick project switcher: Ctrl+Shift+P opens FZF in a new tab
config.keys = {
  {
    key = "p",
    mods = "CTRL|SHIFT",
    action = wezterm.action.SpawnCommandInNewTab({
      args = { "bash", "-c", "cd $(find ~/Developer -maxdepth 2 -type d | fzf) && exec zsh" },
    }),
  },
}

return config
```

One annoyance: Wezterm's multiplexer mode is half-baked compared to Tmux. I stopped trying to replace Tmux with it and let each tool do what it's best at.

### ZSH + Oh My Zsh

[ZSH](https://github.com/ohmyzsh/ohmyzsh) with Oh My Zsh is the shell layer. Bash's autocomplete is embarrassing in 2025 — no inline suggestions, no syntax highlighting as you type, no smart history search. ZSH's plugin ecosystem fixes all of that.

I run three plugins that matter: `zsh-autosuggestions` (ghost-text completion from your history), `zsh-syntax-highlighting` (red text when a command doesn't exist, green when it does), and `git` (aliases like `gco` for `git checkout`). The rest of Oh My Zsh I could take or leave. My `.zshrc` is 80 lines and loads in under 200ms — if yours takes longer, audit your plugins.

### Tmux

[Tmux](https://github.com/tmux/tmux) handles session persistence and workspace organization. When my SSH connection drops or I close my laptop mid-debug session, Tmux keeps every pane, every running process, every scroll position alive. I tried Zellij for the modern UX and floating panes, but it crashed twice during production incident debugging — the one time you absolutely need your multiplexer to be rock solid. Tmux is boring and that's the point.

I have three persistent sessions: `work`, `personal`, and `scratch`. Prefix key is rebound to `Ctrl+a` (closer to home row than the default `Ctrl+b`), and I use `tmux-resurrect` to survive full system reboots.

```bash title="~/.tmux.conf"
set -g prefix C-a
unbind C-b
bind C-a send-prefix

set -g mouse on
setw -g mode-keys vi
set -g base-index 1

# session persistence across reboots
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @continuum-restore 'on'
```

The only complaint is that Tmux's copy mode keybindings are arcane until you configure vi-mode — but once you do, selecting and yanking text feels like Neovim.

## Productivity and utilities

These sit between the core tools and fill the gaps. Each one replaced a slower workflow I didn't realize was slow until I timed it.

### FZF

[FZF](https://github.com/junegunn/fzf) is the single most impactful tool in this entire list. It's a general-purpose fuzzy finder that plugs into everything: `Ctrl+T` for file navigation, `Ctrl+R` for command history search, and inside Neovim via Telescope for project-wide file finding.

The speed difference is visceral — instead of `cd`-ing through four nested directories, I hit a keybind, type three characters, and I'm there. Once you muscle-memory fuzzy finding, navigating with `ls` and `cd` feels like using a flip phone after a smartphone.

FZF's `--preview` flag with bat gives me file previews inline, so I can confirm I'm opening the right file before committing to it. I set these as defaults so every FZF invocation gets previews for free:

```bash title="~/.zshrc"
export FZF_DEFAULT_OPTS="--height 40% --layout=reverse --border"
export FZF_CTRL_T_OPTS="--preview 'bat --color=always --line-range=:50 {}'"
export FZF_ALT_C_OPTS="--preview 'eza --tree --level=2 --icons {}'"
```

> FZF doesn't replace one tool. It replaces the *concept* of navigating to things manually. That mental shift is worth more than any individual config tweak.

### Lazygit

[Lazygit](https://github.com/jesseduffield/lazygit) is a TUI for Git that makes interactive rebasing, conflict resolution, and cherry-picks tolerable. The raw Git CLI is powerful but punishing for complex operations — staging individual hunks requires remembering `git add -p` flags, interactive rebase means editing a file in your `$EDITOR`, and merge conflicts are a wall of angle brackets.

Lazygit gives me a split view: staged changes on one side, diff on the other, keybinds for every operation. I do simple commits from the command line and reach for Lazygit the moment anything gets interactive. The staging interface alone saves me five minutes per session on days with heavy Git work.

### Bat and Btop++

[Bat](https://github.com/sharkdp/bat) replaces `cat` with syntax highlighting, line numbers, and git diff markers. I aliased `cat` to `bat` globally and forgot about it — inspecting a `package.json` or skimming a config file now gives me highlighted output for free. [Btop++](https://github.com/aristocratos/btop) replaced `htop` for process monitoring. The GPU monitoring panel saved me during Three.js debugging when I couldn't figure out why my discrete GPU wasn't activating. Spotted the issue in ten seconds with Btop's GPU utilization graph. Both tools are zero-config improvements to built-in commands.

### Better Commit

[Better Commit](https://github.com/Everduin94/better-commits) enforces conventional commits without me memorizing the format every time. I tried Commitizen and found it slower with more prompts — Better Commit asks fewer questions and gets out of the way faster. If you're working on a project with CI that validates commit messages (and you should be), this eliminates the "oops, wrong prefix" cycle.

## Shell replacements that compound daily

These are modern rewrites of Unix coreutils. Individually, each saves a few seconds. Collectively, they reshape how you interact with the filesystem. Small friction reductions compound — I estimated these save me 15-20 minutes per day across hundreds of small interactions.

**[eza](https://github.com/eza-community/eza)** replaces `ls` with git-aware file listings, icons, and tree views built in. `eza -la --git` shows me file permissions, sizes, and git status in one shot — information that previously required piping `ls` through multiple commands. I aliased `ls` to `eza` and `tree` to `eza --tree`, so the muscle memory stays the same but the output is categorically better.

```bash title="~/.zshrc"
alias ls="eza --icons"
alias ll="eza -la --icons --git"
alias tree="eza --tree --icons --level=3"
```

**[zoxide](https://github.com/ajeetdsouza/zoxide)** replaces `cd` with frecency-based directory jumping. It learns your habits — after a week of normal use, I stopped typing full paths entirely. The lookup is instant and gets smarter the more you use it.

```bash title="Terminal"
# zoxide learns paths automatically as you navigate
cd ~/Developer/aayush/next-portfolio

# later — from anywhere on the system
z portfolio    # jumps to ~/Developer/aayush/next-portfolio
z blog         # jumps to the most-visited directory matching "blog"
zi portfolio   # interactive selection if multiple matches
```

**[ripgrep (rg)](https://github.com/BurntSushi/ripgrep)** replaces `grep` and it's not close. Ripgrep is faster, respects `.gitignore` by default (no more sifting through `node_modules` results), and supports PCRE2 regex. For [building this blog with MDX](/blog/build-a-blog-with-nextjs-and-mdx), I use `rg` constantly to search across content files and component code simultaneously.

```bash title="Terminal"
# search only TypeScript files for a component usage
rg "MDXRemote" --type ts

# find all TODOs — .gitignore respected automatically, no node_modules noise
rg "TODO|FIXME"

# count matches per file for a quick usage audit
rg "useState" --count --sort path
```

**[delta](https://github.com/dandavison/delta)** makes `git diff` output actually readable. Syntax-highlighted diffs with line numbers, side-by-side view mode, and proper word-level change highlighting. Set it as your git pager once and every `diff`, `log`, and `show` command benefits automatically — zero changes to your workflow.

```ini title="~/.gitconfig"
[core]
  pager = delta
[delta]
  navigate = true
  side-by-side = true
  line-numbers = true
[interactive]
  diffFilter = delta --color-only
```

> Four aliases — `ls`, `cd`, `grep`, `cat` — all pointing to faster tools. Same muscle memory, better output. That's the ideal upgrade path.

## API and database tools

I burned out on Postman's bloat (500MB for an HTTP client, really?) and switched to terminal-native alternatives. These two cover 95% of what I need without Electron.

**[Posting](https://posting.sh/)** is Postman as a TUI. API collections are plain text files I can version-control, diff, and share through Git. It starts in under a second. No account required, no cloud sync, no team-tier upsell. For testing endpoints during development, it's everything I need and nothing I don't.

**[Harlequin](https://harlequin.sh/)** is a lightweight SQL client that works with Postgres, SQLite, and DuckDB. I was using DataGrip but the JetBrains startup time was killing quick database checks — "let me verify this query" shouldn't require waiting 15 seconds for a Java app to boot. Harlequin is instant, keyboard-driven, and has autocomplete for table and column names.

## How it all connects: a real workflow

The individual tools matter less than how they compose. Here's what a typical coding session looks like end to end.

I open Wezterm. Tmux automatically attaches my last session — three windows already arranged: editor, server, and git. I hit `Ctrl+Shift+P` to open my project switcher (FZF scanning `~/Developer`), type "port" to fuzzy-match my portfolio repo, and I'm in the project root.

Neovim opens with Telescope ready. I type `<leader>ff`, search for the component I need to change, and LSP has diagnostics loaded before my fingers leave the keyboard. After making changes, I split a Tmux pane, run the dev server, and preview in the browser.

When I'm ready to commit, `lg` aliases to Lazygit — I stage hunks visually, write a conventional commit message with Better Commit, and push. The diff shows up syntax-highlighted via delta. The entire flow from "open terminal" to "pushed commit" never touches a mouse.

> The philosophy is home-row efficiency. Every mouse reach is a context switch, and context switches are where focused work goes to die.

That's not theoretical. I timed my workflow before and after the migration. Common operations — finding files, switching projects, staging commits, checking processes — dropped from an average of 8 seconds to under 2. Across a full workday, that's a non-trivial amount of reclaimed focus time.

## What didn't survive the cut

Not everything I tried made it. The purge is the most important part of this system — adding tools is easy, removing them requires honesty about what's actually useful versus what looks cool in a dotfiles screenshot.

**Neofetch/Fastfetch** — Fun for exactly one screenshot. After that, it's a startup script that adds 200ms to every new terminal for information I never look at. Removed after a week.

**Cava** — Audio visualizer in the terminal. Beautiful, completely useless for development work. I kept it for two months because it looked good on r/unixporn. Vanity tool.

**Hyprshot** — Screenshot utility for Hyprland. Replaced with a three-line shell script using `grim` and `slurp` that does exactly what I need without another dependency.

**Starship prompt** — Feature-rich cross-shell prompt. Looked great, added 150ms to prompt rendering. I switched to a minimal custom prompt in my `.zshrc` that shows git branch and exit code. Nothing else.

**Fig (now Amazon Q)** — Autocomplete overlay for the terminal. Clever idea, terrible execution. It intercepted keystrokes, conflicted with FZF, and the AI suggestions were wrong often enough to be distracting rather than helpful. Uninstalled after three days.

## The terminal as an investment

Two years in, the productivity gains are real but they're not the main reason I stayed. The deeper value is *understanding what your tools are doing*. GUI applications hide complexity behind buttons and dropdowns. Terminal tools expose it.

When your build fails, you see the exact command that ran. When your git history is wrong, you see the exact sequence of operations. That transparency makes you a better debugger, a better systems thinker, and — counterintuitively — faster at fixing problems even in GUI-heavy environments because you understand the underlying primitives.

The honest cost: the first month was slower. Significantly slower. I had to look up keybindings constantly, my Neovim config broke weekly, and I missed VS Code's "it works out of the box" convenience. If you're considering this switch, budget real time for the transition and don't do it the week before a deadline. The payoff comes, but it's not instant.

I'm watching a few tools for potential additions: [Ghostty](https://ghostty.org/) as a Wezterm alternative (Zig-based, extremely fast, but still maturing), [Helix](https://helix-editor.com/) as a post-Vim modal editor (built-in LSP, no plugin management, but the ecosystem is thin), and [Claude Code](https://docs.anthropic.com/en/docs/claude-code) for AI-assisted development directly in the terminal — the only AI tool I've tried that fits a keyboard-driven workflow instead of fighting it.

The filter stays the same: if it doesn't make me measurably faster after two weeks of honest use, it gets cut. That filter is the whole point of this setup. The specific tools will change — the discipline of cutting what doesn't earn its place won't.

## Frequently asked questions

### What tools are in a terminal-first dev setup?

This terminal-first setup rests on four core tools: Neovim as the editor, Wezterm as the terminal, ZSH with Oh My Zsh as the shell, and Tmux as the multiplexer. FZF, Lazygit, bat, Btop++, eza, zoxide, ripgrep and delta fill the gaps around them.

### Why switch from VS Code to Neovim?

VS Code hit 2.4GB of RAM during a Next.js debugging session and froze the laptop mid-demo. Neovim with native LSP and Treesitter gives the same autocomplete, go-to-definition and inline diagnostics, but starts in 40ms instead of four seconds.

### Why use Tmux instead of Zellij or Wezterm's multiplexer?

Tmux keeps every pane, process and scroll position alive when an SSH connection drops or the laptop closes, and tmux-resurrect restores sessions after a full reboot. Zellij crashed twice during production incident debugging, and Wezterm's multiplexer mode is half-baked compared to Tmux.

### What are the best modern replacements for ls, cd, grep and cat?

eza replaces ls with git-aware listings, zoxide replaces cd with frecency-based directory jumping, ripgrep replaces grep and respects .gitignore by default, and bat replaces cat with syntax highlighting. Aliasing the old commands to the new tools keeps the same muscle memory and saves an estimated 15 to 20 minutes per day.

### How long does it take to get productive with a terminal-first workflow?

Expect the first month to be significantly slower: Neovim's learning curve is brutal for the first two weeks and keybindings need constant lookups. After the switch, common operations like finding files, switching projects and staging commits dropped from an average of 8 seconds to under 2.

### Is there a terminal alternative to Postman?

Posting is a TUI HTTP client that stores API collections as plain text files you can version in Git, starts in under a second, and needs no account. For databases, Harlequin is a keyboard-driven SQL client for Postgres, SQLite and DuckDB.
