oh-my-dot
A cross-platform dotfile manager with an advanced shell framework written in Go.
Oh-my-dot helps you manage your dotfiles across multiple machines with git integration and provides a powerful shell framework for managing shell configurations (aliases, prompts, completions) across bash, zsh, fish, PowerShell, and POSIX sh.
Features
- Cross-Platform: Works on Windows, macOS, and Linux
- Git Integration: Store and sync your dotfiles with git
- Shell Framework: Manage shell features with advanced loading strategies
- Eager loading for instant availability
- Deferred loading for faster shell startup
- On-command loading for lazy evaluation
- Local Overrides: Per-machine customizations with security validation
- Health Checks: Built-in
doctor command to validate configuration
- Interactive Mode: Browse and manage features interactively
Install
Linux and macOS (Automatic)
Run the install script to automatically download and install the latest version:
curl -fsSL https://raw.githubusercontent.com/PatrickMatthiesen/oh-my-dot/main/install.sh | bash
> Security Note: For added security, you can download and inspect the script before running it:
> sh > curl -fsSL https://raw.githubusercontent.com/PatrickMatthiesen/oh-my-dot/main/install.sh -o install.sh > # Review the script > cat install.sh > # Run it > bash install.sh >
This script will:
- Detect your OS and architecture automatically
- Download the latest release from GitHub
- Install the binary to
~/.oh-my-dot/bin
- Create a symlink in
~/.local/bin
- Add the binary to your current session's PATH
If you need to install a specific version, you can set the OH_MY_DOT_VERSION environment variable:
curl -fsSL https://raw.githubusercontent.com/PatrickMatthiesen/oh-my-dot/main/install.sh | OH_MY_DOT_VERSION=v0.0.25 bash
Windows (Winget)
winget install PatrickMatthiesen.oh-my-dot
Manual Installation
- Find the latest release matching your CPU architecture and Operating system.
- Download the executable to a persistent folder.
> A folder you know won't change or randomly be deleted
>
> I recommend putting it under
$HOME/oh-my-dot
- Add the folder to your PATH
- Start using oh-my-dot
Quick Start
Initialize Repository
# New fresh config
oh-my-dot init github.com/username/dotfiles
# Or with explicit remote
oh-my-dot init --remote github.com/username/dotfiles
# Existing config (use --force to override)
oh-my-dot init -r github.com/username/dotfiles -f /path/to/dotfiles --force
Apply Dotfiles
oh-my-dot apply
This will:
- Link your dotfiles to their target locations
- Install shell hooks for the shell framework
Shell Completion
Enable tab completion for your shell:
# Bash
echo 'source <(oh-my-dot completion bash)' >> ~/.bashrc
# Zsh
echo 'source <(oh-my-dot completion zsh)' >> ~/.zshrc
# Fish
oh-my-dot completion fish > ~/.config/fish/completions/oh-my-dot.fish
# PowerShell
oh-my-dot completion powershell >> $PROFILE
Shell Framework
The shell framework allows you to manage shell configurations as modular features with advanced loading strategies.
Adding Features
Interactive Mode (Recommended)
oh-my-dot feature add -i
Browse the catalog and select features to add. The interactive mode automatically detects your current shell, places it at the top of the shell selection list, and pre-selects it for your convenience.
Supported Shells: bash, zsh, fish, PowerShell, and POSIX sh
Direct Addition
# Add to current shell (auto-detected)
oh-my-dot feature add git-prompt
# Add to specific shell
oh-my-dot feature add kubectl-completion --shell bash
# Add to all supported shells
oh-my-dot feature add core-aliases --all
When no --shell flag is provided, oh-my-dot tries to detects your current shell and adds the feature to it.
Loading Strategies
Features can be loaded with different strategies to optimize shell startup:
Eager Loading (Default)
Loads immediately during shell startup:
oh-my-dot feature add git-prompt --strategy eager
Deferred Loading
Loads in background for interactive shells (faster startup):
oh-my-dot feature add kubectl-completion --strategy defer
On-Command Loading
Lazy loads when specific commands are invoked:
oh-my-dot feature add nvm --strategy on-command --on-command nvm,node,npm
Managing Features
# List features
oh-my-dot feature list
oh-my-dot feature list --shell bash
# Remove features
oh-my-dot feature remove -i # Interactive
oh-my-dot feature remove git-prompt # Direct
oh-my-dot feature remove kubectl --all # From all shells
# Update/refresh features
oh-my-dot feature update -i # Interactive
oh-my-dot feature update powershell-aliases # Direct
oh-my-dot feature update powershell-aliases --shell powershell
# Enable/disable features
oh-my-dot feature enable git-prompt
oh-my-dot feature disable kubectl --shell bash
# Show feature info
oh-my-dot feature info git-prompt
Feature Files
Features are stored in omd-shells//features/:
# Example: omd-shells/bash/features/git-prompt.sh
# Add your custom shell code here
parse_git_branch() {
git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
}
export PS1="\u@\h \W \$(parse_git_branch) $ "
Local Overrides
Create enabled.local.json for per-machine customizations:
# omd-shells/bash/enabled.local.json
{
"features": [
{
"name": "git-prompt",
"strategy": "eager"
},
{
"name": "work-vpn",
"strategy": "on-command",
"onCommand": ["vpn-connect"]
}
]
}
Security Requirements:
- File must be owned by current user
- File must not be group or world writable
- File must be a regular file (not a symlink)
Invalid local overrides are automatically ignored with warnings.
Organizing dotfiles
Use add FILE to store a dotfile. If its filename is taken, add automatically
includes parent directory names and reports the chosen path. Use --as tool/config
for an exact name. Bare add opens a picker in a terminal. list shows full paths;
remove tool/config selects one entry. Folder names organize storage and do not activate groups.
See the nested file naming guide for examples,
Windows path rules, and an isolated test configuration.
Health Checks
Validate your repository and shell framework setup:
# Check all shells
oh-my-dot doctor
# Check specific shell
oh-my-dot doctor --shell bash
# Auto-fix issues
oh-my-dot doctor --fix
The doctor checks:
- Git repository and effective commit identity
- Origin remote configuration and read access (warnings only)
- Directory structure
- Manifest validity
- Feature file existence
- Profile hooks installation
- Local override security
- Init script syntax
Repository checks run even without shell features. Missing Git identity is an
error with instructions for setting your name and email; doctor --fix does not
choose an identity for you. Missing or inaccessible remotes produce warnings in
doctor. Local add and remove operations do not contact the remote. Remote read
access does not guarantee push permission.
PowerShell Support
Oh-my-dot fully supports PowerShell (both Windows PowerShell 5.1 and PowerShell Core 7+):
Auto-Detection: When running feature add -i in PowerShell, your current shell is automatically detected and pre-selected.
PowerShell-Specific Features:
powershell-prompt - Custom prompt with git status
powershell-aliases - Common PowerShell aliases and shortcuts
posh-git - Git integration for PowerShell
Profile Integration:
# PowerShell profile ($PROFILE)
. "$HOME\dotfiles\omd-shells\powershell\init.ps1"
The init script supports all loading strategies (eager, defer, on-command) with PowerShell-native syntax.
Directory Structure
dotfiles/
├── files/ # Your dotfiles
│ ├── .gitconfig
│ ├── .vimrc
│ └── ...
├── omd-shells/ # Shell framework
│ ├── bash/
│ │ ├── enabled.json # Base configuration (tracked)
│ │ ├── enabled.local.json # Local overrides (untracked)
│ │ ├── init.sh # Auto-generated init script
│ │ ├── features/ # Feature implementations
│ │ │ ├── git-prompt.sh
│ │ │ └── aliases.sh
│ │ └── helpers/ # Shared helper functions
│ ├── zsh/
│ ├── fish/
│ └── powershell/
└── .linkings # Dotfile link mappings
Configuration
Oh-my-dot uses a .oh-my-dot.yaml config file:
repo-path: ~/dotfiles
remote: github.com/username/dotfiles
Commands Reference
Core Commands
oh-my-dot init - Initialize dotfiles repository
oh-my-dot apply - Apply dotfiles and shell integration
oh-my-dot push - Commit and push changes to git
oh-my-dot pull - Pull changes from git
oh-my-dot status - Show repository status
Feature Commands
oh-my-dot feature add [-i] - Add shell feature
oh-my-dot feature remove [-i] - Remove shell feature
oh-my-dot feature list - List all features
oh-my-dot feature enable - Enable feature
oh-my-dot feature disable - Disable feature
oh-my-dot feature info - Show feature details
Utility Commands
oh-my-dot doctor [--fix] - Health check and diagnostics
oh-my-dot completion - Generate shell completion
oh-my-dot version - Show version information
Automatic Remote Update Checks
oh-my-dot performs a lightweight remote sync check (no full fetch) on:
oh-my-dot add
oh-my-dot remove
oh-my-dot apply
oh-my-dot push
oh-my-dot doctor
When updates are detected, oh-my-dot shows a non-blocking notice and suggests oh-my-dot pull.
Sync state messages:
- Remote ahead: prompts you to run
oh-my-dot pull
- Diverged: warns that pull may require conflict resolution
- Local ahead: suggests running
oh-my-dot push
Global Flags
-i, --interactive - Force interactive mode
--no-interactive - Disable all prompts (for CI/scripting)
Examples
Basic Workflow
# Initialize
oh-my-dot init github.com/username/dotfiles
# Add features interactively
oh-my-dot feature add -i
# Apply changes
oh-my-dot apply
# Commit and push
oh-my-dot push
Advanced Feature Management
# Add git prompt with eager loading
oh-my-dot feature add git-prompt --strategy eager --shell bash
# Add kubectl completion with deferred loading
oh-my-dot feature add kubectl --strategy defer
# Add nvm with on-command loading
oh-my-dot feature add nvm --strategy on-command --on-command nvm,node,npm
# Create local override for work machine
cat > ~/dotfiles/omd-shells/bash/enabled.local.json << 'EOF'
{
"features": [
{
"name": "work-aliases",
"strategy": "eager"
}
]
}
EOF
chmod 600 ~/dotfiles/omd-shells/bash/enabled.local.json
# Validate setup
oh-my-dot doctor --fix
Troubleshooting
# Check health
oh-my-dot doctor
# Fix common issues
oh-my-dot doctor --fix
# Re-apply shell hooks
oh-my-dot apply
# Check git status
oh-my-dot status
Known Issues
SSH
If you are using SSH to clone your dotfiles, you will need to add your SSH key to the SSH-Agent. This is because oh-my-dot uses Git under the hood:
ssh-add ~/.ssh/id_rsa
> If you are having issues on Windows you might want to install a newer version of OpenSSH. The one that comes with Windows is outdated and requires a bit more work to get going.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Security
Oh-my-dot includes security features to protect against path traversal and other vulnerabilities. See docs/SECURITY.md for details on:
- Path traversal protection
- Configurable home directory restrictions
- Input validation
To report security vulnerabilities, please use GitHub Security Advisories.
License
This project is licensed under the MIT License - see the LICENSE file for details.