1 · Why a deliberate setup matters
A messy machine is a slow, risky machine. Files you can't find. Ten versions of Node installed three different ways. Apps that silently went out of date months ago. Passwords saved in a browser you no longer trust. None of it screams "problem" on day one — it just quietly taxes you forever.
A good setup optimises three things at once:
- Speed — you find things instantly and never fight your tools.
- Reproducibility — you can rebuild your whole environment on a new laptop in an afternoon, not a week.
- Security — the boring hygiene (updates, a real password manager, antivirus) is what actually keeps you and the company safe.
One principle ties it all together. Prefer tools that manage themselves. A package manager that updates every app, a password manager that generates every password, an antivirus that updates its own definitions — automation beats willpower.
2 · A home for everything: file organisation
The single best habit: give your code one root folder and never scatter projects across the Desktop and Downloads. On macOS, ~/Development (or ~/Developer) is the convention.
# One root for all your work — create it once
mkdir -p ~/Development
Inside it, one folder per project, each self-contained. Consistency is the point: when every project looks the same, you never have to think about where anything lives.
~/Development/
├── mindmerge/ # one folder = one project = one git repo
│ ├── README.md # what it is + how to run it
│ ├── .gitignore # what git should ignore (incl. secrets)
│ ├── .env # local secrets — NEVER committed
│ └── src/
├── client-website/
└── experiments/ # throwaway/learning projects live together
- Work out of the project folder, not Downloads. Downloads is a temporary inbox — treat anything there as disposable.
- A
README.mdin every project. Future-you (and teammates) will thank you. - Keep secrets out of the repo. Config and API keys go in a git-ignored
.env, never in the code. (See the environment config section of the Git guide for the full why.)
Bonus habit: dotfiles. Your config files (shell, git, editor) can themselves live in a git repo called dotfiles. That way your whole setup — aliases, git identity, editor settings — is version-controlled and portable to any new machine.
3 · Install through a package manager, not one-off downloads
Here's the habit that separates a professional setup from a fragile one. When you need a tool — a language, a database, an app — don't hunt down a website and double-click an installer. Install it through a package manager.
What's wrong with manual, "isolated" installs? Each one becomes an island you have to maintain by hand:
| Manual download | Package manager |
|---|---|
| You must remember to check each app for updates. | One command updates everything at once. |
| Versions drift — "works on my machine" bugs. | Everyone can install the same versions. |
| You trust whatever random site you landed on. | Packages come from a curated, checksummed catalog. |
| No record of what you installed. | Your whole setup is a list you can replay. |
On macOS the standard is Homebrew (brew). Install it once with the official one-liner from brew.sh:
# Install Homebrew (the official installer from brew.sh)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Homebrew installs two kinds of things:
- Formulae — command-line tools, languages and libraries (
git,node,python). - Casks — full GUI applications (VS Code, Chrome, Bitwarden).
# Command-line tools & languages (formulae)
brew install git node gh
# Desktop apps (casks) — installed & updatable just like CLI tools
brew install --cask visual-studio-code google-chrome iterm2
# Search before you install
brew search postgresql
For apps that only live in the Mac App Store, add mas so even those are scriptable:
brew install mas
mas search Xcode
mas install 497799835 # install by its App Store ID
Not on a Mac? Same idea, different tool: Windows → winget (built in) or Chocolatey (choco); Linux → your distro's manager (apt, dnf, pacman). The habit is universal: install through the manager, not the browser.
4 · Make it runnable: your PATH and shell profile
You install a tool, type its name, and the terminal snaps back command not found. Nine times out of ten the tool is installed perfectly fine — your shell just doesn't know where to look. This one idea trips up nearly everyone, so spend ten minutes on it now and never lose an hour to it later.
When you run a command, your shell walks through a list of folders called $PATH and launches the first matching program it finds. If the tool's folder isn't on that list, you get command not found — even though the file is sitting right there on disk.
Installed ≠ findable. Reinstalling almost never fixes command not found — you just install the same thing to the same place your shell still isn't looking. Fix the PATH, not the install.
So when a command isn't found, run this three-step triage instead of reaching for the installer again:
# 1 · Is it actually installed? Find the binary.
brew --prefix the-tool # where Homebrew put it, if it's a brew tool
ls ~/.the-tool/bin # non-brew installers often drop binaries here
# 2 · Is that folder on your PATH?
command -v the-tool # prints the path if found — nothing if not
echo "$PATH" | tr ':' '\n' # list every PATH folder, one per line
# 3 · Missing? Add the folder to PATH (below), then reload your shell.
Homebrew's "keg-only" trap
Most Homebrew tools land in /opt/homebrew/bin, which is already on your PATH — so they just work. But a few are deliberately not linked, so they don't shadow a version macOS itself relies on. Homebrew calls these keg-only, and Java (openjdk) is the one nearly everyone hits: brew installs it, yet java stays "not found" until you wire it up. Conveniently, brew prints the exact lines you need:
# Ask brew how to wire up a keg-only formula — it prints the exact lines
brew info openjdk
# For Java: point JAVA_HOME at the keg and put its bin on PATH
export JAVA_HOME="$(brew --prefix openjdk)"
export PATH="$JAVA_HOME/bin:$PATH"
Set both: many JVM tools (Maven, Gradle, and SDKs that themselves run on Java) look for JAVA_HOME, not just java on the PATH. And if you want every app — including /usr/bin/java and GUI tools — to find it, register the keg with the system once (this one needs your password):
# Optional: let macOS's own java_home discover the keg, system-wide
sudo ln -sfn "$(brew --prefix openjdk)/libexec/openjdk.jdk" \
/Library/Java/JavaVirtualMachines/openjdk.jdk
Tools installed outside Homebrew
Not everything comes from a package manager — a security suite, some vendor SDKs and language toolchains ship their own installer. Those usually drop the program in a hidden folder like ~/.the-tool/bin and try to add it to your PATH by editing a shell file for you. Two things routinely go wrong: the installer edits the wrong file, or you simply never reloaded your shell. Which brings us to the real gotcha…
Which profile? .zshrc vs .bash_profile
Your PATH lines only take effect if they live in the file your shell actually reads at startup — and you probably have more than one such file lying around. Check which shell you run, then edit its file:
echo "$SHELL" # /bin/zsh, /opt/homebrew/bin/bash, …
| Your shell | Startup file it reads (macOS) |
|---|---|
| zsh — the macOS default | ~/.zshrc |
| bash — in Terminal (a login shell) | ~/.bash_profile (not ~/.bashrc) |
This is the subtle one: macOS Terminal opens a login shell, and there bash reads ~/.bash_profile — so a PATH line an installer wrote into ~/.bashrc silently never runs. Put your exports in the right file, and have .bash_profile pull in .bashrc so there's just one place to maintain:
# Add a tool's folder to PATH permanently (bash in Terminal)
echo 'export PATH="$HOME/.the-tool/bin:$PATH"' >> ~/.bash_profile
# Make bash also load .bashrc, so you maintain a single file
echo '[ -r ~/.bashrc ] && . ~/.bashrc' >> ~/.bash_profile
# Apply it right now — no need to quit the terminal
source ~/.bash_profile
A good habit is to keep all of this in one clearly-commented block in your profile, so future-you knows why each line is there. A sensible starting point:
# ~/.bash_profile — keep your shell environment in one place
# Homebrew keg-only tools (Java, etc.) — point tools at them explicitly
export JAVA_HOME="$(brew --prefix openjdk)"
export PATH="$JAVA_HOME/bin:$PATH"
# Tools installed outside Homebrew add their own bin folder
export PATH="$HOME/.the-tool/bin:$PATH"
# Load .bashrc too, so aliases & prompt live in a single file
[ -r ~/.bashrc ] && . ~/.bashrc
Added it and it's STILL not found? You almost certainly didn't reload. A shell reads its profile once, at startup — so either run source ~/.bash_profile or open a fresh terminal window before you try again.
5 · A reproducible machine (Brewfile)
Because everything is installed through Homebrew, your entire setup can be captured in a single text file — a Brewfile — and replayed on any Mac. This is the same "recipe you can rebuild from" idea as a project's lockfile, but for your whole machine.
# Brewfile — a portable description of your machine
tap "homebrew/bundle"
# CLI tools
brew "git"
brew "node"
brew "gh"
brew "mas"
# GUI apps
cask "visual-studio-code"
cask "google-chrome"
cask "bitwarden"
cask "iterm2"
# Save your current setup to a Brewfile...
brew bundle dump
# ...and reinstall everything on a fresh machine from it
brew bundle install
Keep the Brewfile in your dotfiles repo. New laptop day becomes: install Homebrew → brew bundle install → coffee. Everything you use, back in minutes.
6 · Updates are security
Most successful attacks don't use exotic zero-days — they exploit known holes in software people never got around to updating. Every update you skip leaves a documented, publicly-known door open. Staying current is the highest-value security habit there is, and the package manager makes it a one-liner.
# Update EVERYTHING Homebrew manages, in one go
brew update # refresh the catalog of available versions
brew upgrade # upgrade all installed formulae & casks
brew cleanup # remove old, superseded versions
Some apps update themselves and are skipped by a normal upgrade; sweep those in too with --greedy:
brew upgrade --greedy # also update casks that self-update
Your operating system is the most important thing to keep patched. On macOS, turn on automatic updates (System Settings → General → Software Update → Automatic Updates), and you can also check from the terminal:
softwareupdate --list # see what's available
softwareupdate --install --all # install all pending OS updates
Update runtimes and frameworks through the manager too — never by re-downloading an installer over the top. Update Node with brew upgrade node (or a version manager like nvm/fnm if you juggle versions); update project libraries with your language's manager (npm, pip, …) and commit the updated lockfile.
Make it a rhythm, not a heroic act. Run the update trio once a week (or automate it with a tool like brew autoupdate). "I'll do it later" is how machines end up years behind.
7 · Passwords: use Bitwarden, not your browser
A password manager creates a long, random, unique password for every account and remembers them all behind one master password. This is non-negotiable for anyone with access to company systems — password reuse is how one leaked site turns into a dozen compromised accounts.
Turn off your browser's built-in password manager
Browsers offer to "save passwords," and it's convenient — but it's the wrong tool for the job. Turn it off and use a dedicated manager instead. Why:
- It locks you into one browser. A real manager works across every browser, your phone, and desktop apps.
- Weaker protection by default. On a shared or unlocked machine, browser-stored passwords are often one click from being viewed in plain text.
- Two half-managers fight. Running the browser's autofill and a real manager causes confusing double prompts and mis-saved logins. Pick one — the good one.
Disable it (do this in every browser you use):
| Browser | Where to turn it off |
|---|---|
| Chrome / Edge | Settings → Autofill and passwords → Password Manager → turn off Offer to save passwords & Auto Sign-in |
| Safari | Settings → AutoFill → uncheck User names and passwords |
| Firefox | Settings → Privacy & Security → Logins and Passwords → uncheck Ask to save logins |
Install Bitwarden — app and browser extension
Our pick is Bitwarden: open-source, audited, free for personal use, and it runs everywhere. Install both pieces — the desktop app (for a system-wide vault) and the browser extension (for autofill on websites):
# Desktop app via Homebrew (updates with the rest of your machine)
brew install --cask bitwarden
- Browser extension: install it from your browser's own extension store (Chrome Web Store, Firefox Add-ons, Edge Add-ons, Safari Extensions). Extensions come from the browser store, not Homebrew.
- Mobile: install the Bitwarden app on your phone too, so your vault is with you everywhere.
Then set it up right:
- A strong master password — a long passphrase of several random words beats a short cryptic one. This is the one password you must never forget and never reuse.
- Turn on two-factor authentication (2FA) for the Bitwarden account itself.
- Let it generate every new password — long, random, unique, one per site.
Your master password can't be recovered. Bitwarden encrypts your vault with it and never sees it — if you lose it, no one can reset it for you. Memorise it, and store an emergency copy somewhere genuinely safe (a sealed note at home, not a file called passwords.txt).
8 · Antivirus & keeping it current (Bitdefender)
"Macs don't get viruses" is a myth — malware, adware and phishing payloads target every platform, and a work machine is a valuable target. Run reputable endpoint protection as one layer of defence in depth. Our pick is Bitdefender.
This is the one deliberate exception to "install everything through Homebrew." Full security suites are distributed through the vendor's own installer with a built-in updater — and that's correct: you want the security vendor pushing new threat definitions directly, several times a day.
- Install from the vendor. Get Bitdefender from your Bitdefender Central account (the official installer). (Bitdefender isn't in Homebrew at all —
brew search bitdefenderreturns nothing — so it's one of the few apps you install outsidebrew.) - Leave automatic updates ON. For antivirus this matters more than for anything else: protection is only as good as its newest definitions. Never disable auto-update to "save resources."
- Keep real-time protection enabled so threats are caught as they arrive, not only during a manual scan.
- Run exactly one real-time antivirus. Two fighting over every file scan will slow the machine and cause false conflicts.
Antivirus is a layer, not a force field. It complements — never replaces — the basics: stay patched, use a password manager, enable 2FA, and think before you click a link or run a script you didn't write.
9 · While you're here: quick security wins
Three more things that take five minutes and dramatically raise your security floor:
- Turn on disk encryption. macOS FileVault (System Settings → Privacy & Security → FileVault) makes a lost or stolen laptop useless to a thief. Windows has BitLocker.
- Enable the firewall (System Settings → Network → Firewall).
- Set up automatic backups. macOS Time Machine to an external drive means a dead SSD or ransomware is an inconvenience, not a catastrophe.
10 · Day-one checklist
Run through this on any new machine and you're set up like a professional:
| Files | Create ~/Development; one folder per project; secrets in a git-ignored .env. |
| Package manager | Install Homebrew; install tools & apps via brew/brew --cask; capture a Brewfile. |
| PATH & shell | Know your shell (echo $SHELL); put PATH exports in the file it reads; source or reopen to apply. |
| Updates | Weekly brew update && brew upgrade && brew cleanup; OS auto-updates ON. |
| Passwords | Disable browser password saving; install Bitwarden app + extension; strong master password; 2FA on. |
| Antivirus | Install Bitdefender from Central; auto-update & real-time protection ON. |
| Hardening | FileVault ON, firewall ON, Time Machine backups running. |
Do this once, keep the good habits, and your machine stays fast, reproducible and safe — so you can spend your attention on the actual work. Next, if you haven't yet: read the Git & GitHub guide and make your first pull request. 🚀