This commit is contained in:
Ben Kyd
2026-03-11 13:33:25 +00:00
parent aa479dc6b0
commit e8994b77f1
252 changed files with 111 additions and 78 deletions

View File

@@ -1,6 +1,24 @@
# Dotfiles
Mirrors `$HOME`. Symlinked via `bootstrap.sh`.
Filesystem overlay. Structure mirrors actual paths on disk.
```
dotfiles/
home/benk/ -> symlinked into $HOME
.config/nvim/
.config/fish/
.config/wezterm/
.tmux.conf
.vimrc
...
etc/ -> copied into /etc (prompted, needs sudo)
fstab
nginx/nginx.conf
packages/ -> package lists for brew/yay
bootstrap.sh -> does everything
```
## Usage
```
git clone git@github.com:benkyd/dotfiles.git ~/dotfiles
@@ -8,11 +26,11 @@ cd ~/dotfiles
./bootstrap.sh
```
The bootstrap script will:
1. Detect your OS (macOS or Arch Linux)
2. Optionally install packages (Homebrew on macOS, yay on Arch)
3. Install tmux plugin manager and fisher (fish plugin manager)
4. Symlink all dotfiles into `$HOME` (existing files backed up to `~/dotfiles.bak/`)
5. Optionally copy system configs from `etc/` to `/etc/` (with sudo, prompted)
The bootstrap will:
1. Detect OS (macOS / Arch)
2. Optionally install packages (Homebrew or yay)
3. Install oh-my-fish, fisher, tmux plugin manager
4. Symlink `home/benk/` into `$HOME`
5. Optionally copy `etc/` to `/etc` (prompted)
Works on both macOS and Linux — wezterm, tmux, and fish auto-detect the platform.
Existing files are backed up to `~/dotfiles.bak/`.

View File

