Eklavya's Blog

A Comprehensive Guide to Customizing your MacBook

I recently got a new laptop - a MacBook Air (M4 2025)! I customized it so that it's easy for me to use. Major changes include:

  • Moving data from my old laptop to my new laptop.
  • Installing and configuring software for basic necessities, programming, and writing content.
  • Setting up a nice environment on my terminal.

As I made all these changes to my new laptop, I noted down the steps that I took for future reference. I think they could be useful to others, so here they are, as a blog post.

This post is written for macOS Tahoe. You may have to modify some instructions if you're using a newer macOS. If you're not using macOS, you can still get a similar working environment on Linux, but you'll have to make major modifications to the instructions below.

You can also refer to this dependency graph (source code).

Basic setup

  • Connect to a WiFi network, since we'll be downloading a lot of stuff.
  • Sign into iCloud. Create an account if you don't have one.
  • Remove useless apps from dock: right-click on the app in the dock, go to Options and click 'Remove from Dock'.

System Preferences

Click the Apple logo in the top-left corner of your screen and choose 'System Settings'. Here you can customize most aspects of your operating system. If you have the time, go through each of the items and choose the options which make sense to you. These are the changes which I made:

  • General > Software Update: update the OS.
  • Appearance: Use dark theme.
  • General > About: change 'Name'.
  • General > Storage: empty trash automatically.
  • General > Date and Time: select 24-hour time.
  • General > Language and Region: customize language and units.
  • General > Sharing:
    • Update local hostname.
    • Allow remote login via SSH.
  • Apple Intelligence and Siri: turn off.
  • Privacy and Security: Turn off FileVault.
  • Control Center:
    • Pick things that should show up in menu bar.
    • Show battery percentage.
    • Clock options: show seconds and date.
  • Desktop and Dock:
    • Position on screen: left.
    • Uncheck 'show suggested and recent apps in Dock'.
  • Menu Bar: Set 'Automatically hide and show the menu bar' to 'Never'. (This way I can see battery level, internet connectivity, volume, time, etc. in full-screen windows.)
  • Display: Choose the larger size.
  • Sound: select 'play feedback when volume is changed'.
  • Lock screen:
    • Customize screen lock and display off timings.
    • Show 24-hour time.
  • iCloud: turn off iCloud syncing for all items.
  • Keyboard > Input Sources > Edit:
    • Show input menu in menu bar.
    • Add other languages that I can type in: Greek, Hindi, Telugu, Kannada.

Finder preferences

Finder is the file manager in macOS.

  • Finder preferences (Cmd + ,):
    • General: Show hard disk and connected servers on desktop.
    • Tags: Don't show any.
    • Sidebar: Select useful locations.
    • Advanced:
      • Show all filename extensions.
      • Keep folders on top in windows.
      • Search current folder when performing a search.
  • Open home directory in Finder and then press Cmd + J to show view options. Select the options you like and press 'Use as Defaults'.
  • Go to 'View' in Finder's menu bar:
    • Show path bar.
  • Press Cmd + Shift + . to enable viewing hidden files.

Install Google Chrome and/or Firefox

  • Sync profile to get bookmarks and extensions.
  • Make it the default browser.
  • Perhaps also look at Safari settings just in case.

TextEdit preferences

TextEdit is the default plain-text and rich-text editor bundled with macOS.

I usually use Vim for text editing. Vim is far superior to TextEdit in terms of advanced functionality, like customizability, syntax highlighting, find-and-replace, etc. But having a lightweight GUI text editor can be handy.

TextEdit preferences (Cmd + ,):

  • Format: plain text. This is needed to prevent new instances of TextEdit from opening a rich-text editor.
  • Font: Menlo, size 16.
  • Disable 'Correct spelling automatically'.
  • Display HTML files as HTML code.
  • Disable 'add .txt extension to plain text files'. This is needed if you have to edit extensionless files.

Terminal and Shell

If you're an aspiring programmer or power user, you should get to know the command-line. For this blog post, I'm going to assume that you know how to run commands from the shell and you know the meaning of the following words: terminal emulator, shell, prompt, home directory, current working directory. In case you don't, here's a nice short tutorial by TreeHouse: Introduction to the Mac OS X Command Line.

