DEV Community

Cover image for I Spent Months Perfecting My Dotfiles So You Don't Have To — Here's Everything Inside
Gouranga Das Samrat
Gouranga Das Samrat

Posted on

I Spent Months Perfecting My Dotfiles So You Don't Have To — Here's Everything Inside

"Your terminal is where you live. Make it beautiful."

Every developer has a dotfiles repo. Most of them are a pile of Gists half-remembered from 2019, a .bashrc that's been copy-pasted between machines for years, and a VS Code settings file that's one merge conflict away from catastrophe.

This one is different. I want to walk you through every real, working piece of gourangadassamrat/dotfiles — not just the highlights reel, but the actual code, the design decisions, and the parts that took the most iteration to get right.


⚡ The Bootstrap: One Command, Full Environment

git clone https://github.com/GourangaDasSamrat/dotfiles.git ~/dotfiles
cd ~/dotfiles/scripts && ./install.sh
Enter fullscreen mode Exit fullscreen mode

install.sh calls every module in lib/ in order. If you want to pick and choose:

./setup.sh
Enter fullscreen mode Exit fullscreen mode

This drops you into a numbered menu of every .sh file found recursively in scripts/ (excluding itself and utils/). You pick by number — or type all. No YAML, no external tooling, just bash.

The brains behind cross-platform compatibility live in utils/detect.sh, which determines your OS, available package manager (apt, brew, pacman), and sudo access. Every script in lib/ sources this. The result: the same lib/packages.sh that runs apt install on Ubuntu runs brew install on macOS, transparently.

Everything is symlinked into place using GNU Stow — one call to stow <module> and the directory structure inside that module folder maps directly onto $HOME. Zero manual path management.


🐚 The Shell: Nothing Is Left Unquestioned

The zsh config lives under zsh/.config/zsh/ and is split into core/, functions/, plugins/, and user/. Here's what's actually in each.

core/

colors.zsh — Defines COLOR_HEADER, COLOR_SUCCESS, COLOR_ERROR, COLOR_WARNING, COLOR_TEXT, COLOR_CURSOR, COLOR_BORDER, COLOR_NORMAL, COLOR_RESET as ANSI escape sequences. Every function and alias in the repo uses these — the whole terminal has a consistent color palette, not just a theme.

env.zshDOTFILES path, GOPATH, editor set to nvim, XDG_* base dirs.

history.zshHISTSIZE, SAVEHIST, setopt SHARE_HISTORY. Done correctly.

user/aliases.zsh

A few highlights that deserve explanation:

eza aliases are conditional. They only activate if eza is actually in $PATH:

if (($+commands[eza])); then
  alias ls='eza --color=always --long --git --no-filesize --icons=always --no-time --no-user --no-permissions'
  alias lt='eza --tree -a -I "node_modules|.git"'
fi
Enter fullscreen mode Exit fullscreen mode

VS Code profile switching is handled gracefully across code, code-oss, and code-insiders. It detects which binary exists and aliases it correctly, then layers profile shortcuts on top — only if code resolves at all:

alias code-b='code --profile "Backend Dev"'
alias code-f='code --profile "Frontend Dev"'
alias code-g='code --profile "Go Dev"'
alias code-c='code --profile "C/C++ Dev"'
alias code-d='code --profile "Database Dev"'
alias code-r='code --profile "Rust Dev"'
alias code-l='code --profile "Lua Dev"'
alias code-p='code --profile "Python Dev"'
alias code-w='code --profile "Wiki Dev"'
Enter fullscreen mode Exit fullscreen mode

Nine profiles. One alias each. Termux support is included too — for those of us who develop on Android:

if [[ -d /data/data/com.termux ]]; then
  alias debian="TERM='xterm-256color' proot-distro login debian --user gouranga"
fi
Enter fullscreen mode Exit fullscreen mode

🔧 user/overrides.zsh: mkdir and rm Reimagined

These two rewrites are among my favorite parts of the whole repo.

mkdir — Git-aware directory creation

When you create a single directory, an interactive prompt appears — no fzf, just pure terminal keyboard input with read -k1 and ANSI escape sequences for arrow key detection:

  ◆  Initialize git repository in 'myproject'?
     Yes  › No
Enter fullscreen mode Exit fullscreen mode

Use left/right arrows to toggle, Enter to confirm. If you say Yes:

