Making Dotfiles Visible: A Deep Dive into GNU Stow's --dotfiles Flag

5 min read 871 words

The Hidden File Problem

If you've ever managed dotfiles with GNU Stow, you've likely encountered the visibility problem: your repository is littered with hidden files and directories that require ls -la to see. This makes browsing the repository in IDEs, GitHub, or terminal file managers frustrating and opaque.

I recently solved this problem by restructuring my entire dotfiles repository using GNU Stow's --dotfiles flag in commit d1ddce5. The result? Every configuration file is now immediately visible while maintaining proper XDG Base Directory compliance when deployed.

Understanding GNU Stow's --dotfiles Flag

GNU Stow's --dotfiles flag, introduced in version 2.3.0, enables special preprocessing for files and directories with a dot- prefix. When this flag is used, Stow transforms the prefix during symlink creation:

# Repository structure (visible)
fish/dot-config/fish/config.fish
fish/dot-bashrc

# After stowing with --dotfiles
~/.config/fish/config.fish  -> fish/dot-config/fish/config.fish
~/.bashrc                   -> fish/dot-bashrc

The transformation rules are simple but powerful:

  • dot- prefix becomes . (period)
  • dot-config becomes .config
  • dot-vimrc becomes .vimrc
  • Nested structures are preserved: dot-config/nvim/init.lua.config/nvim/init.lua

The Transformation: Before and After

Before: Hidden File Chaos

dotfiles/
├── .vimrc
├── .tmux.conf
├── .gitconfig
├── .config/
│   ├── nvim/
│   ├── fish/
│   └── starship.toml
└── .scripts/

Browsing this requires hidden file visibility, and IDEs often struggle with indexing.

After: Complete Visibility

dotfiles/
├── dot-vimrc
├── dot-tmux.conf
├── dot-gitconfig
├── dot-config/
│   ├── nvim/
│   ├── fish/
│   └── starship.toml
├── dot-scripts/
└── brew/
    └── Brewfile

Every file is immediately visible with standard ls, IDEs can index everything, and the structure is self-documenting.

Implementation Details

The restructuring involved 118 files across multiple categories:

1. XDG Config Directory Migration

All .config/ directories were transformed to dot-config/:

# Applications affected (50+ configs)
.config/nvim/     → dot-config/nvim/
.config/fish/     → dot-config/fish/
.config/starship/ → dot-config/starship/
.config/lazygit/  → dot-config/lazygit/
# ... and many more

2. Root Dotfiles Transformation

Traditional dotfiles got the dot- prefix:

.vimrc        → dot-vimrc
.tmux.conf    → dot-tmux.conf
.gitconfig    → dot-gitconfig
.bash_aliases → dot-bash_aliases

3. Bootstrap Script Overhaul

The deployment script was completely rewritten to handle the new pattern:

#!/usr/bin/env bash

# Stow packages using --dotfiles flag
for package in bash editorconfig env fish nvim tmux vim snippets \
               starship lazygit lazyvim wezterm nushell yazi raycast \
               zellij marimo bat aerospace sesh ripgrep ghostty; do
  stow --target=$HOME --dotfiles $package
done

# Stow packages without --dotfiles (special cases)
for package in git scripts; do
  stow --target=$HOME $package
done

# Install Homebrew dependencies
brew bundle install --file=brew/Brewfile

The Technical Deep Dive

How --dotfiles Works Internally

According to the GNU Stow manual, the --dotfiles flag adds a preprocessing step that:

  1. Scans package directories for files/folders with dot- prefix
  2. During symlink creation, replaces dot- with . in the target path
  3. Preserves the original filename in the package directory
  4. Handles nested structures correctly

Edge Cases and Considerations

The transformation has some nuances:

  • Files without dot- prefix are processed normally
  • dot- prefixed files are never ignored by default ignore patterns
  • The flag must be used consistently across all stow operations

Package Management Flexibility

One major benefit is granular package management:

# Install specific configurations
stow --dotfiles --target=$HOME fish
stow --dotfiles --target=$HOME nvim

# Remove specific configurations  
stow --delete --dotfiles --target=$HOME fish

# Reinstall with updates
stow --restow --dotfiles --target=$HOME nvim

Real-World Benefits

Developer Experience Improvements

  1. IDE Integration: All files are indexed and searchable
  2. GitHub Browsing: Repository structure is immediately clear
  3. Code Reviews: Changes to configuration files are obvious
  4. Documentation: Self-documenting directory structure

Maintenance Advantages

  1. Debugging: Easy to locate specific configuration files
  2. Backup Verification: Visual confirmation of what's being tracked
  3. Selective Syncing: Clear package boundaries for partial deployments
  4. Team Sharing: Colleagues can understand structure at a glance

Migration Strategy

If you're considering this transformation:

1. Backup Everything

git checkout -b dotfiles-backup
git push origin dotfiles-backup

2. Transform Incrementally

# Start with one package
git mv .config/fish dot-config/fish
stow --delete fish  # unstow old version
stow --dotfiles fish  # stow new version

3. Update Bootstrap Scripts

Modify your deployment scripts to use --dotfiles flag consistently.

4. Test Thoroughly

Verify all configurations work as expected before committing fully.

Gotchas and Limitations

Mixed Package Handling

Some packages might need special treatment. In my setup, I handle git and scripts packages differently:

# These use --dotfiles
stow --dotfiles fish nvim tmux

# These don't (they manage their own dot-prefixing)
stow git scripts

File History Preservation

Use git mv for renames to preserve file history:

git mv .vimrc dot-vimrc
git mv .config/fish dot-config/fish

Tool Integration

Some tools might be confused by the new naming. Document any special cases in your README.

Conclusion

GNU Stow's --dotfiles flag solves a fundamental usability problem with dotfiles management. By making configuration files visible in repositories while maintaining proper deployment locations, it dramatically improves the developer experience.

The transformation requires careful planning and testing, but the benefits—immediate visibility, better IDE support, clearer repository structure—make it worthwhile for any serious dotfiles setup.

If you manage dotfiles with Stow, consider implementing this pattern. Your future self (and anyone browsing your configurations) will thank you.

Resources