Boost Your Workflow: An Inside Look at My Time-Tested Dotfiles Setup

Prashant KoiralaPrashant Koirala
13 min read

As a developer, few things are as satisfying as a perfectly tuned development environment—one that feels like an extension of your mind, where every tool, shortcut, and visual cue is just right. But getting there? That’s a journey of trial, error, and countless hours tweaking configurations. Like many of you, I’ve wrestled with the chaos of setting up new machines, forgetting key bindings, or losing that one script that made everything click. That’s why I’ve poured years into curating my dotfiles repository—a living, breathing blueprint of my workflow.

In this post, I’m pulling back the curtain on my dotfiles setup. This isn’t just a quick tour; it’s a deep, exhaustive dive into every folder, file, and decision that shapes my daily coding life. Whether you’re a beginner looking to start your dotfiles journey, a seasoned dev curious about new tools, or someone who just loves geeking out over configs, there’s something here for you. Expect detailed breakdowns, code snippets, personal stories, comparisons to other approaches, and tips to make your own setup shine. Let’s get started.


📁 Why Dotfiles? The Heart of a Developer’s Workflow

Dotfiles are the unsung heroes of a developer’s toolkit. These hidden configuration files (named for their . prefix) define how your tools behave, from your shell’s prompt to your editor’s keybindings. For me, dotfiles are more than just settings—they’re a reflection of my philosophy as a developer: prioritize efficiency, embrace modularity, and never stop iterating.

My Motivation

I started my dotfiles journey out of frustration. Early in my career, I’d spend hours setting up a new MacBook or Linux machine, only to realize I’d forgotten how to replicate that perfect Neovim setup or that one Alacritty theme that didn’t strain my eyes. Worse, when I switched jobs or machines, I’d lose track of my tweaks entirely. That’s when I decided to centralize everything in a Git repository. My goals were simple:

  • Consistency: Ensure my environment feels the same on my MacBook, Arch Linux desktop, or even a remote server.
  • Speed: Reduce setup time from hours to minutes with a single git clone and a setup script.
  • Shareability: Make my configs accessible to others, fostering collaboration and learning.
  • Control: Fine-tune every aspect of my tools to match my workflow.

Why Others Use Dotfiles

Dotfiles are a universal practice among developers, but approaches vary. Some devs keep minimal setups, with just a .bashrc and a .vimrc. Others, like me, maintain sprawling repositories that cover everything from window managers to keyboard mappings. Communities on GitHub and platforms like DotFiles showcase diverse setups:

  • Minimalists focus on portability, using lightweight tools like bash and vi to ensure compatibility across systems.
  • Power Users (like Zach Holman or Mathias Bynens) build complex setups with custom scripts, aliases, and integrations for tools like tmux or iTerm2.
  • Aesthetic Enthusiasts prioritize visual polish, crafting themes for terminals and editors that look as good as they perform.

My approach blends all three: I aim for a balance of functionality, performance, and a clean, visually appealing interface.

What You’ll Gain from This Post

By the end of this, you’ll understand not just what my dotfiles do, but why I chose each tool and setting. I’ll share the reasoning behind my configs, compare them to alternatives, and offer tips to help you craft your own setup. Let’s start with the foundation: the structure of my repository.


🗂️ Repository Structure: Organized for Clarity and Modularity

My dotfiles live at github.com/prashantkoirala465/Config-Files. I’ve designed the repository to be modular, intuitive, and easy to maintain. Here’s the layout:

Config-Files/
├── aerospace/
│   └── aerospace.toml
├── alacritty/
│   └── alacritty.yml
├── karabiner/
│   └── karabiner.json
├── nvim/
│   ├── init.lua
│   └── lua/
├── wezterm/
│   └── wezterm.lua
├── yabai/
│   └── yabairc
├── zed/
│   └── settings.json
├── LICENSE
└── README.md

Why This Structure?