Terminal preferences

Terminal.app is the default terminal emulator on macOS. But I recommend a better alternative, like iTerm2.

In iTerm2, I went to Settings > Profiles, and created a new profile and made it default (so as to not modify the factory default). In Colors, I chose 'Regular' as the Color Preset and unchecked 'use bright version of ANSI colors for bold text'.

In iTerm2, you may want to configure Option + arrow keys to move over words, just like in Terminal.app. To do this, go to Settings > Profiles > Keys > Key Mappings, and select 'Terminal.app Compatibility' as the preset.

If you decide to stick to Terminal.app, that's also not a bad option. In Terminal.app, you may want to deselect 'restore text when reopening windows' in the 'Preferences > Profile > Window' tab in Terminal.app.

Installing Xcode command-line tools

The 'Xcode command-line tools' consist of command-line applications that are very common in Unix-like environments, like git, gcc, make, perl.

Run xcode-select --install from a terminal. A dialog box will pop up. Select install. You should probably connect to a power source before doing this because macOS is going to suggest you do so.

Dotfiles

Dotfiles colloquially refers to configuration files placed in the home directory. These files' names start with a dot (.). Common examples are .zshrc, .vimrc and .gitconfig.

I have put all my dotfiles in a GitHub repository at sharmaeklavya2/dotfiles. You can find detailed instructions for setting them up in the repository's readme. Here is a brief version:

git clone https://github.com/sharmaeklavya2/dotfiles.git
cd dotfiles
python3 scripts/make_links.py

Now either restart your terminal or run source ~/.zshrc. If you executed the above instructions correctly, the first thing you'll notice is the improved, colorful prompt.

Environment variables that I don't want version-controlled with my dotfiles go in ~/.env. This file is sourced in .zshrc and .bashrc.

Install Homebrew

Homebrew (a.k.a. brew) is a package manager, which means it's like a terminal version of the App Store. You can install programs (called packages by brew) by simply writing commands on the terminal:

brew install name-of-package

See brew's website for installation instructions.

Brew will check for updates every time you run it. To prevent that from happening, add export HOMEBREW_NO_AUTO_UPDATE=1 to ~/.env.

Install tmux

I usually need multiple shells to be open. I can use iTerm's or Terminal.app's 'tabs' (Cmd + T) to achieve this. But I use tmux instead since it has more features. Also, if you SSH to a server that has tmux installed, you can open multiple shells on the server on a single SSH session.

To install, run brew install tmux.

Install newer bash

The version of bash that ships with macOS is very old. Run brew install bash to install a newer version of bash. This is helpful to check the compatibility of shell scripts between zsh and bash. When working on remote computers, I may not have zsh available.

Set up cron

Cron is a service that allows us to run a program (job) periodically, e.g., every two minutes. The jobs and their frequencies are specified in a file called crontab. Run crontab -e to edit your crontab in a terminal text editor.

If your cron jobs fail, you'll get 'mail' in /var/mail/$USER. You can view it by simply opening /var/mail/$USER in a text editor, and you can delete the file's contents to empty your inbox.

If your cron job requires reading files in protected directories, you'll have to give /usr/sbin/cron full-disk access. See https://apple.stackexchange.com/a/378558 for details.

Install command-line programs

MacTex

MacTex is a suite of programs for typesetting documents using TeX and LaTeX. LaTeX is a great system for writing professional-looking mathematical documents.

You can install MacTex using a GUI installer, but I did it using brew install --cask mactex.

Python and packages

