Navigate, modify, and manage Luan's dotfiles repository from any directory...
The repository lives at ~/dotfiles on macOS and Arch Linux.
Debugging: Installation output is logged to ~/dotfiles_install.log
The repo follows a one directory per tool pattern. To see the current structure:
tree ~/dotfiles -L 2 -d # or: ls -la ~/dotfiles
Each tool directory should contain:
install script with install() and configure() functionsSee references/tool-template.md for the install script template.
| Tool | Directory | Config Location | Has Install Script |
|---|---|---|---|
| Neovim | nvim/ |
~/.config/nvim |
Yes (binary from Nix + config/plugin setup) |
| Tmux | tmux/ |
~/.tmux.conf |
Yes (binary from Nix base + config symlink) |
| Zsh | zsh/ |
~/.zshrc, ~/.zsh/ |
Yes (install.zsh) |
| Git | git/ |
~/.gitconfig |
Yes (binary from Nix + config symlinks) |
| Ghostty | ghostty/ |
~/.config/ghostty |
No |
| Helix | helix/ |
~/.config/helix |
Yes (binary from Nix + config symlinks) |
| Whisper | whisper/ |
N/A | Yes (Nix flake: openai-whisper, opt-in) |
| Skills | skills/ |
~/.claude/skills/, ~/.pi/agent/skills/ |
Yes |
| Rust | rust/ |
N/A | Yes (Nix flake: rustc, cargo, rustfmt, clippy, rust-analyzer) |
| Go | go/ |
N/A | Yes (Nix flake: go, gopls, gofumpt, goimports-reviser) |
| Ruby | ruby/ |
N/A | Yes (Nix flake: ruby_3_4) |
| Base utilities | base/ |
N/A | Yes (Nix flake: fzf, fd, ffmpeg, jq, eza, ripgrep, openssh, tmux, poppler-utils) |
| Node | node/ |
N/A | Yes (Nix flake: node + TypeScript tools) |
| Hunk | hunk/ |
~/.config/hunk/config.toml, git aliases (hdiff, hshow) |
Yes |
| Bin | bin/ |
~/.local/bin |
Yes (custom scripts) |
| jj | jj/ |
N/A | Yes (Nix flake: Jujutsu VCS) |
| gh | gh/ |
~/.config/gh-not, launchd agent |
Yes (binary from Nix + extensions/config) |
| glab | glab/ |
N/A | Yes (Nix flake: glab, opt-in) |
| AWS CLI | aws/ |
~/.aws/config |
Yes (Nix flake: awscli2, opt-in) |
| 1Password CLI | 1password/ |
N/A | Yes (Nix flake: 1password-cli) |
| Platform | Detection | Package Manager | Notes |
|---|---|---|---|
| macOS | uname == Darwin |
brew |
Personal machines |
| Arch/Omarchy | command -v pacman |
pacman/yay |
Arch + Hyprland |
| Omarchy | ~/.local/share/omarchy exists |
pacman/yay |
Uses default configs, skip apply() |
See references/platform-detection.md for detection code snippets.
Never create or edit files directly in config target directories like ~/.config/ or ~/.local/bin/. These locations contain symlinks to ~/dotfiles/, so changes made there are either not version controlled or will be overwritten by install scripts.
Always make changes in ~/dotfiles/ so they are:
dot pullCommon mistakes to avoid:
~/.claude/skills/ or ~/.pi/agent/skills/ instead of ~/dotfiles/skills/~/.config/nvim/ instead of ~/dotfiles/nvim/~/.local/bin/ instead of ~/dotfiles/bin/After creating or modifying files in ~/dotfiles/, run the appropriate install script to create symlinks (e.g., dot install skills, dot install nvim).
@latest tags, --lts flags, or omit version specifiers where possible.install(), configure(), and optionally apply() and update() functions.Homebrew is installed lazily in Phase 3 of install, only when needed for brew-dependent tools.
| Purpose | Location | Example |
|---|---|---|
| User binaries/scripts | ~/.local/bin/ |
dotfiles, dot |
| Tool extractions | ~/.local/<tool>/ |
~/.local/gh/ |
Scripts from bin/ are symlinked individually to ~/.local/bin/.
Scripts should produce the same result whether run once or many times:
Check before installing: Use command -v <tool> to skip if already installed
if command -v rustc &>/dev/null; then
echo "Rust already installed"
return
fi
Use -sf for symlinks: The -f flag overwrites existing symlinks safely
ln -sf "$SCRIPT_DIR/.config" "$HOME/.config/tool"
Handle existing directories: Check and backup if needed
if [[ -e "$target" && ! -L "$target" ]]; then
mv "$target" "$target.backup"
fi
Use --noconfirm for package managers: Avoid interactive prompts
sudo pacman -S --noconfirm package
brew install package # Already non-interactive
The dot command (symlinked to ~/.local/bin/ from bin/dotfiles) provides easy management:
dotfiles status # Check install/config health
dotfiles pull # Pull latest and apply changes (skipped on Omarchy)
dotfiles edit # Open dotfiles in $EDITOR
dotfiles update # Update tools (brew, Nix profiles, nvim plugins, etc.)
The CLI uses jj (Jujutsu) if available, falling back to git.
<tool>/ directory at repo root<tool>/install script using the template with:install() - Install the tool binary/packageconfigure() - Symlink configs, set up environmentapply() (optional) - Reload config after dotfiles pull, or handle migrationsupdate() (optional) - Update tool for dotfiles updatecheck_installed() / check_configured() - For dot status health checksinstall in the appropriate phaseSee references/tool-template.md for the install script template. See references/install-patterns.md for version checking and migrations.
See references/nvim-config.md for structure details.
Key locations:
nvim/lua/plugins/<name>.luanvim/lua/config/mappings.luanvim/init.lua# Main install
~/dotfiles/install
# Tool-specific installs
~/dotfiles/base/install
~/dotfiles/nvim/install
~/dotfiles/zsh/install.zsh
~/dotfiles/skills/install
~/dotfiles/aws/install
~/dotfiles/node/install
~/dotfiles/rust/install
~/dotfiles/go/install
~/dotfiles/jj/install
The lib/common.sh file provides shared functions for all scripts:
source "$DOTFILES_DIR/lib/common.sh"
dotfiles_dir # Get dotfiles path
is_macos # Check if running on macOS
is_arch # Check if running on Arch Linux
is_omarchy # Check if running on Omarchy
vcs_cmd # Run jj or git command
log_info/log_success/log_warn/log_error # Logging helpers