Skip to main content

Command Palette

Search for a command to run...

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

Updated
12 min read
Boost Your Workflow: An Inside Look at My Time-Tested Dotfiles Setup

As a developer, nothing beats the feeling of a finely tuned workspace, where every tool, shortcut, and visual detail feels like a natural extension of your thought process. Setting up that perfect environment, though, is rarely straightforward. It’s a journey of trial and error, late-night tweaks, and the occasional frustration of a forgotten keybinding or a lost script that made everything just right. Like many of you, I’ve spent countless hours wrestling with new machine setups, trying to recreate the magic of a workflow that hums along effortlessly. That’s why I’ve poured years into building and refining my dotfiles repository, a living snapshot of how I work, available at github.com/prashantkoirala465/Config-Files.

In this post, I’m opening the hood on my dotfiles setup, sharing not just the configs themselves but the stories, decisions, and hard-earned lessons behind them. This isn’t a surface-level overview; it’s a detailed exploration of every file, folder, and choice that shapes my daily coding life. Whether you’re a newcomer starting your own dotfiles journey, a veteran developer curious about fresh tools, or simply someone who loves geeking out over configurations, I hope you’ll find something valuable here. Expect in-depth breakdowns, practical code snippets, personal anecdotes, comparisons to other approaches, and actionable tips to craft a setup that works for you. Let’s dive in.

Why Dotfiles Matter

Dotfiles, those unassuming configuration files tucked away with their telltale . prefix, are the quiet architects of a developer’s environment. They dictate everything from how your shell prompt looks to the behavior of your editor’s keybindings. For me, dotfiles are more than just settings; they’re a reflection of my approach to coding: prioritize efficiency, embrace modularity, and always keep refining.

My Dotfiles Origin Story

My dotfiles journey began out of necessity. Early in my career, setting up a new MacBook or Linux machine was a slog. I’d spend hours piecing together my ideal Neovim setup or tweaking an Alacritty theme to reduce eye strain, only to realize I couldn’t replicate it later. Switching jobs or hardware meant starting from scratch, and I’d inevitably forget some critical tweak. Frustrated, I decided to centralize my configurations in a Git repository with a few clear goals:

  • Consistency: Make my environment feel identical whether I’m on my MacBook, Arch Linux desktop, or a remote server.
  • Speed: Cut setup time from hours to minutes with a single git clone and a setup script.
  • Shareability: Open-source my configs to learn from others and give back to the community.
  • Control: Customize every tool to fit my workflow like a glove.

The Broader Dotfiles Landscape

Dotfiles are a universal practice, but every developer’s approach is unique. Some keep things lean with just a .bashrc or .vimrc, prioritizing portability. Others, like Zach Holman or Mathias Bynens, build intricate setups with custom scripts and integrations for tools like tmux or iTerm2. Then there are the aesthetic enthusiasts who craft visually stunning terminal and editor themes. My setup blends all three: it’s functional, performant, and easy on the eyes, drawing inspiration from communities like DotFiles.

What You’ll Take Away

By the end of this post, you’ll not only see what my dotfiles do but understand why I made each choice. I’ll break down my reasoning, compare my approach to alternatives, and share tips to help you build a setup that feels uniquely yours. Let’s start with the foundation: how my repository is organized.

Repository Structure: Built for Clarity and Flexibility

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

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 Layout?

Each tool gets its own dedicated folder, keeping things organized and making it easy to swap components. If I decide to switch from Alacritty to Kitty, for example, I can update just the alacritty/ folder without touching the rest. The README.md walks you through setup steps, and the MIT LICENSE ensures others can freely use or adapt my work.

How Others Organize Dotfiles

Some developers use a “bare” Git repository, tracking files directly in their home directory (~/.git). Others rely on tools like Stow to manage symlinks. I opted for a directory-based approach because it’s simple and pairs well with my setup script, which handles symlinking to the home directory automatically.

Tips for Your Repository

  • Document Clearly: A detailed README with setup instructions is non-negotiable.
  • Use Submodules: For external plugins, Git submodules keep everything in sync.
  • Commit Often: Regular backups prevent losing your tweaks.
  • Test Fresh: Periodically try your setup on a clean virtual machine to ensure it works seamlessly.

Window Management: Taming the Chaos with Aerospace

For someone juggling multiple projects—coding, debugging, writing—a good window manager is essential. My workflow thrives on keyboard-driven organization, and for years, I relied on Yabai, a tiling window manager for macOS. Its ability to snap windows into grids or stacks transformed how I multitasked. My yabairc was tuned for simplicity and speed:

#!/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 gave me a clean, tiled layout with subtle borders to highlight active windows. But as macOS tightened security with each update, Yabai required more manual tweaks to keep its scripting features running smoothly.

Enter Aerospace

In 2024, I switched to Aerospace, a polished alternative that builds on Yabai’s strengths. Its TOML-based configuration is more readable than Yabai’s shell scripts, and it feels smoother out of the box. 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' },
]

Aerospace’s stacking layout suits my preference for vertically organized windows, especially when editing multiple files in Neovim or Zed. The 18px gaps and 20px padding create a spacious workspace, and the Nordic-inspired colors add a subtle, professional touch.

Comparing Approaches

Many macOS users lean on native tools like Mission Control or apps like Rectangle. Linux developers often favor i3 or sway. Aerospace strikes a balance, offering tiling automation with enough flexibility for manual tweaks, making it ideal for developers who value both structure and control.

Window Management Tips

  • Try Different Layouts: Experiment with binary space partitioning versus stacking to find your flow.
  • Optimize Keybindings: Use intuitive shortcuts, like Vim-inspired h/j/k/l, for navigation.
  • Test Multi-Monitor: Make sure your config works across displays.
  • Document Choices: Note why you picked specific gaps or layouts for future tweaks.