cd "$1"
git init -q
echo "# $1" > README.md
git add .
git commit -m "chore: initialize repository with README" -q
Enter fullscreen mode Exit fullscreen mode

It quietly creates the repo, writes a README, and makes the first conventional commit — all in one mkdir call. Creating multiple directories skips the prompt entirely.

rm — Confirm before you destroy

Overrides rm to first show you exactly what you're deleting (with 📁/📄 icons for directories vs files), then presents the same arrow-key Yes/No interface. Flags like -rf still pass through after confirmation. Both overrides use tput civis to hide the cursor during interaction and trap 'tput cnorm' EXIT to restore it on exit or Ctrl+C.


🔌 plugins/fzf.zsh: fzf Done Properly

The fzf config ships two themes — Dracula and Catppuccin — as named functions that can be swapped by calling them:

_fzf_theme_dracula()    # active by default
_fzf_theme_catppuccin() # call to switch
Enter fullscreen mode Exit fullscreen mode

Each sets the full 8-color FZF_DEFAULT_OPTS palette: fg, bg, hl, info, prompt, pointer, marker, spinner, header, border.

Search uses fd instead of find:

export FZF_DEFAULT_COMMAND="fd --hidden --strip-cwd-prefix --exclude .git"
Enter fullscreen mode Exit fullscreen mode

Tab completion previews use eza for directories and bat for files. Context-aware completion via _fzf_comprun routes different commands to appropriate previews — cd gets a directory tree, ssh gets dig {}, export/unset evaluates the variable value.


📡 functions/ — Custom Commands Written From Scratch

apireq — A Full API Client in Your Terminal

apireq is the most complex function in the repo. It's a complete interactive HTTP client powered by fzf, written entirely in zsh. No dependencies beyond curl, fzf, bat, jq, and optionally python3 for JSON validation.

Flow:

  1. Choose: Create new request or Load saved .http file
  2. Pick HTTP method via fzf
  3. Enter URL
  4. Multi-select with Space: Auth · Custom Headers · Query Params · Request Body
  5. Auth: Bearer Token or Basic Auth (password via read -rs, no echo to terminal)
  6. Body: JSON (validated via python3 -m json.tool), Raw Text, Form Data (urlencoded), or Multipart (supports file upload via key=@/path/to/file)
  7. Output: auto (bat for headers + jq for JSON body), bat, jq, or raw
  8. Save as .http file with an fzf folder picker that browses $HOME

The .http format is real — saved requests can be loaded, inspected in a preview pane, and optionally modified field-by-field (method, URL, headers, body) before re-sending.

archive.zsh — Universal Pack/Unpack

extract() handles tar.*, tgz, tbz2, txz, and zip via a clean case statement with colorized output using the colors.zsh palette.

compress() presents an fzf menu of 7 formats with human descriptions:

tar.gz   → Good balance, common
tar.bz2  → Better compression, slower
tar.xz   → Best compression, slowest
zip      → Cross-platform
7z       → High compression
gz       → Single file only
bz2      → Single file only
Enter fullscreen mode Exit fullscreen mode

.gz and .bz2 correctly bail out with an error if you try to compress a directory.

network.zsh — Three Genuinely Useful Web Commands

All three are conditionally defined — they only load if their dependencies exist at shell startup.

isup [url] — Uses httpie with -F (follow redirects) and -p=h (headers only) to check site status. Displays ✔ ONLINE [200 OK], ⚠ ISSUE [301], or ✘ OFFLINE. Extracts and shows the Server: header value.

myip — Fetches ipinfo.io via httpie, parses the JSON with grep -Po, and prints IP address, city + region, and ISP — all styled with the color palette.

inspect [url] — Fetches response headers filtered to security-relevant ones (Server, Content-Type, X-Powered-By, Cache-Control, Strict-Transport-Security), then runs openssl s_client to show SSL cert validity dates. Only defined when both http and openssl are available.

utils.zsh — The Everyday Toolkit

serve [port] — Python HTTP server with a full validation loop: ensures the port is numeric, 1–65535, and not already bound (lsof -Pi :$port -sTCP:LISTEN). Prompts for another port if occupied.

timer <duration> — Accepts raw seconds, 1h30m, 45m20s, or any combination. Renders a full-screen countdown: color-coded time display (green → yellow → red as it runs out), a 40-char block progress bar (█░), a braille spinner, and elapsed time. On completion: terminal bell (\a), notify-send desktop notification, and system audio via paplay or aplay if available.

