Dev tools on my macOS (2025)

Published: |

Dev tools on my macOS (2025)



Homebrew

https://brew.sh, alternatives to MacPorts, manual scripts and etc.

Despite Homebrew being released in 2009, it remains as the community default choice of package manager for macOS. Personally, I like to use Homebrew with Brewfile https://docs.brew.sh/Brew-Bundle-and-Brewfile. Instead of execute commands like brew install neovim imperatively, I like to define them in a Brewfile and run brew bundle to install them declaratively:

~/.config/Brewfile
# Example Brewfile
brew "lsd"
brew "neovim"
brew "zellij"
brew "mise"
# GUIs
cask "flux"
cask "ghostty"
cask "zed"

The obvious benefit of this approach is we can backup the Brewfile and reinstall the packages on a new environment whenever we need to.

Mise

https://mise.jdx.dev, alternatives to: asdf, nvm, pyenv and etc.

In the case of package management, I would recommend mise as the package version manager. What is a package version manager? It’s a tool that allows us to manage different versions of a package on the same system. For example, if we have multiple projects that require different versions of Node.js, we can use mise to switch between them easily. This is not something that can be easily achieved with brew.

The way I use mise is by creating a mise.toml file at the root of each project:

mise.toml
[tools]
node = "24"
pnpm = "10"

Or by executing the mise use command inside the project directory:

Terminal window
mise use node@24
mise use pnpm@10

The directory with mise.toml at its root will have the declared versions enabled within the project. If we switch to another project with different tools or versions, mise will automatically switch.

The mise use --global <tool>@<version> command will create a global configuration file in ~/.config/mise/mise.toml that will ensure the tools listed are available globally.

~/.config/mise/mise.toml
[tools]
python = "3.13" # globally defined Python version

When to use mise vs brew?

If mise and brew can both install packages, why do I use them together?

While it is possible to use mise to manage everything (if the tool is available in its registry). But personally, I still like to use brew for packages that I do not care about their versions, such as git, curl, or jq. Plus, Brewfile have a greater selection of GUI applications through brew cask. Therefore, my rules between mise and brew are:

  • Use mise for tools that I care about their versions, such as node, pnpm, or python.
  • Use brew and Brewfile for packages that I do not care about their versions, such as git, curl, or jq and GUI applications like ghostty, raycast, orbstack, etc.

Fish Shell

https://fishshell.com, alternatives to zsh, bash and etc.

On modern macOS, zsh is the default shell. However, I prefer to use fish as my daily shell. When compared to zsh, fish offers features like syntax highlighting, auto-completion, and a rich command history out of the box! We would have to install zsh framework like on-my-zsh and a bunch of plugins to achieve the same baseline features as fish. Btw, did I mention fish is now written in Rust? 🦀

Because I would like to have the latest stable version of fish, I install it through Brewfile:

Brewfile
brew "fish"

Although I like fish very much, I do not set fish as my default shell. I keep zsh as the system default shell. This is because as popular as fish is, most tools and scripts will most like not to have fish in mind, and are still based on either bash or zsh. In the past, I had issues with fish conflicting with other tools (e.g., when running automatic scripts), and now I would rather manually set fish as the shell in places where I need it. For example, in the code editor Zed, I add the following lines in ~/.config/zed/settings.json to set fish as the default shell for its integrated terminal:

"terminal": {
"shell": {
"with_arguments": {
"program": "/opt/homebrew/bin/fish",
"args": ["--login", "--interactive"]
}
}
}

Ghostty

https://ghostty.org, alternatives to alacritty, iterm2, warp and etc.

Only released in December 2024, Ghostty by Mitchell Hashimoto is already the go-to terminal emulator of many developers. It is written in the Zig language and it is honestly fast. Compared to other terminal emulators I’ve tried, Ghostty offers flawless performance and I really enjoyed the fact that Ghostty has built-in nerd fonts, it just makes so much sense.

Set fish as default shell in Ghostty

Find the Ghostty configuration file for example $HOME/.config/ghostty/config and add in the following lines:

.config/ghostty/config
command = /opt/homebrew/bin/fish --login --interactive
shell-integration = fish

Raycast

https://www.raycast.com, alternatives to Spotlight, Alfred, and etc.

The last tool on this list is also my most-used in terms of daily usage. Raycast replaces the sluggish Spotlight that came with macOS, but it offers a whole lot more than just a faster search tool. Some of its built-in or third-party extensions replace the need for other tools, and here are some of my favorites:

  • Clipboard History. I bind it to shortcut Cmd + Shift + C.
  • Window Management. This replaced Rectangle for me.
  • Raycast AI (paid feature). My go-to AI assistant as with a simple shortcut Option + Space, I can quickly open up a LLM chatbot with different models to choose from.
  • Raycast Notes. This also replaced the built-in macOS Notes app for me, as it offers developer friendly features like Markdown support and syntax highlighting etc.

This is not a exhaustive list of features of Raycast. There are so much more: Calculator, Currency Converter, Emoji Picker, Calendar Integrations, Shortcuts, Translate etc… I highly recommend you to check Raycast out if you haven’t already.


All Together

Here’s how I would setup the above tools after a fresh macOS installation:

1. Install homebrew

Open the default Terminal app, and paste in the installation script from https://brew.sh

2. Init Brewfile

Create Brewfile in ~/.config/Brewfile or your preferred location, and list out tools as brew or cask (Search on the brew.sh website for clarifications):

~/.config/Brewfile
brew "fish"
brew "mise"
cask "ghostty"
cask "raycast"

Run brew bundle within the ~/.config directory.

3. Setup fish in Ghostty

Follow the guide above to set fish as the default shell in Ghostty.

4. Use mise to manage package versions

For more project-dependent packages, like node, python and pnpm etc, we can:

Terminal window
# setup project-based versions
mise use node@24
mise use python@3.13
# or setup globally versions
mise use --global node@24
mise use --global python@3.13

5. Launch Raycast

Launch Raycast, configure to your needs, and be a 10x developer 🚀


There are so many other dev tools I use on a daily basis that I haven’t mentioned, for example: neovim, astronvim, lazygit, starship, zellij, zed, orbstack and more, but I feel like they deserve a dedicated blog post so stay tuned for my future blog posts 👀