Bring .zshrc up to the current machine config (portable paths), ship homelab/ansible shell helpers, shared Cursor rules/skills, and an install.sh so Irina can clone and run ./install.sh --ira.
136 lines
4.0 KiB
Bash
Executable File
136 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Install shared Levkin machine config from this repo onto the current Mac.
|
|
# Safe to re-run. Does not overwrite ~/.zshrc.local or secrets.
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
|
BACKUP_DIR="${BACKUP_DIR:-$HOME/.dotfiles-backup-$(date +%Y%m%d-%H%M%S)}"
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: ./install.sh [--ira] [--no-cursor] [--no-zsh] [--dry-run]
|
|
|
|
--ira Print Irina follow-up steps (clone personal-scripts, Gmail app password)
|
|
--no-cursor Skip ~/.cursor rules/skills/mcp example
|
|
--no-zsh Skip ~/.zshrc and ~/.p10k.zsh
|
|
--dry-run Show actions only
|
|
EOF
|
|
}
|
|
|
|
DO_ZSH=1
|
|
DO_CURSOR=1
|
|
IRA=0
|
|
DRY=0
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--ira) IRA=1 ;;
|
|
--no-cursor) DO_CURSOR=0 ;;
|
|
--no-zsh) DO_ZSH=0 ;;
|
|
--dry-run) DRY=1 ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
run() {
|
|
if [[ "$DRY" -eq 1 ]]; then
|
|
echo "+ $*"
|
|
else
|
|
"$@"
|
|
fi
|
|
}
|
|
|
|
backup_if_exists() {
|
|
local path="$1"
|
|
if [[ -e "$path" || -L "$path" ]]; then
|
|
run mkdir -p "$BACKUP_DIR"
|
|
run mv "$path" "$BACKUP_DIR/$(basename "$path")"
|
|
echo "Backed up $path → $BACKUP_DIR/"
|
|
fi
|
|
}
|
|
|
|
link_file() {
|
|
local src="$1" dest="$2"
|
|
if [[ -L "$dest" ]] && [[ "$(readlink "$dest")" == "$src" ]]; then
|
|
echo "OK (already linked): $dest"
|
|
return 0
|
|
fi
|
|
backup_if_exists "$dest"
|
|
run ln -s "$src" "$dest"
|
|
echo "Linked $dest → $src"
|
|
}
|
|
|
|
copy_tree_merge() {
|
|
local src="$1" dest="$2"
|
|
run mkdir -p "$dest"
|
|
# Copy files; do not delete extras already on the machine
|
|
if [[ "$DRY" -eq 1 ]]; then
|
|
echo "+ rsync -a $src/ $dest/"
|
|
else
|
|
rsync -a "$src/" "$dest/"
|
|
fi
|
|
echo "Synced $src → $dest"
|
|
}
|
|
|
|
echo "dotfiles root: $ROOT"
|
|
|
|
if [[ "$DO_ZSH" -eq 1 ]]; then
|
|
link_file "$ROOT/.zshrc" "$HOME/.zshrc"
|
|
link_file "$ROOT/.p10k.zsh" "$HOME/.p10k.zsh"
|
|
if [[ ! -f "$HOME/.zshrc.local" ]]; then
|
|
run cp "$ROOT/zsh/zshrc.local.example" "$HOME/.zshrc.local"
|
|
echo "Created ~/.zshrc.local from example (edit as needed)"
|
|
fi
|
|
# Global gitleaks pre-commit (optional)
|
|
if [[ -x "$ROOT/scripts/git-hooks/install.sh" ]]; then
|
|
if [[ "$DRY" -eq 1 ]]; then
|
|
echo "+ $ROOT/scripts/git-hooks/install.sh"
|
|
else
|
|
"$ROOT/scripts/git-hooks/install.sh" || echo "git-hooks install skipped/failed (non-fatal)"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [[ "$DO_CURSOR" -eq 1 ]]; then
|
|
run mkdir -p "$HOME/.cursor/rules" "$HOME/.cursor/skills"
|
|
copy_tree_merge "$ROOT/cursor/rules" "$HOME/.cursor/rules"
|
|
copy_tree_merge "$ROOT/cursor/skills" "$HOME/.cursor/skills"
|
|
if [[ ! -f "$HOME/.cursor/mcp.json" && -f "$ROOT/cursor/mcp.json.example" ]]; then
|
|
run cp "$ROOT/cursor/mcp.json.example" "$HOME/.cursor/mcp.json"
|
|
echo "Installed ~/.cursor/mcp.json from example (edit if needed)"
|
|
elif [[ -f "$HOME/.cursor/mcp.json" ]]; then
|
|
echo "Left existing ~/.cursor/mcp.json alone (see cursor/mcp.json.example)"
|
|
fi
|
|
fi
|
|
|
|
mkdir -p "$HOME/Documents/code" 2>/dev/null || true
|
|
|
|
cat <<EOF
|
|
|
|
Done.
|
|
Reload shell: exec zsh (or: source ~/.zshrc)
|
|
Homelab help: hhlp
|
|
Personal make: mps (after cloning personal-scripts)
|
|
EOF
|
|
|
|
if [[ "$IRA" -eq 1 ]]; then
|
|
cat <<'EOF'
|
|
|
|
── Irina next steps ──────────────────────────────────────────
|
|
1. Vaultwarden → "Gmail App Password (Ira)" (create Google App Password)
|
|
2. Clone household scripts:
|
|
git clone gitea@git.levkin.ca:ilia/personal-scripts.git ~/Documents/code/personal-scripts
|
|
(HTTPS: https://git.levkin.ca/ilia/personal-scripts.git as ira)
|
|
3. Optional infra clone (for hsp / mk ping — not required for Gmail):
|
|
git clone gitea@git.levkin.ca:ilia/ansible.git ~/Documents/code/ansible
|
|
4. Optional family docs:
|
|
git clone gitea@git.levkin.ca:ilia/levkin.git ~/Documents/code/levkin
|
|
5. In personal-scripts:
|
|
cp .env.irina.example .env.irina && chmod 600 .env.irina
|
|
# fill GMAIL_ADDRESS / GMAIL_APP_PASSWORD
|
|
6. Open personal-scripts (or ansible) in Cursor and paste the prompt from:
|
|
docs/irina-cursor-onboarding-prompt.md
|
|
EOF
|
|
fi
|