backup <path> — One command creates folder_backup_20260429_142301.tar.gz with a precise timestamp.

weather [city] — Fetches wttr.in/<city>?0mFq&format=v2 — the v2 format gives a full readable weather card. Defaults to Khulna.

t <command> — Prefixes every output line from any command with [YYYY-MM-DD HH:MM:SS] via moreutils' ts. Uses stdbuf -oL -eL for real-time line-buffered output and FORCE_COLOR=3 to preserve colors in piped output. Defined only if ts is installed.

expose [port] [ttl] — Wraps slim share with the same port validation as serve. Exposes localhost to the internet. Optional ttl argument passed through. Defined only if slim is installed.

security.zsh — Auto-Locking GPG

Spawns a background daemon named gpg-auto-lock-loop via exec -a (so it's grep-able by name) that fires gpg-connect-agent reloadagent /bye every 900 seconds — locking your GPG key cache. Checks for an existing instance before spawning so sourcing your config multiple times never creates duplicates.

whois.zsh — Filtered WHOIS Lookup

Defines a server map with keys dp (whois.digitalplat.org), iana (whois.iana.org), and com (whois.verisign-grs.com):

dzw example.com           # default server
dzw dp example.com        # via digitalplat.org
dzw iana example.com      # via IANA
Enter fullscreen mode Exit fullscreen mode

Output is filtered with grep -E to useful fields only — Domain Name, Registrar, dates, Name Servers, Status — stripping all legal boilerplate.

chpwd.zsh — Smart Directory Change Hooks

Three functions registered via add-zsh-hook chpwd:

_manage_python_venv — Checks for .venv, venv, or .env directories. Auto-activates on cd in, auto-deactivates on cd out.

_list_project_tools — On every cd, detects and lists available automation targets. justfilejust --list. Makefile → awk-parsed targets. package.jsonjq -r '.scripts | keys[]'. docker-compose.ymldocker compose ps --services.

_auto_nvm_use — Reads .nvmrc and calls nvm use automatically.

plugins/pass.zsh — Encrypted Secret Management

env-save <file> <pass-path> — Reads a .env file and pipes it into pass insert -m at any path in the password store. Multi-line safe.

env-load <pass-path> [filename] — Pulls secrets out of pass into a local file (defaults to .env). Verifies the path exists before writing. Prints line count on success.


🪟 tmux: Live Weather in the Status Bar

The tmux config uses Catppuccin macchiato with rounded window separators and status bar at the top, updating every second.

The live weather widget:

set -ag status-right "#[fg=#b7bdf8,bg=#24273a] #[fg=#24273a,bg=#b7bdf8,bold]#(curl -s 'wttr.in/Khulna?format=%%c%%t' | tr -d '+')#[fg=#b7bdf8,bg=#24273a] "
Enter fullscreen mode Exit fullscreen mode

This fetches the current condition icon and temperature from wttr.in every second. tr -d '+' strips the leading + from positive temperatures.

Key bindings:

Prefix:         Ctrl+A
Splits:         | horizontal · - vertical (opens at current path)
Pane nav:       h·j·k·l (Vim) or Alt+Arrow (no prefix)
Window nav:     Alt+1–5 (no prefix needed)
Window reorder: < and > to swap left/right
Resize:         Prefix + H/J/K/L (repeatable with -r)
Zoom pane:      Prefix + m
Enter fullscreen mode Exit fullscreen mode

Persistence: tmux-resurrect + tmux-continuum auto-save every 5 minutes (@continuum-save-interval '5'), restore on server start (@continuum-restore 'on'), and capture pane contents (@resurrect-capture-pane-contents 'on').


🖥️ VS Code: Nine Profiles, Every Extension Documented

The docs/vscode/vscode-extensions.md documents every extension per profile:

Profile Formatter Key Extensions
Default Dracula, Error Lens, GitLens, Code Spell Checker, Commit Sage, Todo Tree
Frontend Prettier + ESLint Live Server, Pretty TS Errors, Tailwind IntelliSense
Backend Prettier + ESLint Thunder Client, Prisma, SQLTools
C/C++ clangd clangd, Code Runner
Go gopls + goimports Go (official), Code Runner
Database prettier-sql Prettier SQL VSCode, SQLTools
Rust rust-analyzer rust-analyzer, Code Runner
Lua sumneko Lua, Code Runner
Wiki Prettier Prettier

Font stack: Operator Mono (italic keywords + ligatures) → Cartograph CF → JetBrains Mono.

Custom snippets shipped: cpp.json (competitive programming main, LeetCode template), go.json (main, package, iferr, interface), react-components.code-snippets, clang-format.code-snippets.


✏️ Neovim: lazy.nvim + Custom Dashboard

Managed by lazy.nvim. Plugins:

  • Mofiqul/dracula.nvim — Dracula with italic_comment = true
  • nvim-lualine/lualine.nvim — statusline with dracula-nvim theme
  • windwp/nvim-autopairs — auto-close brackets on InsertEnter
  • folke/todo-comments.nvim — highlights TODO:, FIXME:, NOTE: etc.
  • rhysd/committia.vim — splits the commit window into diff + message panes
  • lewis6991/gitsigns.nvim — git diff signs in the gutter
  • goolord/alpha-nvim — ASCII NEOVIM banner dashboard with New File, File Browser, and Quit shortcuts

Options set in one compact idiomatic block: line numbers, cursorline, 2-space tabs, smart case search, clipboard = "unnamedplus", persistent undo, no swapfile, trailing space and tab indicators.

A gitcommit FileType autocmd enables spell and sets textwidth=72 — matching the 72-char limit the git hook warns about.


🔧 Git: GPG Signing + Hooks That Apply Everywhere

.gitconfig

All commits are GPG-signed by default. core.hooksPath = ~/.git-hooks redirects hooks globally — every repository on the machine gets these hooks automatically without any per-repo setup.

Useful aliases:

git lg         # color graph log with relative time
git today      # commits since midnight with [HH:MM AM/PM] timestamps
git yesterday  # yesterday's commits
git mine       # your commits only across all branches
git last       # full detail: hash, author, date, full message
git undo       # soft reset HEAD~1
git unstage    # reset HEAD --
git el         # dump log to git_history.txt
Enter fullscreen mode Exit fullscreen mode

commit-msg hook

Validates the Conventional Commits spec: type(scope): subject. Skips merge commits (^Merge) and revert commits (^Revert). Valid types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert. Warns (non-blocking) if the subject line exceeds 72 characters.

pre-push hook

Sources ~/.zsh_secrets and checks for GIT_PUSH_PASS. If set, prompts for a passphrase via /dev/tty with stty -echo (no terminal echo). Push proceeds only on match. A lightweight push authorization layer without external tooling.


📊 GitHub CLI: Contribution Analytics in the Terminal

gh/.config/gh/config.yml ships a full suite of GraphQL-powered gh aliases with ANSI color formatting baked into the --jq expressions:

Current activity:

gh today              # every commit with [HH:MM] timestamps, all repos
gh today-summary      # repo-by-repo breakdown + total count
gh today-stats        # commits, PRs, issues, private contributions
gh this-month-summary # monthly breakdown via GraphQL (handles 1000+ commits)
gh this-year-summary  # year breakdown sorted by repo
gh this-year-languages # top 5 languages by bytes committed this year
gh streak             # current and longest commit streak
Enter fullscreen mode Exit fullscreen mode

Historical lookups:

gh yesterday           # prior day commits with timestamps
gh last-month-summary  # prior month breakdown
gh last-year-languages # top 5 languages in previous year
Enter fullscreen mode Exit fullscreen mode

Utilities:

gh prs   # your PRs in the current repo (all states)
gh open  # open current repo in browser
gh co    # interactive PR checkout
Enter fullscreen mode Exit fullscreen mode

All cross-platform — macOS date flags handled separately from Linux via [[ "$OSTYPE" == "darwin"* ]] checks in the shell snippets.


🎨 Starship: A Two-Line Prompt Showing Everything

The starship.toml config uses a two-line layout with $fill for right-alignment. Line 1 (left): hostname (SSH only), directory, language version modules. Line 1 (right): git branch, git status, command duration, time, OS. Line 2: (green on success, red on error).

Notable details:

  • Directory truncated to 1 level (truncation_length = 1)
  • Git status shows ahead/behind counts (⇡/⇣), untracked (?), modified (!), staged (+), renamed (»), deleted ( )
  • Command duration shown after just 1ms
  • Custom VS Code version[custom.vscode] runs a shell script that finds the installed binary, reads its package.json, and shows the version inline in the prompt whenever VS Code is available. Works across code, code-oss, and code-insiders.
  • Language icons for Node, Go, Python, Rust, Java, Kotlin, Lua, Dart, Swift, Zig, Deno, Bun, and more — all Nerd Font.

🖱️ Rofi: Dracula App Launcher (Linux)

rofi/config.rasi uses the Dracula palette as CSS variables: MonoLisa 13 font, rounded 8px corners, 95% opaque background (#282a36ee), bd93f9 purple border and selection highlight, MacTahoe-dark icon theme. 7 items visible, 1 column, no scrollbar.


🎵 ytm-player: YouTube Music in the Terminal

High-quality audio, 80% default volume, prefetch_next enabled, block-style progress bar, album art in UI. MPRIS enabled for Linux media key integration. LastFM and Discord Rich Presence configured but disabled by default — just uncomment to enable.


🏗️ Full Architecture

scripts/
├── install.sh               # runs lib/* in order
├── setup.sh                 # interactive numbered menu
├── config/wallpapers.url    # remote wallpapers repo URL
├── utils/detect.sh          # OS, pkg manager, sudo detection
└── lib/
    ├── packages.sh          # all tools via apt/brew/pacman
    ├── plugins.sh           # oh-my-zsh, zsh plugins, tpm
    ├── wallpapers.sh        # clones wallpapers repo
    ├── dotfiles.sh          # stow + chmod git hooks
    ├── go_tools.sh          # gopls, goimports, golangci-lint, air,
    │                        # gotests, govulncheck, shfmt, usql, slim
    │                        # (--update flag supported)
    └── python_tools.sh      # httpie, ytm-player via uv
                             # (--update flag supported)
Enter fullscreen mode Exit fullscreen mode

usql is installed with custom build tags (mysql postgres sqlite3 moderncsqlite) — one universal SQL client for four databases. Both go_tools.sh and python_tools.sh call go clean -modcache or equivalent cleanup after installation.


✅ CI/CD: Dotfiles That Are Actually Tested

shell-validation.yml — Runs shellcheck on every .sh file in scripts/ to catch undefined variables, unsafe patterns, and portability issues.

scripts-functionality.yml — Integration tests that run the core install scripts end-to-end in a CI environment.

Full GitHub issue template system: bug reports, feature requests, and config update requests — each with structured fields. PR template with a checklist.


🔒 Secret Templates

docs/templates/.zsh_secrets.template — Documents exactly which variables to set (including GIT_PUSH_PASS) in ~/.zsh_secrets, sourced by the pre-push hook.

docs/templates/.connections.usql.template — Ready-to-fill database connection string template for usql.


Getting Started

# Full auto-bootstrap
git clone https://github.com/GourangaDasSamrat/dotfiles.git ~/dotfiles
cd ~/dotfiles/scripts && ./install.sh

# Interactive — pick exactly what you want
cd ~/dotfiles/scripts && ./setup.sh

# Just Go tools
bash ~/dotfiles/scripts/lib/go_tools.sh

# Update all Go tools
bash ~/dotfiles/scripts/lib/go_tools.sh --update

# Just Python tools
bash ~/dotfiles/scripts/lib/python_tools.sh
Enter fullscreen mode Exit fullscreen mode

Why This Is Different From Most Dotfiles Repos

Conditional loading everywhere. Nothing breaks if a dependency isn't installed. Every alias, function, and plugin checks for its binary before defining itself. Works on a minimal server and a fully loaded workstation.

The functions are genuinely useful replacements. apireq isn't a thin curl wrapper — it's a workflow with saved state. timer isn't a sleep alias — it's a full TUI. chpwd hooks aren't novelties — they save real keystrokes every day.

Git hygiene enforced at the machine level. core.hooksPath in .gitconfig points to a global location. Every repository you clone or create automatically gets conventional commit validation and push authorization — not just repos where you remembered to install hooks.

Modular by design. You can take exactly one piece — the fzf config, the git aliases, the apireq function, the starship prompt — and drop it into your own setup without the rest.


The repo is at github.com/GourangaDasSamrat/dotfiles. Everything described here is real, working code — read the source.

If it made your terminal feel like home — drop a ⭐


Built by Gouranga Das Samrat · MIT License · Issues and PRs welcome

Top comments (0)