A CLI development environment is just tools composed together. Here's what I actually use and why. Not a recommendation list — a snapshot of what works for me right now.
Multiplexer: Zellij
Chose Zellij over tmux. The reason is boring: it works out of the box. Tmux is more configurable but I've watched people spend days on their tmux config. Zellij gives you sessions, panes, layouts, and keybinding hints without a dotfile.
If you already have a tmux config you love, keep it. Tmux is battle-tested and available on every server you'll ever SSH into. Zellij isn't. That's a real tradeoff I accept because I'm mostly working locally.
Editor: Neovim
Started from kickstart.nvim and added things as I needed them. The principle: don't install a plugin until you hit the wall it solves.
telescope.nvim -- fuzzy find everything
harpoon -- jump between active files
nvim-lspconfig -- language servers
nvim-dap -- debugging (when printf isn't enough)
gen.nvim -- local AI chat via Ollama
lazygit.nvim -- git without leaving the editor
That's most of it. Six plugins doing real work. Not thirty plugins doing theoretical work.
AI integration
Two layers. gen.nvim in the editor talks to local Ollama models for quick questions and small refactors. Claude Code in a terminal pane handles bigger tasks — architecture discussions, multi-file changes, the kind of thing where you need a collaborator not an autocomplete.
Local models for privacy-sensitive work and offline. Cloud models when I need reasoning depth. The routing is manual — I pick the tool based on the task. Automated routing sounds cool but adds complexity I don't need.
# local AI for quick stuff
:Gen Chat # in neovim
ollama run codestral # in terminal
# Claude Code for real collaboration
claude # in a zellij pane
# context bridge
wherewasi pull | claude --message - # feed project context
The switching workflow
Project switching is where CLI either shines or falls apart. If it takes more than ten seconds to get oriented in a different project, you'll stop switching and start context-stacking (twelve browser tabs, three half-finished branches).
cd ~/projects/uroboro # go there
zellij attach uroboro # restore session (or create new)
# editor opens, panes restore, we're working
Zellij sessions are named per project. Each one has its own pane layout. Switch sessions, and you're looking at exactly what you were looking at last time. No "where was I?"
What's missing
Visual diffing. git diff works for small changes. For big refactors across many files, a side-by-side visual diff is genuinely better. I use delta as a pager, which helps, but it's not the same as a GUI diff viewer.
Image work. Terminals can display images now (kitty protocol, sixel) but it's janky. If I need to look at a screenshot or diagram, I open it in a viewer. No pretending the terminal handles everything.
The stack isn't finished. It changes when I hit a new wall. That's the point — it's built from actual problems, not from a "recommended tools" list.