Skip to content

Repository files navigation

dotfiles

A Rust-powered dotfiles bootstrapper for a personal developer environment with first-class support for macOS and Ubuntu.

demo


What's inside

Layer Tool Details
Bootstrapper dotup Rust CLI for install, dry-run, doctor, and sync workflows
Shell Zsh + Oh-My-Zsh + Starship Shared shell config with optional local overrides
Editor Neovim (from scratch) nvim/ in this repo, symlinked to ~/.config/nvim; built-in LSP, built-in completion, vim.pack for 5 plugins
Multiplexer Tmux and Zellij Both installed and configured; pick per session. Plugin-free on both sides
Terminal WezTerm Personal defaults with documented font expectations
Package management Homebrew on macOS, APT on Ubuntu Other Linux package managers remain best-effort
IDE integration IdeaVim JetBrains Vim motions via vim/ideavimrc.vim

Quick start

git clone https://github.com/toandaominh1997/dotfiles.git "$HOME/.dotfiles/tool"
cd "$HOME/.dotfiles/tool"
cargo run -- --auto

Restart your terminal, then open nvim once — vim.pack installs its plugins and nvim-treesitter builds parsers on first launch. Tmux needs no bootstrap.


Support model

  • First-class platforms: macOS and Ubuntu
  • Best-effort platforms: other Linux distributions supported through existing package-manager adapters
  • GUI app installation: macOS-only
  • Setup bias: personal machine defaults first, with explicit local overrides for machine-specific differences

Dotup CLI

cargo run -- --auto                  # full install
cargo run -- --auto --upgrade --verbose
cargo run -- --auto --dry-run        # show what would change
cargo run -- --doctor                # health check
cargo run -- --sync                  # commit + push this repo
cargo run -- --auto --profile work
cargo run --                         # no flag: print help, change nothing

Profiles

Profiles are defined in dotup.toml:

  • default — personal baseline with shell, editor, tmux, and core CLI tools
  • work — adds common work tooling such as AWS CLI, Docker, Kubernetes, Node, Rust, and Terraform
  • minimal — smaller shell and terminal setup

Install flow

dotup orchestrates setup in this order:

  1. Initialize the platform package manager
  2. Install required packages from the selected profile
  3. Install optional packages from the selected profile
  4. Install macOS casks when running on macOS
  5. Install fonts
  6. Configure zsh
  7. Configure tmux
  8. Configure Vim and Neovim

Existing configs are backed up with a timestamp before being overwritten.


Zsh

The generated ~/.zshrc sources ~/.dotfiles/tool/zsh/config.zsh.

Highlights:

  • Starship prompt
  • Oh-My-Zsh with plugin-based completion and UX improvements
  • macOS Homebrew shellenv bootstrapping
  • optional machine-local additions via ~/.zshrc.local

Update Oh-My-Zsh:

omz update

Tmux

Prefix: Ctrl+b

tmux/config.tmux is ~120 lines of built-in tmux, with no plugin manager and no helper scripts.

  • clipboard via native OSC 52 (set-clipboard on) — works locally and over SSH
  • Ctrl+h/j/k/l moves between panes, and passes through to Neovim when the pane is running it (vim-tmux-navigator behaviour, no plugin on either side)
  • vi copy mode; mouse drag, double-click and triple-click all copy
  • prefix + ? opens a keybinding cheatsheet popup
  • prefix + r reloads (idempotent — re-sourcing does not duplicate options)
  • optional machine-local additions via ~/.tmux.conf.local

Nothing to install — the config is live as soon as tmux starts.

Claude Code under tmux

Two things break by default and are fixed here: Shift+Enter submits instead of inserting a newline, and desktop notifications / the progress bar never reach the outer terminal.

set -s extended-keys always     # `on` is not enough — see CLAUDE.md
set -s extended-keys-format csi-u
set -as terminal-features "xterm*:extkeys"
set -g allow-passthrough all    # `on` only works while the pane is visible

Ctrl+J and \ + Enter insert a newline in any terminal with no config. Run /terminal-setup in the host terminal, never inside tmux.


Zellij

