New Year, New Terminal Setup
Every new year people tend to make these “resolutions” to improve their lives somehow. I don't really believe in making these “new year, new me” types of resolutions myself; Nevertheless, the beginning of a new year is a good time to do some improvement tasks one has been putting off for a while. For me, this time it's about refining my macOS terminal setup and dotfiles.
My previous setup served me well for years - iTerm2, Zsh, Powerlevel10k, and various ZSH plugins, with dotfiles managed via Git bare repository – though functional, I felt it was time for an upgrade. This blog post covers the key changes in my 2025 setup.
During 2024, I've been watching a lot of "developer influencer content" from Dreams of Code, Dreams of Autonomy, Typecraft, Fireship, Theo, Primeagen and the likes. While I don't think anyone should take their opinions as gospel, they often provide interesting takes and inspiration. No, I won't be switching to Arch Linux – btw – or Neovim (as I am a Cursor fan), but some ideas have definitely affected my thinking and setup.
I've used iTerm2 for the past decade or so. It has served me well, but my main gripe with it has been the lack of file-based configuration.
A while back, Ghostty started popping up on my radar. Developed by none other than Mitchell Hashimoto (Founder of HashiCorp & creator of Vagrant, Packer, Consul, Terraform, Vault, Nomad, Waypoint, and more), it promises to be a native, fast, compliant, and configurable open-source terminal emulator for Linux & macOS.
So I went ahead and just ran:
brew install --cask ghosttyI love it that it aims to have Zero Configuration Philosophy, but when you do want to configure something it can be done via simple key-value format:
font-family = "Monolisa"font-size = 16theme = "catppuccin-mocha"As you see, the amount of configuration I needed is really minimal. I use Catppuccin Mocha theme (you can list all the bundled themes with ghostty +list-themes) and my favorite Monolisa font – though I can't yet say for sure if it works as well as other Ghostty "native" fonts (see ghostty +list-fonts), but so far I haven't spotted any issues.
One specific thing I love about it is how Ghostty has implemented zooming. I do a lot of live demos at work through screen sharing: With iTerm2 if you zoom in (cmd++) it will zoom the entire terminal application window, but with Ghostty it will only zoom the text content – not the terminal application window. Just this is a reason to switch for me!
Additionally, like iTerm2, Ghostty supports macOS Auto Secure Input – which is not a common feature in other terminal emulators.
My previous Git bare repository setup for dotfiles felt somehow cumbersome, because to me it felt sometimes confusing to keep track of which files in my $HOME are managed by git and which are not. It was better than my older Ansible setup, but still it left me wanting for something more.
There's an old and battle-tested tool for managing bunch of symlinks: GNU Stow. After seeing a video by Dreams of Autonomy on the topic, I realized that it's exactly what I've been looking for!
❯ tree .. -a..└── sources └── foo.txt └── bar.txt2 directories, 2 files❯ stow .❯ tree .. -a..└── foo.txt -> sources/foo.txt└── bar.txt -> sources/bar.txt├── sources └── foo.txt └── bar.txt2 directories, 4 filesUsing stow allows me to have all my "managed" dotfiles (i.e. configuration files) in a single specific "source" directory: ~/dotfiles. And of course, that "source" directory can be version controlled via git and synced to a GitHub remote repository.
And in case you're wondering will the .git folder be symlinked too: Stow ignores certain files (like .git folder) by default, but you can customize this behaviour with .stow-local-ignore file. On macOS, I recommend ignoring at least .DS_Store files.
Once I run stow . within that "source" directory (~/dotfiles), it will reflect its file structure into the "target" directory (the parent directory by default, in this case ~) as symlinks.
~/.zshrc are now symlinked from my home directory to my ~/dotfiles directory:
Now, whenever I need to add a new configuration file, I just add it to the ~/dotfiles directory and run stow . again.
If you have upstream changes from your GitHub remote repository (in cases such as you use and modify the same dotfiles in multiple machines), you can use the neat little script from System Crafters to:
- automatically stash your local changes
- pull from remote upstream
- and pop the local changes back
- stow after pulling (unless conflicts)
I haven't published my dotfiles as public repository, but you can find hundreds of thousands of examples of dotfiles in GitHub.
So far I've been using Powerlevel10k as my prompt and it's been working well. I really don't have a reason to switch (maybe other than Powerlevel10k not being actively maintained anymore), but I decided to give Starship a try. Maybe I'll switch back or maybe I won't, we'll see.
I know many "senior developers" recommend using Fish shell, but I hate the idea of using a non-POSIX-compliant shell. Hence I'm sticking with Zsh with some plugins (although one can argue some plugins might result in non-POSIX-compliant behavior).
I refuse to use Oh My Zsh since it is slow as hell and contains a lot of unnecessary plugins. Previously I used to install Zsh Plugins manually and sourcing them from brew --prefix directory, but I found it cumbersome to manage. Now I switched to zinit which is a modern (and seemingly really fast) Zsh plugin manager. Here's an example how I source zinit and install/load plugins with Turbo/Lucid mode:
Only relevant parts to zinit & plugin loading are shown here:
source $(brew --prefix)/opt/zinit/zinit.zshzinit wait lucid for \atinit"ZINIT[COMPINIT_OPTS]=-C; zicompinit; zicdreplay" \ zdharma-continuum/fast-syntax-highlighting \blockf \ zsh-users/zsh-completions \atload"!_zsh_autosuggest_start" \ zsh-users/zsh-autosuggestionsI've been using ls replacement eza and cat enhancement bat for some years now. I really love these kinds of "enhanced" tools for native commands to boost terminal productivity.
Still, one of the most important CLI commands I use daily is cd and for that I've been really craving for a tool that would help me navigate directories faster. Luckily there is a solution to use a combination of zoxide (smarter cd replacement) and fzf (command-line fuzzy finder) to improve the way I navigate directories. Again shout-out to Dreams of Autonomy for the great introduction for these two.
I have my opinions about the “AI hype” (as you might too), but I still see a lot of value for having easy access to GenAI tooling wherever I work. Cursor is great, but I want to have access to AI sometimes directly in the terminal as well: For that, GitHub Copilot CLI is a neat tool. But typing the gh copilot suggest command is a bit cumbersome, so I've aliased it to § character which I don't use anywhere else really:
alias §='gh copilot suggest -t shell'$ alias:
I've left many aspects of my setup unmentioned in this post, but I just wanted to document some of the highlights of the changes I've made to my setup for 2025 – and hopefully for many years to come!
I suspect I will be tweaking this setup even more as I go along, but hopefully this blog post can serve as a bit of inspiration & reference for you to improve your own setup!
Oh, and have a happy new year! 😊