Expert guide for managing cross-platform shell dotfiles with modular configuration, automatic symlinking, and lazy-loading patterns for macOS and Linux.
Expert assistant for managing a centralized dotfiles system with automatic symlinking, modular shell initialization, and cross-platform compatibility.
This skill helps you manage a sophisticated dotfiles repository that:
The dotfiles system has three core components:
1. **Bootstrap System**: `script/bootstrap` finds `dot.*` files and creates symlinks (`~/.dotfiles/tool/dot.config` → `~/.config`)
2. **Shell Initialization**: `.bashrc`/`.zshrc` automatically source all `*.sh`/`*.bash`/`*.zsh` files in sorted order
3. **Tool Organization**: Each tool gets its own directory with standard file patterns
1. **Create tool directory**: `mkdir ~/.dotfiles/[toolname]`
2. **Determine what files are needed**:
- `dot.*` files for configuration that should be symlinked to home directory
- `*.sh`/`*.zsh` files ONLY if they need to run on every shell startup
- Executable scripts without `.sh` extension if they should be run manually
- Scripts in `bin/` for general utilities
3. **CRITICAL RULE - Auto-sourcing**:
- Files with `.sh` or `.zsh` extensions are **automatically sourced during shell startup**
- **ONLY** use these extensions for environment setup (PATH, aliases, env vars, completions)
- **NEVER** use these extensions for action scripts, ProxyCommand scripts, or one-time setup
- Manual scripts: Remove `.sh` extension and make executable, or move to `bin/`
4. **Create initialization script with installation detection**:
```bash
cat > ~/.dotfiles/[toolname]/load.sh << 'EOF'
#!/usr/bin/env bash
if command -v [toolname] &> /dev/null; then
# Tool is installed - configure it
export TOOL_HOME="$HOME/.[toolname]"
export PATH="$TOOL_HOME/bin:$PATH"
# Shell-specific completions
if [[ -n "$ZSH_VERSION" ]]; then
eval "$([toolname] completions zsh)"
elif [[ -n "$BASH_VERSION" ]]; then
eval "$([toolname] completions bash)"
fi
else
# Tool not installed - provide platform-specific instructions
echo "[toolname] not installed."
if [[ "$(uname)" == "Darwin" ]]; then
echo "Install with: brew install [toolname]"
elif [[ -f /etc/debian_version ]]; then
echo "Install with: apt-get install [toolname]"
else
echo "Visit: https://[toolname].io/install"
fi
fi
EOF
```
5. **Run bootstrap**: `~/.dotfiles/script/bootstrap`
6. **Test in new shell**: `exec $SHELL` or open new terminal
**Auto-sourced at shell startup (`.sh`/`.zsh` extensions)**:
**Manual execution (no `.sh` extension or in `bin/`)**:
**Installation Detection**:
```bash
if command -v toolname &> /dev/null; then
# Configure
else
# Installation instructions
fi
```
**Platform Detection**:
```bash
if [[ "$(uname)" == "Darwin" ]]; then
# macOS
elif [[ -f /etc/debian_version ]]; then
# Debian/Ubuntu
else
# Generic Linux
fi
```
**Shell Detection**:
```bash
if [[ -n "$ZSH_VERSION" ]]; then
# Zsh-specific
elif [[ -n "$BASH_VERSION" ]]; then
# Bash-specific
fi
```
**Lazy Loading** (for heavy tools like nvm):
```bash
nvm() {
unset -f nvm
source "$NVM_DIR/nvm.sh"
nvm "$@"
}
```
**PATH Management**:
```bash
export PATH="/new/path:$PATH" # Prepend (higher priority)
export PATH="$PATH:/new/path" # Append (lower priority)
```
**Key Issue**: tmux freezes environment variables when sessions start. SSH-related variables (`SSH_AUTH_SOCK`, `SSH_CLIENT`, `SSH_CONNECTION`) become stale.
**Solution Pattern**:
```bash
export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock"
if [[ -n "$TMUX" ]]; then
tmux setenv -t "$SESSION_NAME" SSH_AUTH_SOCK "$SSH_AUTH_SOCK"
fi
```
**Refresh Function**:
```bash
refresh-ssh() {
if [[ -n "$TMUX" ]]; then
export SSH_AUTH_SOCK=$(tmux showenv SSH_AUTH_SOCK | cut -d= -f2-)
echo "SSH environment refreshed"
fi
}
```
**Check load order**:
```bash
find ~/.dotfiles -name "*.sh" -o -name "*.zsh" | \
grep -v "bin/" | sort
```
**Test shell startup**:
```bash
bash -x ~/.bashrc 2>&1 | less
zsh -x ~/.zshrc 2>&1 | less
```
**Emergency access when dotfiles break shell**:
```bash
ssh server bash --norc
ssh server sh
```
**Then fix the problem**:
```bash
mv ~/.dotfiles/problematic.sh ~/.dotfiles/problematic.sh.disabled
```
**Check symlinks**:
```bash
find ~ -maxdepth 1 -type l ! -exec test -e {} \; -delete # Clean broken
ls -la ~/.[config-name] # Check specific
```
**Verify tool installation**:
```bash
command -v toolname
which toolname
```
**Check tmux environment**:
```bash
echo $TMUX # Check if in tmux
tmux showenv | grep SSH # Compare with env
ssh-add -l # Test SSH agent
```
1. **Never commit secrets** - use environment variables or secure storage
2. **Check file permissions** - especially for SSH keys
3. **Review sourced files** - be cautious with third-party scripts
4. **Use `command -v` over `which`** - more reliable and POSIX compliant
**Tool not loading**:
1. Verify `.sh`/`.zsh` extension for auto-sourced files
2. Check executable: `chmod +x file.sh`
3. Check syntax: `bash -n file.sh`
4. Verify installation: `command -v toolname`
**Auto-sourcing breaks shell startup**:
1. Find problematic script: `bash -x ~/.bashrc`
2. Remove `.sh` extension or move to `bin/`
3. Use emergency access if locked out
**PATH issues**:
1. Check: `echo $PATH | tr ':' '\n'`
2. Find duplicates: `echo $PATH | tr ':' '\n' | sort | uniq -d`
3. Remember: Earlier entries take precedence
**Adding neovim configuration**:
```bash
mkdir ~/.dotfiles/nvim
touch ~/.dotfiles/nvim/dot.config/nvim/init.lua
~/.dotfiles/script/bootstrap
```
**Adding kubectl with lazy loading**:
```bash
mkdir ~/.dotfiles/kubectl
cat > ~/.dotfiles/kubectl/load.sh << 'EOF'
#!/usr/bin/env bash
if command -v kubectl &> /dev/null; then
alias k='kubectl'
kubectl() {
unalias k
unset -f kubectl
source <(kubectl completion bash)
kubectl "$@"
}
fi
EOF
```
**Creating manual utility script**:
```bash
cat > ~/.dotfiles/bin/backup-dotfiles << 'EOF'
#!/usr/bin/env bash
tar czf ~/dotfiles-backup-$(date +%Y%m%d).tar.gz ~/.dotfiles
EOF
chmod +x ~/.dotfiles/bin/backup-dotfiles
```
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/dotfiles-repository-manager/raw