Cross-platform dotfiles that work across macOS, WSL Ubuntu, and Arch Linux. Because maintaining three separate configs is nobody's idea of a good time.
A dotfiles setup that prioritizes shared configuration with platform-specific overrides only when absolutely necessary. Includes a bunch of modern CLI tools, a theme system that actually works, and some custom tools to keep everything organized.
Quick stats: ~100 CLI tools, shared zsh/tmux/neovim configs, automated theme switching, and a discovery system so you can actually remember what you installed.
Clone and run the setup script:
git clone https://github.com/datapointchris/dotfiles.git ~/dotfiles
cd ~/dotfiles
./install.sh # Automatically detects your platformSkip font installation if needed:
SKIP_FONTS=1 ./install.shResilient Installation: The installer continues even when individual downloads fail (common in corporate networks with firewalls). At the end, you get a comprehensive failure report with manual installation steps for any missing tools. Most of your system will be working - just a few packages might need manual attention.
See the quickstart guide for details.
dotfiles/
├── platforms/ # System configurations (deployed to $HOME)
│ ├── common/ # Shared configs (zsh, nvim, tmux, git)
│ ├── macos/ # macOS-specific overrides
│ ├── wsl/ # WSL Ubuntu-specific overrides
│ └── arch/ # Arch Linux-specific overrides
├── apps/ # Personal CLI applications (shell scripts)
│ ├── common/ # Cross-platform: menu, notes, backup-dirs, patterns
│ └── macos/ # macOS-specific tools
├── management/ # Repository management
│ ├── symlinks/ # Symlinks manager (Python)
│ ├── packages.yml # Package definitions
│ └── {platform}/ # Platform-specific install scripts
└── docs/ # Documentation (because future you will forget)
External tools (installed from GitHub, not in this repo):
sess,toolbox: Go apps viago install github.com/datapointchris/...theme,font: Bash tools cloned to~/.local/share/
The core philosophy: write configs once in platforms/common/, override only what's platform-specific.
This setup follows some opinionated principles that make maintenance easier:
Fail Fast and Loud (But Keep Going): Individual installers exit immediately on errors with clear messages. But the wrapper catches failures and continues installing everything else. You get the full error context for what broke AND a working system with just a few missing pieces. No silent failures, no broken partial installations.
Explicit Over Hidden: Platform-specific logic lives at the top level (bootstrap scripts, main Taskfile), not buried deep in install scripts. If there are OS conditionals, you see them upfront.
Straightforward and Simple: Prefer some duplication over complex abstractions. Three similar install scripts (one per platform) are clearer than one script with conditional maze. The small amount of repeated code is worth the reduced cognitive load.
Linear and Predictable: Installation follows clear phases in order. No surprises, no hidden dependencies being installed behind the scenes. You can follow exactly what's happening at each step.
Universal Tools: Install scripts work on any platform with no OS detection. Platform logic stays in the taskfiles that call them.
This means when something breaks (and it will), you can quickly find and fix it. When you come back six months later, the code still makes sense.
Scripts in this repo use colors, unicode characters, and emojis to make output scannable and easy to understand at a glance.
Default Assumption: Output is for human consumption, not log aggregation systems. Readability trumps machine parsability.
Color-Coded Hierarchy:
- Blue thick borders (━━━): Main headers and footers
- Cyan text: Section headings and subsections
- Green: Success messages and status
- Red: Errors and failures
- Yellow: Warnings and cautions
Status Indicators:
✓Unicode checkmarks for individual successes (keeps output compact)✅Emoji checkbox for final success messages (high visibility)✗Red X for errors⚠️Warning sign for important notes•Bullets for lists (cleaner than hyphens)
Guidelines:
- Use emojis sparingly but helpfully
- If there would be 50+ checkboxes, use unicode
✓instead - Never use decorative emojis (smileys, celebrations, etc.)
- Add spacing around major sections for breathing room
If a specific project's logs will be ingested by a log aggregation system (Splunk, ELK, etc.), dial back the colors and special characters. But that's rare for personal projects.
See platforms/common/.local/shell/formatting.sh and platforms/common/.local/shell/colors.sh for reusable libraries that are sourced system-wide and can be copied to other projects.
This setup uses different package managers for different purposes, because that's apparently the world we live in:
| What | How | Examples |
|---|---|---|
| System utilities | brew / apt / pacman | bat, eza, fd, ripgrep, tmux, neovim |
| Python | uv | version management, ruff, mypy, etc. |
| Node.js | nvm | version management, LSPs, formatters |
Why the split? Cross-platform consistency, project-specific versions, and keeping system packages separate from development tools.
See CLAUDE.md for the full philosophy (it's longer than it needs to be, but comprehensive).
Installed something six months ago and forgot about it? The toolbox command has you covered:
toolbox list # See everything
toolbox show ripgrep # Details, examples, why you installed it
toolbox search git # Find git-related tools
toolbox random # Discover something you forgot existedCurrently 31 tools documented in the registry with usage examples and tips. More getting added as I remember they exist.
# Themes
theme list # List available themes
theme apply rose-pine # Apply theme across terminal apps
theme preview # Preview themes with fzf
# Package updates
task update # Update everything
# Symlinks
task symlinks:link # Deploy configs (also: relink, check, unlink)
# Discovery
toolbox search python # Find Python toolsRun task --list to see all available tasks.
The symlinks tool manages deploying configs from the repo to their actual locations. Written in Python because shell scripts for path manipulation are a recipe for sadness.
Important: After adding or removing files in the repo, run task symlinks:link to update symlinks. Otherwise Neovim will complain about missing modules and you'll spend 20 minutes debugging before remembering this note.
Unified theme generation from theme.yml source files. The theme CLI applies themes consistently across ghostty, tmux, btop, and more:
theme list- See available themestheme apply <name>- Apply theme across all appstheme preview- Interactive preview with fzftheme current- Show current theme and statstheme like/dislike- Track preferences
Theme persists across sessions. Neovim uses either generated colorschemes or original plugins based on theme configuration.
Full docs are available at datapointchris.github.io/dotfiles:
- Quickstart - Get running in 15 minutes
- Installation - Detailed install guide
- Architecture - How everything fits together
- Tool Reference - All the tools
- Troubleshooting - When things break
There's also a learnings section with extracted wisdom from bugs I've fixed and things I've figured out.
Neovim: Native LSP with 10+ language servers, CodeCompanion for Claude integration, custom colorscheme manager with 17 themes.
Shell: Custom ZSH prompt with git status, zoxide for smart directory jumping, fzf with preview, syntax highlighting, vi-mode.
Modern CLI replacements: bat (cat with syntax highlighting), eza (ls with git integration), fd (find that respects .gitignore), ripgrep (grep but faster), yazi (terminal file manager).
Task automation: Modular Taskfile system with separate files for brew, npm, uv, symlinks, etc. Makes it easy to add new automation without creating a monolithic mess.
This is a personal dotfiles repo, but you're welcome to:
- Steal ideas for your own setup
- Open issues if you spot something broken
- Suggest tools or improvements
MIT - do whatever you want with it
Tip: Running toolbox random occasionally is a good way to rediscover tools you installed and immediately forgot about.