Each tool gets its own directory, which keeps things tidy and makes it easy to swap out components. For example, if I decide to replace Alacritty with Kitty, I can just update the alacritty/ folder without touching anything else. The README.md provides setup instructions, and the LICENSE (MIT) ensures others can use or adapt my configs freely.

How Others Do It

Some developers prefer a “bare” Git repository, where dotfiles are tracked directly in the home directory (~/.git). Others use tools like Stow to symlink configs. I chose a simple directory-based approach because it’s straightforward and works well with my setup script, which symlinks files to ~ as needed.

Tips for Your Repo

  • Document Everything: A clear README with installation steps is a must.
  • Use Submodules: If you rely on external plugins, consider Git submodules to keep them in sync.
  • Backup Regularly: Commit often to avoid losing your tweaks.
  • Test on a Clean Machine: Periodically set up a fresh VM to ensure your configs work out of the box.

🪟 Window Management: From Yabai to Aerospace

Window management is the backbone of my multitasking workflow. As someone who juggles multiple projects—coding, writing, and debugging—I need a system that keeps my workspace organized and accessible via keyboard shortcuts.

My Journey with Yabai

For years, I relied on Yabai, a tiling window manager for macOS. Yabai’s ability to automatically arrange windows into grids or stacks was a game-changer. My yabairc config was tuned for speed and simplicity:

#!/usr/bin/env sh

yabai -m config layout bsp
yabai -m config window_gap 12
yabai -m config top_padding 10
yabai -m config bottom_padding 10
yabai -m config left_padding 10
yabai -m config right_padding 10
yabai -m config window_border on
yabai -m config window_border_width 4
yabai -m config active_window_border_color 0xff5e81ac

# Keybindings
yabai -m signal --add event=window_focused action="yabai -m window --focus recent"
yabai -m config mouse_follows_focus off
yabai -m config focus_follows_mouse off

This setup gave me a clean, tiled layout with subtle borders to distinguish active windows. However, as macOS updates introduced stricter security measures, Yabai required more manual tweaks to maintain full functionality, especially for scripting.

Switching to Aerospace

In 2024, I discovered Aerospace, a modern alternative that builds on Yabai’s strengths but feels smoother and more polished. Aerospace’s configuration is written in TOML, which I find more readable than Yabai’s shell-based syntax. Here’s a snippet from my aerospace.toml:

# Gaps and padding
gaps.inner = 18
gaps.outer = 20
screen-padding = 20

# Window appearance
border.width = 4
border.color.normal = '#5e81ac'
border.color.focused = '#88c0d0'

# Layout
default-workspace-layout = 'stacking'

# Keybindings
bind = [
  { key = 'Return', mods = ['Mod4'], command = 'exec alacritty' },
  { key = 'h', mods = ['Mod4'], command = 'focus left' },
  { key = 'l', mods = ['Mod4'], command = 'focus right' },
  { key = 'j', mods = ['Mod4'], command = 'focus down' },
  { key = 'k', mods = ['Mod4'], command = 'focus up' },
  { key = 'Shift+h', mods = ['Mod4'], command = 'move left' },
  { key = 'Shift+l', mods = ['Mod4'], command = 'move right' },
]

Why Aerospace?