@@ -2,13 +2,50 @@
set -euo pipefail
DOTFILES_DIR="$(cd "$(dirname "$0")" && pwd)"
HOME_DIR="$HOME"
BACKUP_DIR="$HOME/dotfiles.bak"
USER="$(whoami)"
usage() {
echo "Usage: ./bootstrap.sh [--pull]"
echo ""
echo " (no args) Install packages, sync repo -> system"
echo " --pull Sync system -> repo (pull changes back)"
exit 0
}
# --- Pull mode: copy live files back into the repo ---
pull_back() {
OVERLAY_HOME="$DOTFILES_DIR/home/$USER"
if [ ! -d "$OVERLAY_HOME" ]; then
OVERLAY_HOME="$DOTFILES_DIR/home/benk"
fi
echo "==> Pulling home files back into repo..."
rsync -av --itemize-changes --existing --update \
"$HOME/" "$OVERLAY_HOME/"
echo ""
if [ -d "$DOTFILES_DIR/etc" ]; then
echo "==> Pulling /etc files back into repo..."
sudo rsync -av --itemize-changes --existing --update \
/etc/ "$DOTFILES_DIR/etc/"
echo ""
fi
echo "Done. Review changes with 'git diff' then commit."
exit 0
}
if [[ "${1:-}" == "--pull" ]]; then
pull_back
elif [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
usage
fi
echo "Ben's dotfiles"
echo "=============="
echo "Dotfiles dir: $DOTFILES_DIR"
echo "Home dir: $HOME_DIR"
echo "Repo: $DOTFILES_DIR"
echo "User: $USER"
echo ""
# --- Detect OS ---
@@ -62,94 +99,70 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
fi
echo ""
# --- tmux plugin manager ---
# --- Shell tooling ---
echo "==> Setting up shell tooling..."
# tmux plugin manager
if [ ! -d "$HOME/.tmux/plugins/tpm" ]; then
echo "==> Installing tmux plugin manager..."
echo " Installing tmux plugin manager..."
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
echo " Done. Run <C-b>I in tmux to install plugins."
echo ""
else
echo " ok tmux plugin manager"
fi
# --- fish plugin manager ---
# oh-my-fish
if command -v fish &>/dev/null; then
if ! fish -c "type -q fisher" 2>/dev/null; then
echo "==> Installing fisher (fish plugin manager)..."
fish -c "curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher"
echo ""
fi
fi
# --- $HOME symlinks ---
echo "==> Symlinking home files..."
find "$DOTFILES_DIR" -maxdepth 1 -name '.*' -not -name '.git' -not -name '.gitignore' -not -name '.gitmodules' | while read -r src; do
item="$(basename "$src")"
dst="$HOME_DIR/$item"
if [ -L "$dst" ] && [ "$(readlink "$dst")" = "$src" ]; then
echo " ok $item"
continue
fi
if [ -e "$dst" ] || [ -L "$dst" ]; then
backup="$BACKUP_DIR/$item"
mkdir -p "$(dirname "$backup")"
mv "$dst" "$backup"
echo " bak $item -> dotfiles.bak/$item"
fi
ln -s "$src" "$dst"
echo " ln $item"
done
if [ -d "$DOTFILES_DIR/pictures" ]; then
dst="$HOME_DIR/pictures"
src="$DOTFILES_DIR/pictures"
if [ -L "$dst" ] && [ "$(readlink "$dst")" = "$src" ]; then
echo " ok pictures"
if [ ! -d "$HOME/.local/share/omf" ]; then
echo " Installing oh-my-fish..."
curl -L https://get.oh-my.fish | fish
else
if [ -e "$dst" ] || [ -L "$dst" ]; then
mv "$dst" "$BACKUP_DIR/pictures"
echo " bak pictures -> dotfiles.bak/pictures"
fi
ln -s "$src" "$dst"
echo " ln pictures"
echo " ok oh-my-fish"
fi
# fisher
if ! fish -c "type -q fisher" 2>/dev/null; then
echo " Installing fisher (fish plugin manager)..."
fish -c "curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher"
else
echo " ok fisher"
fi
fi
echo ""
# --- /etc copies ---
# --- Overlay: home/benk/ -> $HOME ---
OVERLAY_HOME="$DOTFILES_DIR/home/$USER"
if [ ! -d "$OVERLAY_HOME" ]; then
echo "WARNING: No home overlay for user '$USER', falling back to home/benk/"
OVERLAY_HOME="$DOTFILES_DIR/home/benk"
fi
echo "==> Syncing $OVERLAY_HOME -> $HOME"
mkdir -p "$BACKUP_DIR/home"
rsync -av --itemize-changes --backup --backup-dir="$BACKUP_DIR/home" \
"$OVERLAY_HOME/" "$HOME/"
echo ""
# --- Overlay: etc/ -> /etc ---
if [ -d "$DOTFILES_DIR/etc" ]; then
etc_files=$(find "$DOTFILES_DIR/etc" -type f 2>/dev/null)
if [ -n "$etc_files" ]; then
echo "==> System config files found in etc/"
echo "==> System config files in etc/:"
echo "$etc_files" | while read -r src; do
rel="${src#$DOTFILES_DIR/}"
echo " /$rel"
echo " /${src#$DOTFILES_DIR/}"
done
echo ""
read -p "Copy system configs to /etc? This requires sudo. [y/N] " -n 1 -r
read -p "Sync to /etc? Requires sudo. [y/N] " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "$etc_files" | while read -r src; do
rel="${src#$DOTFILES_DIR/}"
dst="/$rel"
if [ -f "$dst" ]; then
backup="$BACKUP_DIR/$rel"
sudo mkdir -p "$(dirname "$backup")"
sudo cp "$dst" "$backup"
echo " bak /$rel -> dotfiles.bak/$rel"
fi
sudo mkdir -p "$(dirname "$dst")"
sudo cp "$src" "$dst"
echo " cp $rel"
done
mkdir -p "$BACKUP_DIR/etc"
sudo rsync -av --itemize-changes --backup --backup-dir="$BACKUP_DIR/etc" \
"$DOTFILES_DIR/etc/" /etc/
echo " Originals backed up to ~/dotfiles.bak/etc/"
else
echo " Skipped."
fi
@@ -157,4 +170,4 @@ if [ -d "$DOTFILES_DIR/etc" ]; then
fi
echo ""
echo "Done. Backup at ~/dotfiles.bak/ (if anything was moved)"
echo "Done. Backups at ~/dotfiles.bak/"

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 679 B

After

Width:  |  Height:  |  Size: 679 B

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 689 B

View File

Before

Width:  |  Height:  |  Size: 551 B

After

Width:  |  Height:  |  Size: 551 B

View File

Before

Width:  |  Height:  |  Size: 501 B

After

Width:  |  Height:  |  Size: 501 B

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 719 B

View File

Before

Width:  |  Height:  |  Size: 633 B

After

Width:  |  Height:  |  Size: 633 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 751 B

After

Width:  |  Height:  |  Size: 751 B

View File

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 157 B

After

Width:  |  Height:  |  Size: 157 B

View File

Before

Width:  |  Height:  |  Size: 156 B

After

Width:  |  Height:  |  Size: 156 B

View File

Before

Width:  |  Height:  |  Size: 157 B

After

Width:  |  Height:  |  Size: 157 B

View File

Before

Width:  |  Height:  |  Size: 156 B

After

Width:  |  Height:  |  Size: 156 B

View File

Before

Width:  |  Height:  |  Size: 157 B

After

Width:  |  Height:  |  Size: 157 B

View File

Before

Width:  |  Height:  |  Size: 156 B

After

Width:  |  Height:  |  Size: 156 B

View File

Before

Width:  |  Height:  |  Size: 161 B

After

Width:  |  Height:  |  Size: 161 B

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 485 B

After

Width:  |  Height:  |  Size: 485 B

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 449 B

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 450 B

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 383 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Some files were not shown because too many files have changed in this diff Show More