macOS comes pre-installed with Python 3 (and doesn't have Python 2 installed), but it may not be the latest version.

Run brew install python3. That will install python3 and pip3.

I use python virtual environments. I use one big virtualenv where I install all commonly used packages, and I sometimes create application-specific virtualenvs.

Run python3 -m venv /path/to/venv/ to create a python3 virtualenv.

Activate the virtualenv using source /path/to/venv/bin/activate. Now all python commands and applications you run will use this virtualenv.

I usually install python packages only when required, but some are useful enough that I installed them in the beginning:

pip install requests jinja2 markdown pipdeptree flake8 grip

These packages are useful for math and computation:

pip install numpy scipy pandas matplotlib

Other useful programs

  • Although git is provided by the Xcode command line tools, a more recent version can be obtained using brew install git.
  • To be able to write and run Java programs, install openjdk: brew install openjdk.
  • Node.js and npm: brew install node.
  • Other useful programs that can be brew installed: delta, diffr, graphviz, ffmpeg, pandoc, dos2unix, htop, rlwrap.
  • Install yt-dlp by first installing node, and then running pip install "yt-dlp[default,curl-cffi]" yt-dlp-ejs.

Transfer backed-up data

Reorganizing data and backup

There are many places where I store my files:

  • My laptop's SSD (which is small enough for all my files to not fit on it).
  • My external hard disk.
  • My Dropbox account.
  • My GitHub repositories.
  • My Android phone.

Some of my files are stored on more than one of the above locations. To keep the copies in sync and avoid losing changes, I organized my stuff into folders based on the kind of content and access patterns and demarcated which folders will be on which storage mediums.

Fortunately, my content that changes frequently is lightweight (code, documents), and heavier content (videos, music, books) changes less frequently, so the former is either in git repositories or synced in real-time to Dropbox, and I keep copies of the latter on my hard disk.

If you use git, make sure to push all unpushed code on your old computer to an online remote to avoid losing data.

Filesystem issues

My external hard disk used to be NTFS-formatted. macOS cannot write to NTFS drives; it can only read from them. So I had two options:

  1. Copy the data elsewhere, reformat the external disk to exFAT, and then copy data back to the hard disk. This is what I ended up doing.
  2. Install an NTFS driver: I don't like this option because:
    1. Installing NTFS drivers requires reducing the system security level by booting into recovery mode.
    2. Open-source drivers are problematic (require mounting/unmounting via command-line) and closed-source drivers cost money (but some hard-disk manufacturers can get you free access to Paragon drivers if you're using their disk.)

I installed Dropbox's desktop app on my new laptop. This app creates a directory at ~/Dropbox and downloads all your online content into it. Anything you put in this directory will get synced to your online account.

In Preferences > Sync, I changed the default sync preference from 'online only' to 'available offline'.

Apparently, Dropbox doesn't allow external symlinks, so instead of having files outside and their symlinks inside Dropbox, I have files inside Dropbox and symlinks to them outside.

Clone git repositories

I have git repositories on github.com, gist.github.com, and overleaf.com. For private repositories, and when I push to repositories, I need to provide credentials to the git remote. It used to be easier many years ago, when the credentials were username and password. But these days github and overleaf use tokens. You can either generate new tokens (instructions for GitHub and Overleaf), or if you have an older macbook already, you'll find your tokens in the 'Keychain Access' application.

Customize Vim

Install newer Vim

Although macOS comes with vim pre-installed, that version of Vim was compiled without some important features. You can see which features are installed by running vim --version.

Run brew install vim to install a newer, better Vim. Alternatively, you can install MacVim (brew install macvim). These will not replace the old vim; the old vim can still be accessed at /usr/bin/vim.

Detecting dark mode

My .vimrc tries to detect whether the OS is using dark mode, and then sets dark mode in vim (set background=dark) accordingly. To do this detection, it uses the darkdetect python module. If this module is not installed, .vimrc falls back to using dark mode in vim.

I have installed darkdetect in a virtualenv, and I activate it whenever I want detection to work in my .vimrc. Moreover, if you change the system's dark/light mode while vim is running, you would have to either restart vim, or run :call SetBackground().

Get Vim plugins

Go to ~/.vim/pack/default/start (create this directory if it doesn't exist) and clone the git repositories of the plugins you need. You can see the list of plugins that I use at vimpackages.txt in my dotfiles. If you're using my dotfiles, you can run ./scripts/get_vim_packages.py. This will download and install the vim plugins from vimpackages.txt.

Most plugins will be ready to use as soon as you clone their repositories (remember to restart vim for the plugins to be loaded). The only exception in vimpackages.txt is coc.nvim, for which you must run

cd ~/.vim/pack/default/start/coc.nvim
npm ci

Autocomplete using CoC

I use coc.nvim for code auto-completion. You can view the key-mappings in .vimrc. coc.nvim comes with basic auto-complete, but for intelligent language-specific auto-complete, we need to install extensions for those languages. E.g., for typescript and python, we need the tsserver and pyright extensions, which can be installed by running the following in vim:

:CocInstall coc-tsserver coc-pyright

I'm using these extensions: coc-clangd, coc-css, coc-html, coc-htmldjango, coc-json, coc-pyright, coc-texlab, coc-tsserver.

Compatibility with Older Systems

I may want to use vim with my .vimrc on other computers, where vim may have fewer features and no plugins. Hence, I have used feature detection extensively in my .vimrc using has and exists. I tested my .vimrc on vim.tiny on Debian using Docker. Here are the steps for doing so.

  1. Install Docker: either manually, or using brew install --cask docker.
  2. Run the docker GUI application and follow the setup instructions. This starts the docker service.
  3. In terminal, run docker run -it -v ~/.vimrc:/root/.vimrc:ro debian:stable-slim bash. This
    1. Pulls the docker:stable-slim image from Docker Hub.
    2. Starts a container with ~/.vimrc mounted to /root/.vimrc in read-only mode (ro). This ensures that any changes to ~/.vimrc show up in /root/.vimrc on the container, but the container cannot modify the ~/.vimrc.
    3. Runs bash in an interactive TTY (-it).
  4. Now a different command-line prompt will appear, since we're inside bash in the container.
  5. We must now install vim.tiny. To do so, run apt update and then apt install vim.tiny.
  6. Now run vim.tiny and see if any errors show up. You can run vim.tiny --version to see what features are available.

Install Nginx and serve website mirrors

I use Nginx to serve static content. It's useful to access local websites that I downloaded or created.

Install and run Nginx

brew install nginx
nginx

Now go to http://localhost:8080. You should see a welcome page from Nginx.

Enable nginx autoindex

Go to /opt/homebrew/etc/nginx/nginx.conf and add autoindex on; to 'http > server > location /'. You may also wish to change the port from 8080 to something else by changing the listen value.

Then rename /opt/homebrew/var/www/index.html to /opt/homebrew/var/www/index.html~.

After making these changes, run nginx -s reload for the changes to take effect.

Visit http://localhost:8080 again. Now instead of seeing the welcome page, you should see the list of files in /opt/homebrew/var/www.

Optionally, if you want the index page to look pretty, you can use the ngx-fancyindex module. But it seemed a bit too difficult to configure. So I use the following string-replacement hack to inject my own CSS:

  1. Put style.css at /opt/homebrew/var/www/. You can put whatever CSS you want in style.css. You can see my style file in this gist.

  2. Add this to 'http > server > location /' in /opt/homebrew/etc/nginx/nginx.conf:

        sub_filter '<head><title>Index of' '<head>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="color-scheme" content="light dark" />
    <link rel="stylesheet" href="/style.css" />
    <title>Index of';
        sub_filter_once on;
    

Serve my websites with Nginx

I had backed up compressed archives of my websites to my external hard disk. I copied the websites from there, uncompressed them, and placed them in /opt/homebrew/var/www.

You can put symlinks in /opt/homebrew/var/www, but /opt/homebrew/var/www itself cannot be a symlink.

Security

Anyone on your network can see your files in /opt/homebrew/var/www, so you should be careful about what you put there to preserve your privacy.

You can set password authentication for Nginx, but if someone is eavesdropping, they can easily recover your password.

If you want to prevent others on your network from accessing the http server, you can restrict Nginx to work on localhost only. To do this, go to /opt/homebrew/etc/nginx/nginx.conf and change listen 8080; to listen localhost:8080;. This is somewhat secure, but not secure against a talented attacker (see https://security.stackexchange.com/q/86773).