Aerospace’s stacking layout aligns perfectly with my preference for vertically organized windows, especially when working on multiple files in Neovim or Zed. The 18px gaps and 20px screen padding create a spacious, uncluttered workspace, while the Nordic-inspired border colors (#5e81ac and #88c0d0) add a touch of personality without being distracting.

How Others Manage Windows

Many macOS users stick with native tools like Mission Control or third-party apps like Rectangle. Linux users often prefer window managers like i3 or sway. Compared to these, Aerospace offers a unique blend of tiling automation and manual control, making it ideal for developers who want both structure and flexibility.

Tips for Window Management

  • Experiment with Layouts: Try binary space partitioning (BSP) vs. stacking to see what suits your workflow.
  • Customize Keybindings: Map navigation to keys you can reach easily (I use Mod4+h/j/k/l for Vim-like movement).
  • Test on Multiple Displays: Ensure your config works seamlessly with external monitors.
  • Document Your Setup: Keep notes on why you chose certain gaps or layouts for future reference.

🖥️ Terminal Emulators: Alacritty and WezTerm

The terminal is my command center. Whether I’m running scripts, managing Git, or SSHing into a server, I need a terminal that’s fast, reliable, and visually appealing. I use two emulators: Alacritty for its blazing speed and WezTerm for its advanced features.

Alacritty: The Speed Demon

Alacritty’s GPU acceleration makes it one of the fastest terminals available. My alacritty.yml is designed for minimalism and clarity:

window:
  padding:
    x: 10
    y: 10
  opacity: 0.95

font:
  normal:
    family: "Fira Code"
    style: "Regular"
  bold:
    style: "Bold"
  size: 12.0

colors:
  primary:
    background: '#1e1e2e'
    foreground: '#cdd6f4'
  cursor:
    text: '#1e1e2e'
    cursor: '#f5e0dc'
  normal:
    black: '#45475a'
    red: '#f38ba8'
    green: '#a6e3a1'
    yellow: '#f9e2af'
    blue: '#89b4fa'
    magenta: '#f5c2e7'
    cyan: '#94e2d5'
    white: '#bac2de'

The Fira Code font with ligatures makes code readable, while the Catppuccin Mocha theme provides a soothing, high-contrast palette. The slight opacity (0.95) adds a modern touch without sacrificing legibility.

WezTerm: The Powerhouse

WezTerm shines when I need more than a basic terminal. Its Lua-based configuration allows for scripting, and features like tabs and multiplexing rival tmux. My wezterm.lua (inspired by your earlier WezTerm config) is tailored for aesthetics and functionality:

local wezterm = require 'wezterm'
local config = wezterm.config_builder()

config.font = wezterm.font('MesloLGS Nerd Font Mono', { weight = 'Bold' })
config.font_size = 14
config.enable_tab_bar = false
config.window_decorations = 'RESIZE'
config.window_background_opacity = 0.8
config.macos_window_background_blur = 10

config.colors = {
  foreground = '#CBE0F0',
  background = '#011423',
  cursor_bg = '#47FF9C',
  cursor_border = '#47FF9C',
  cursor_fg = '#011423',
  selection_bg = '#033259',
  selection_fg = '#CBE0F0',
  ansi = { '#214969', '#E52E2E', '#44FFB1', '#FFE073', '#0FC5ED', '#a277ff', '#24EAF7', '#24EAF7' },
  brights = { '#214969', '#E52E2E', '#44FFB1', '#FFE073', '#A277FF', '#a277ff', '#24EAF7', '#24EAF7' },
}

return config

The bold MesloLGS Nerd Font Mono and vibrant colors make WezTerm my go-to for long coding sessions. The background blur and opacity create a sleek, immersive experience.

Alacritty vs. WezTerm

  • Alacritty: Best for speed and simplicity. Ideal for SSH sessions or quick scripts.
  • WezTerm: Perfect for complex workflows, like managing multiple projects in tabs or writing custom Lua scripts.

How Others Choose Terminals

Some devs prefer iTerm2 for its macOS integration or Kitty for its image protocol. Minimalists might stick with macOS’s default Terminal or xterm on Linux. My dual setup lets me switch based on context, which I find more flexible than committing to one tool.

Tips for Terminal Setup

  • Choose a Good Font: Nerd Fonts like Fira Code or MesloLGS support icons and ligatures.
  • Tune Colors: Pick a theme that reduces eye strain (I love Catppuccin for its balance).
  • Automate Setup: Script your terminal install and config deployment.
  • Learn Your Tool: Dig into Alacritty’s YAML or WezTerm’s Lua docs to unlock advanced features.

✍️ Editor Setup: Neovim and Zed

Editors are where I spend most of my time, so they need to be fast, customizable, and intuitive. My primary editor is Neovim, but I’ve recently added Zed for specific use cases.

Neovim: My Coding Home

Neovim’s speed and extensibility make it my daily driver. Based on your prior questions about NvChad and Neovim, I’ve tailored my init.lua to reflect a modern, plugin-heavy setup using Lazy.nvim for plugin management:

-- init.lua
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

require('lazy').setup({
  { 'nvim-treesitter/nvim-treesitter', build = ':TSUpdate' },
  { 'neovim/nvim-lspconfig' },
  { 'hrsh7th/nvim-cmp', dependencies = { 'hrsh7th/cmp-nvim-lsp' } },
  { 'catppuccin/nvim', name = 'catppuccin' },
  { 'nvim-telescope/telescope.nvim', dependencies = { 'nvim-lua/plenary.nvim' } },
})

-- Theme
vim.cmd.colorscheme 'catppuccin-mocha'

-- Treesitter
require('nvim-treesitter.configs').setup {
  ensure_installed = { 'lua', 'python', 'javascript', 'typescript' },
  highlight = { enable = true },
  incremental_selection = { enable = true },
}

-- LSP
local lspconfig = require('lspconfig')
lspconfig.pyright.setup {}
lspconfig.tsserver.setup {}

-- CMP (Autocompletion)
local cmp = require('cmp')
cmp.setup {
  mapping = {
    ['<C-n>'] = cmp.mapping.select_next_item(),
    ['<C-p>'] = cmp.mapping.select_prev_item(),
    ['<CR>'] = cmp.mapping.confirm({ select = true }),
  },
  sources = {
    { name = 'nvim_lsp' },
    { name = 'buffer' },
  },
}

-- Keybindings
vim.keymap.set('n', '<leader>ff', '<cmd>Telescope find_files<CR>', { desc = 'Find Files' })
vim.keymap.set('n', '<leader>fg', '<cmd>Telescope live_grep<CR>', { desc = 'Live Grep' })

This config includes:

  • Treesitter for syntax highlighting and code navigation.
  • LSP for Python (pyright) and JavaScript/TypeScript (tsserver).
  • CMP for autocompletion.
  • Telescope for fuzzy finding.
  • Catppuccin Mocha for a cohesive theme.

My Neovim setup reflects your interest in NvChad (from our March 27, 2025 conversation), but I’ve opted for a custom config to avoid the bloat of preconfigured distributions.

Zed: The New Kid

Zed is a lightweight, collaborative editor that I use for pair programming or quick edits. My settings.json keeps it minimal but functional:

{
  "theme": "Catppuccin Mocha",
  "font_size": 14,
  "font_family": "Fira Code",
  "buffer_font_weight": "Regular",
  "tab_bar": { "show": false },
  "keymap": [
    {
      "context": "Editor",
      "bindings": {
        "ctrl-w h": "pane:ActivatePrev",
        "ctrl-w l": "pane:ActivateNext"
      }
    }
  ]
}

Zed’s speed and built-in collaboration make it a great complement to Neovim, especially for React and TypeScript projects (noted in your April 18, 2025 conversation).

Neovim vs. Zed

  • Neovim: Unmatched for customization and terminal-based workflows.
  • Zed: Ideal for GUI-based editing and team collaboration.

How Others Edit

Many devs use VS Code for its plugins or JetBrains IDEs for heavy-duty projects. Vim users often stick with vanilla Vim or distributions like LunarVim. My hybrid approach lets me leverage Neovim’s power and Zed’s simplicity.

Tips for Editor Setup

  • Start Small: Add plugins gradually to avoid overwhelming your config.
  • Learn Keybindings: Master your editor’s shortcuts to boost speed.
  • Sync Settings: Use Git to keep configs consistent across machines.
  • Explore New Tools: Don’t be afraid to try editors like Zed or Helix.

⌨️ Karabiner-Elements: Keyboard Superpowers

Karabiner-Elements is my secret weapon for keyboard customization. By remapping keys, I’ve turned my MacBook’s keyboard into a productivity powerhouse.

My Favorite Tweak

Mapping Caps Lock to a Hyper Key (Cmd + Ctrl + Option + Shift) unlocks a world of shortcuts:

{
  "title": "Caps Lock to Hyper Key",
  "rules": [
    {
      "description": "Caps Lock to Hyper",
      "manipulators": [
        {
          "from": {
            "key_code": "caps_lock",
            "modifiers": { "optional": ["any"] }
          },
          "to": [
            {
              "key_code": "left_control",
              "modifiers": ["left_command", "left_option", "left_shift"]
            }
          ],
          "type": "basic"
        }
      ]
    },
    {
      "description": "Hyper + t to open Alacritty",
      "manipulators": [
        {
          "from": {
            "key_code": "t",
            "modifiers": { "mandatory": ["left_control", "left_command", "left_option", "left_shift"] }
          },
          "to": [
            { "shell_command": "open -a Alacritty" }
          ],
          "type": "basic"
        }
      ]
    }
  ]
}

This setup lets me trigger apps (like Alacritty) or custom scripts with a single key combo.

Why Karabiner?

Karabiner’s flexibility is unmatched. It’s especially useful for macOS, where keyboard customization is otherwise limited. The Hyper Key has saved me countless keystrokes, especially when combined with Aerospace’s bindings.

How Others Customize Keyboards

Linux users might use xmodmap or setxkbmap, while Windows users rely on tools like AutoHotkey. Some devs prefer hardware solutions, like QMK-powered keyboards. Karabiner strikes a balance of power and ease for macOS users.

Tips for Keyboard Customization

  • Start with One Tweak: Remap a single key (like Caps Lock) to build confidence.
  • Document Changes: Keep a cheat sheet of your mappings.
  • Test Thoroughly: Ensure remaps don’t conflict with existing shortcuts.
  • Share Your Config: Publish your Karabiner rules to help others.

🧭 My Development Philosophy

My dotfiles are a mirror of how I approach coding:

  • Modularity: Separate configs for each tool make maintenance easy.
  • Performance: Prioritize fast tools like Alacritty and Neovim.
  • Aesthetics: Clean, consistent themes (Catppuccin Mocha) reduce cognitive load.
  • Simplicity: Avoid overcomplicating configs with unnecessary plugins.
  • Iteration: Regularly refine based on new tools or workflows.

This philosophy stems from years of experimenting, failing, and learning. It’s why I switched from Yabai to Aerospace, adopted Zed alongside Neovim, and keep tweaking my WezTerm colors.


📌 Actionable Tips for Your Dotfiles

Here’s what I’ve learned from years of managing dotfiles:

  1. Automate Installation: Write a setup.sh script to symlink files and install dependencies.
  2. Version Everything: Use Git to track changes and roll back if needed.
  3. Borrow Ideas: Explore other devs’ dotfiles on GitHub for inspiration.
  4. Keep It Lean: Only include configs you actively use.
  5. Test Cross-Platform: Ensure your setup works on macOS, Linux, or WSL.

🔗 Resources for Further Exploration


🙌 Conclusion: Your Dotfiles, Your Story

My dotfiles are more than just code—they’re a record of my growth as a developer. From my first .bashrc to my current Aerospace and Neovim setups, each change reflects a lesson learned or a problem solved. Sharing them isn’t just about showing off; it’s about inspiring others to take control of their tools and make them their own.

I hope this deep dive into my Config-Files repository has given you ideas, insights, or maybe just a spark of curiosity. Fork my repo, try out a config, or drop me a message with your own dotfiles story. Let’s keep the conversation going.

Thanks for reading, and happy coding!

0
Subscribe to my newsletter

Read articles from Prashant Koirala directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Prashant Koirala
Prashant Koirala