Terminal Emulators: Where Commands Come to Life

The terminal is my control hub, whether I’m running scripts, managing Git, or connecting to a server. I need speed, reliability, and a touch of style. I rely on two emulators: Alacritty for its performance and WezTerm for its advanced features.

Alacritty: Built for Speed

Alacritty’s GPU acceleration makes it one of the fastest terminals out there. My alacritty.yml prioritizes clarity and minimalism:

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 easy to read, while the Catppuccin Mocha theme offers a high-contrast, soothing palette. A slight opacity adds a modern feel without compromising legibility.

WezTerm: The Feature-Packed Alternative

WezTerm excels for complex workflows, with Lua-based scripting and features like tabs and multiplexing that rival tmux. My wezterm.lua balances 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 ideal for long coding sessions, with background blur and opacity creating an immersive experience.

Alacritty vs. WezTerm

  • Alacritty: Perfect for lightweight tasks like SSH or quick scripts.
  • WezTerm: Shines for managing multiple projects with tabs or custom Lua scripts.

Some developers prefer iTerm2 for macOS integration or Kitty for its image protocol. Minimalists might use macOS’s default Terminal or xterm on Linux. My dual setup lets me switch based on the task, offering flexibility over a single-tool commitment.

Terminal Tips

  • Pick a Great Font: Nerd Fonts like Fira Code or MesloLGS support icons and ligatures.
  • Choose Comfortable Colors: Themes like Catppuccin reduce eye strain.
  • Automate Setup: Script your terminal installation and config deployment.
  • Master Your Tool: Explore Alacritty’s YAML or WezTerm’s Lua docs for hidden gems.

Editors: Where Code Meets Creativity

My editors are where I spend most of my time, so they need to be fast, flexible, and intuitive. I primarily use Neovim, with Zed as a secondary option for specific tasks.

Neovim: My Coding Sanctuary

Neovim’s speed and extensibility make it my go-to editor. My init.lua uses Lazy.nvim for plugin management, tailored for a modern, streamlined workflow:

-- 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 includes:

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

I opted for a custom config over distributions like NvChad to keep things lean and tailored.

Zed: A Modern Complement

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

{
  "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 collaboration features make it a great backup, especially for React and TypeScript projects.

Neovim vs. Zed

  • Neovim: Unrivaled for customization and terminal workflows.
  • Zed: Excels in GUI-based editing and team collaboration.

Editor Preferences

Many developers use VS Code for its plugins or JetBrains IDEs for robust projects. Vim enthusiasts might stick with vanilla Vim or LunarVim. My hybrid setup leverages Neovim’s power and Zed’s simplicity.

Editor Tips

  • Build Gradually: Add plugins one at a time to avoid config overload.
  • Master Shortcuts: Learn your editor’s keybindings to work faster.
  • Sync Settings: Use Git to keep configs consistent across devices.
  • Try New Tools: Experiment with editors like Zed or Helix to broaden your toolkit.

Keyboard Customization: Unlocking Efficiency with Karabiner

Karabiner-Elements transforms my MacBook’s keyboard into a productivity powerhouse. My favorite tweak maps Caps Lock to a Hyper Key (Cmd + Ctrl + Option + Shift) for endless shortcut possibilities:

{
  "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 lets me launch apps or scripts with a single key combo, saving countless keystrokes.

Why Karabiner?

Karabiner’s flexibility is unmatched on macOS, where keyboard customization is otherwise limited. It pairs perfectly with Aerospace’s bindings for a seamless workflow.

Linux users might use xmodmap or setxkbmap, while Windows developers lean on AutoHotkey. Some prefer hardware solutions like QMK keyboards. Karabiner offers a sweet spot for macOS users.

Keyboard Tips

  • Start Small: Remap one key to build familiarity.
  • Keep a Cheat Sheet: Document your mappings for reference.
  • Test Thoroughly: Ensure remaps don’t conflict with existing shortcuts.
  • Share Your Setup: Publish your rules to inspire others.

My Development Philosophy

My dotfiles reflect how I approach coding:

  • Modularity: Separate configs for each tool simplify maintenance.
  • Performance: Fast tools like Alacritty and Neovim keep me in flow.
  • Aesthetics: Cohesive themes reduce visual clutter.
  • Simplicity: Avoid unnecessary plugins to stay focused.
  • Iteration: Constantly refine based on new tools or workflows.

This mindset comes from years of experimenting, failing, and learning—whether switching from Yabai to Aerospace or adding Zed to my toolkit.

Practical Tips for Your Dotfiles

Here’s what I’ve learned over the years:

  1. Automate Setup: Create a setup.sh script to handle symlinking and dependencies.
  2. Version Everything: Use Git to track and revert changes.
  3. Steal Ideas: Browse GitHub for inspiration from other developers’ dotfiles.
  4. Stay Lean: Only include configs you actively use.
  5. Test Across Systems: Ensure compatibility with macOS, Linux, or WSL.

Resources to Explore

Wrapping Up: Make Your Dotfiles Your Own

My dotfiles are more than code; they’re a story of my growth as a developer, from my first .bashrc to my current Aerospace and Neovim setups. Each tweak reflects a problem solved or a lesson learned. Sharing them isn’t about bragging—it’s about sparking ideas and encouraging you to take charge of your tools.

I hope this deep dive into my Config-Files repository has inspired you, whether it’s to fork my repo, try a new config, or share your own dotfiles story. Drop me a message or comment with your thoughts, and let’s keep the conversation going.

Thanks for reading, and happy coding!