Installed alongside tmux, not instead of it — ~/.config/zellij/config.kdl is a symlink to zellij/config.kdl here. Use whichever multiplexer you feel like; they never run at the same time and own separate config files.

The config layers on zellij's defaults rather than replacing them (no clear-defaults=true), so it stays short. Two things worth knowing:

  • tmux muscle memory already works. Ctrl b enters zellij's built-in tmux mode: " and % split, z zooms, c new tab, h/j/k/l move focus, d detaches, x closes. That is a zellij built-in, not something configured here.
  • Ctrl+h is unbound. Zellij binds it globally to Move mode, which would swallow the key before Neovim — which maps C-h/j/k/l to window navigation — could see it. Ctrl+j/k/l are not bound by zellij at all, so unbinding that one key makes all four reach Neovim. Zellij's own pane focus stays on Alt+h/j/k/l; Move mode moved to Ctrl p then m.

Clipboard is OSC 52 (no copy_command), same reasoning as everywhere else here.

Zellij is a best-effort package, not a required one: it is not in Ubuntu's apt repositories, so dotup will warn rather than fail there. On Linux install it with cargo install --locked zellij or from a GitHub release. tmux remains required on every platform, which is part of why both are kept.

Unlike tmux, zellij speaks the kitty keyboard protocol natively, so Claude Code's Shift+Enter needs no configuration at all under zellij.

Neovim

~/.config/nvim is a symlink to nvim/ in this repo, so editing the config here edits the live config. Requires Neovim 0.12+.

Built on Neovim's own machinery rather than a framework:

  • Plugin manager: vim.pack (built in) — no lazy.nvim, no NvChad
  • LSP: vim.lsp.config / vim.lsp.enable directly — no nvim-lspconfig
  • Completion: vim.lsp.completion with autotrigger — no nvim-cmp, no blink
  • Plugins (5): tokyonight, nvim-treesitter, gitsigns, fzf-lua, conform

fzf-lua and conform are deferred and sourced on first use.

File Holds
nvim/init.lua entry point, provider + loader settings
nvim/lua/options.lua editor options
nvim/lua/plugins.lua vim.pack specs, treesitter, deferred loaders
nvim/lua/lsp.lua server definitions, diagnostics, native completion
nvim/lua/keymaps.lua keymaps
nvim/nvim-pack-lock.json plugin revisions (committed)

Language servers are enabled only when their binary is on PATH: basedpyright and ruff for Python, lua_ls for Lua.

:lua vim.pack.update()   " update plugins
:lua vim.pack.get()      " list installed
:checkhealth

Run the config's test suite:

nvim --headless -c 'luafile tests/nvim_config_test.lua'
bash tests/tmux_config_test.sh
bash tests/zellij_config_test.sh

WezTerm

Config lives at wezterm/wezterm.lua.

  • Preferred font: AestheticIosevka Nerd Font Mono
  • color scheme: Aesthetic Night
  • pane and tab bindings are tuned to match tmux and editor navigation where possible

IdeaVim

Copy vim/ideavimrc.vim to ~/.ideavimrc for JetBrains IDEs.


Repository structure

.
├── src/                  # dotup Rust orchestration
├── dotup.toml            # package profiles
├── zsh/                  # shared zsh config
├── tmux/                 # shared tmux config
├── nvim/                 # neovim config (symlinked to ~/.config/nvim)
├── zellij/               # zellij config (symlinked to ~/.config/zellij)
├── vim/                  # plain vim + ideavim configs
├── wezterm/              # terminal config
├── starship/             # prompt config
├── fish/                 # fish shell config
├── tests/                # integration + nvim config tests
└── .github/workflows/    # CI workflows

Verification

Useful commands while iterating on the repo:

cargo test
cargo run -- --auto --dry-run --verbose
cargo run -- --doctor
bash tests/integration_test.sh
nvim --headless -c 'luafile tests/nvim_config_test.lua'
bash tests/tmux_config_test.sh
bash tests/zellij_config_test.sh

CI runs on macOS and Ubuntu to keep the documented support model honest.


References

About

A set of vim, tmux and zsh configuration files.

Topics

Resources

Stars

6 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages