AV
4 min read

My work setup

One terminal window on a Mac. What every tool inside it is for, in a line, and what each one actually looks like when I'm working.

I work on a Mac, an M4 MacBook with 24 GB. Nothing exotic about the machine. The one real decision in this setup is that almost everything happens inside a single terminal window. The browser is for looking at the thing I just built, and not much else.

Here's the whole thing, one line per tool. Every screenshot below is my actual machine.

The terminal

  • Ghostty. The terminal emulator. Native, GPU-drawn, opens instantly. I've never once had to think about it.
  • zsh + starship. The prompt. Starship shows the directory, the branch, whether the tree is dirty, and the Node version, without me asking.
  • zsh-autosuggestions. Greys out the rest of a command I've typed before. Right-arrow accepts it.
  • zsh-syntax-highlighting. The command turns green when it's a real binary and red when it isn't. Typos die before I hit enter.
  • JetBrainsMono Nerd Font. A normal coding font with the icon glyphs patched in. It's why every tool below can draw file-type icons.
A zsh session in Ghostty showing an eza tree with file-type icons, the starship prompt, and a greyed-out autosuggestion
eza's tree, the starship prompt, and an autosuggestion waiting to be accepted.

tmux + sesh

tmux is the actual workspace. One window for the editor, one for the dev server, one for whatever else, all split into panes, all still running when I close the laptop. sesh is the bit that makes it painless. One keystroke gives me a fuzzy list of every project directory and every running session, and picking one drops me straight in. I don't create sessions by hand any more.

A tmux session with Neovim on the left and two shell panes on the right, with the tmux status bar listing three windows
One tmux session per project. sesh's list is top-right. That's how I get back into any of them.

Neovim

Neovim is the editor. LSP, treesitter, fuzzy jump to any file or symbol, and it starts in about the time it takes to lift my hand off the key. The real reason it stays is that it lives in the same pane grid as everything else. No window switching between writing code and running it.

Neovim editing a TypeScript file with treesitter syntax highlighting
Neovim, in the same tmux pane grid as everything else.

yazi

yazi is a file manager for the terminal, and the tool I didn't expect to like. Three columns, parent and current and preview, so you're always seeing one step ahead. It previews images, PDFs and video thumbnails inline. That's why ffmpeg, imagemagick, poppler and resvg are on this machine at all. yazi shells out to them to render whatever you're hovering over.

The yazi terminal file manager showing parent, current and preview columns with file-type icons
yazi. Hover a file and you see it, no opening required.

Finding things

  • fzf. Fuzzy-finds anything you can pipe into it. Half of what I do in a terminal is really just fzf with a different input.
  • fd. Finds files. Same job as find, but the syntax is one word and it skips .gitignore by default.
  • ripgrep. Searches file contents. Fast enough that I stopped keeping a mental index of where things live and just grep the repo instead.
  • bat. cat with syntax highlighting and line numbers. Mostly it earns its place as the preview pane inside fzf.
fzf narrowing a file list from fd, with a syntax-highlighted bat preview on the right
fd feeds the list, fzf narrows it, bat previews it. Three tools, one keystroke.
ripgrep output grouped by file with matched terms highlighted
ripgrep across the repo, grouped by file.

Git

  • lazygit. Staging, hunk-by-hunk commits, branches, rebases, stashes, all in one keyboard-driven panel. I still write the commit messages by hand. I stage everything here.
  • git-delta. The diff pager. Side-by-side line numbers, real syntax highlighting, and word-level highlights so you can see the two characters that actually changed.
The lazygit terminal UI showing status, files, branches, commits and the patch for the selected commit
lazygit. Everything I used to type out, as one panel.
A git diff rendered by delta with side-by-side line numbers and word-level highlighting
delta highlights the words that changed, not just the lines.

The rest

  • zoxide. A smarter cd. It learns the directories I actually visit, so z port lands me in this repo from anywhere.
  • atuin. Shell history in a real database. Searchable, synced across machines, with the timing and exit code of every command.
  • btop. The system monitor. Per-core CPU, memory, disk and the process list, for when something starts eating the fan.
  • gh. GitHub from the terminal. PRs, issues and reviews without opening a tab.
  • jq. For reading a JSON response like a human.
atuin's stats view showing the most-used commands and their counts
atuin knows what I actually run. Apparently it's mostly cd.
The btop system monitor showing per-core CPU, memory, disks and the process list
btop, for when the fan starts.

Getting all of it

brew install tmux neovim yazi fzf fd bat eza zoxide atuin starship \
  lazygit git-delta sesh btop ripgrep jq gh ffmpeg imagemagick poppler
brew install --cask ghostty font-jetbrains-mono-nerd-font

That's the whole setup. None of it is clever. Every one of these replaced something I was already doing worse, and after a while there was no reason to leave the terminal.

toolingterminalworkflowneovim