commit 0838f1cf8c914bde0a8eaa263770c997e3366f91 Author: David F Glidden Date: Sun Jul 27 13:17:01 2025 +0200 Initial commit: Complete macOS dotfiles system 🖖 Features: - Master 'engage' script for one-command setup - 120+ CLI tools via Homebrew - 40+ Applications (casks + MAS apps) - Complete macOS system configuration - Security hardening and privacy settings - Obsidian knowledge vault setup - Comprehensive backup strategies - Automated symlink management Live long and prosper\! 🚀 🤖 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1be83c --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +# Dotfiles .gitignore + +# Never commit sensitive files +*.key +*.pem +*.p12 +*.pfx +id_rsa* +id_dsa* +id_ecdsa* +id_ed25519* + +# Backup directories (contain sensitive data) +backups/ +.dotfiles-backup/ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Application specific +.vscode/ +*.log + +# Temporary files +*.tmp +*.swp +*.swo +*~ + +# Mackup backup location +mackup-backup/ + +# Local environment files +.env +.env.local + +# Obsidian vault files (these are synced via iCloud) +*.obsidian/workspace +*.obsidian/workspace.json +*.obsidian/cache/ + +# SSH and GPG (use encrypted backups instead) +ssh/id_* +ssh/known_hosts +gnupg/ + +# Application-specific secrets +.aws/ +.gcloud/ +.docker/config.json + +# History files (use backup scripts instead) +.zsh_history +.bash_history \ No newline at end of file diff --git a/.mackup.cfg b/.mackup.cfg new file mode 100644 index 0000000..baa6763 --- /dev/null +++ b/.mackup.cfg @@ -0,0 +1,24 @@ +# Mackup configuration +# https://github.com/lra/mackup + +# Storage engine to use +[storage] +engine = file_system +path = dotfiles/mackup-backup + +# Apps to sync (uncomment to enable) +# [applications_to_sync] +# bartender +# hazel +# launchbar +# iterm2 +# karabiner-elements +# git +# vim +# zsh + +# Apps to ignore (if using sync all) +[applications_to_ignore] +# List apps you don't want mackup to handle +gnupg +ssh \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..874f476 --- /dev/null +++ b/.npmrc @@ -0,0 +1,25 @@ +# NPM Configuration +# This file will be symlinked to ~/.npmrc + +# Set npm init defaults +init-author-name=David F Glidden +init-author-email=d@davidglidden.eu +init-license=MIT + +# Better npm defaults +save-exact=true +progress=false + +# Performance improvements +fetch-retries=2 +fetch-retry-mintimeout=10000 +fetch-retry-maxtimeout=60000 + +# Security +audit-level=moderate + +# Optional: Custom registry (uncomment if needed) +# registry=https://registry.npmjs.org/ + +# Optional: Scoped registries for organizations +# @mycompany:registry=https://npm.mycompany.com/ \ No newline at end of file diff --git a/APP_CONFIGS.md b/APP_CONFIGS.md new file mode 100644 index 0000000..5c2f764 --- /dev/null +++ b/APP_CONFIGS.md @@ -0,0 +1,117 @@ +# Application Configuration Management + +This document explains how application configurations are managed in this dotfiles repository. + +## Strategy Overview + +We use a hybrid approach: +1. **Direct file management** for simple configs (.npmrc, .ssh/config) +2. **Custom backup scripts** for complex macOS apps (LaunchBar, Hazel, Bartender) +3. **Mackup** as an optional automated solution + +## Configuration Locations + +### Simple Configs (Symlinked) +- `.npmrc` → `~/dotfiles/.npmrc` +- `.ssh/config` → `~/dotfiles/ssh/config` (template) + +### macOS Application Configs +- **LaunchBar**: `~/Library/Application Support/LaunchBar/` +- **Hazel**: `~/Library/Application Support/Hazel/` +- **Bartender**: `~/Library/Preferences/com.surteesstudios.Bartender.plist` + +## Backup Methods + +### Method 1: Manual Script (Recommended) +```bash +# Run the backup script +~/dotfiles/macos-apps/backup-app-configs.sh +``` + +This script: +- Backs up LaunchBar configuration and custom actions +- Exports Hazel rules database +- Saves Bartender preferences +- Converts plists to readable XML format + +### Method 2: Mackup (Automated) +```bash +# First time setup +mackup backup + +# On new machine +mackup restore +``` + +Mackup advantages: +- Automatic detection of supported apps +- Creates symlinks for live sync +- Supports 300+ applications + +## SSH Config + +We maintain a template at `~/dotfiles/ssh/config.example` with: +- Sanitized host configurations +- Best practice settings +- Examples for common scenarios + +**Never commit**: +- Private keys +- Actual hostnames/IPs +- Usernames +- Sensitive paths + +## NPM Configuration + +The `.npmrc` file includes: +- Author defaults for `npm init` +- Performance optimizations +- Security settings +- Registry configuration (if needed) + +## Restore Process + +### Quick Restore +1. Install applications via Homebrew: + ```bash + brew bundle install + ``` + +2. Restore configs: + ```bash + # NPM + ln -sf ~/dotfiles/.npmrc ~/.npmrc + + # SSH (edit first!) + cp ~/dotfiles/ssh/config.example ~/.ssh/config + chmod 600 ~/.ssh/config + + # macOS apps + ~/dotfiles/macos-apps/restore-app-configs.sh + ``` + +### Using Mackup +```bash +# After installing apps +mackup restore +``` + +## Adding New Applications + +To add config management for a new app: + +1. **Find config location**: + ```bash + find ~/Library -name "*AppName*" -type d + ``` + +2. **Add to backup script** or configure Mackup + +3. **Document** the process here + +## Troubleshooting + +- **Permissions issues**: Some apps need to be quit before restoring +- **License/authorization**: Most apps need re-activation after restore +- **Preferences cache**: May need to `killall cfprefsd` after restoring plists +- **Mackup conflicts**: Check `~/.mackup/` for conflicting symlinks \ No newline at end of file diff --git a/BACKUP_STRATEGY.md b/BACKUP_STRATEGY.md new file mode 100644 index 0000000..62f5fcb --- /dev/null +++ b/BACKUP_STRATEGY.md @@ -0,0 +1,98 @@ +# Dotfiles Backup Strategy + +## Overview + +This dotfiles repository uses a multi-layered backup approach: + +1. **Version Control (Git)** - For non-sensitive configuration files +2. **Encrypted Backups** - For sensitive files (SSH keys, credentials) +3. **Historical Backups** - For shell history and evolving configs +4. **Symlinks** - To maintain live connections to config files + +## What Gets Backed Up Where + +### In Git (Public) +- Shell configurations (`.zshrc`, `.bashrc`) +- Git config (sanitized) +- Vim configuration +- Shell scripts and utilities +- Application configs (non-sensitive) + +### Encrypted Backups (Private) +- SSH private keys +- AWS/Cloud credentials +- API tokens +- Password databases + +### Historical Backups +- Shell history (daily snapshots, 7-day retention) +- Checkpoint versions of frequently edited configs + +## Backup Commands + +### 1. Quick Backup (non-sensitive files) +```bash +~/dotfiles/bin/backup-dotfiles +``` + +### 2. Sensitive Files Backup (encrypted) +```bash +~/dotfiles/backup-scripts/backup-sensitive.sh +``` + +### 3. Manual History Checkpoint +```bash +# In your shell +history_checkpoint +``` + +## Restore Process + +### On a New Machine + +1. **Clone dotfiles**: + ```bash + git clone https://github.com/yourusername/dotfiles.git ~/dotfiles + ``` + +2. **Run installation script** (once created): + ```bash + ~/dotfiles/install.sh + ``` + +3. **Restore sensitive files** (if you have backups): + ```bash + # Decrypt SSH keys + gpg -d ~/dotfiles/backups/ssh_[timestamp].tar.gz.gpg | tar -xzf - + ``` + +4. **Set up application-specific configs**: + - Run `mackup restore` for application preferences + - Import browser bookmarks/passwords + - Configure cloud service credentials + +## Security Best Practices + +1. **Never commit**: + - Private keys + - Passwords or tokens + - Personal information + +2. **Use `.gitignore`** properly: + ``` + backups/ + *.key + *.pem + secrets/ + ``` + +3. **Encrypt sensitive backups** with GPG +4. **Store encrypted backups** in a secure location (not in git) +5. **Rotate keys** regularly + +## Maintenance + +- Run backup scripts weekly +- Review and clean old backups monthly +- Update scripts as your setup evolves +- Test restore process periodically \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..13d9619 --- /dev/null +++ b/README.md @@ -0,0 +1,218 @@ +# 🖖 David's Dotfiles - "Engage!" + +> *"Make it so!"* - A complete macOS setup system inspired by Star Trek's efficiency and elegance. + +From zero to fully configured macOS in minutes. This dotfiles repository provides a comprehensive, automated setup for developers, writers, and knowledge workers. + +## 🚀 Quick Start + +**One command to rule them all:** + +```bash +git clone https://github.com/davidglidden/dotfiles.git ~/dotfiles && ~/dotfiles/engage +``` + +That's it! The `engage` script will guide you through a complete system setup. + +## ✨ What This System Provides + +### 📦 **Software Management** +- **120+ CLI tools** via Homebrew (development, media, security) +- **40+ Applications** via casks (productivity, creativity, utilities) +- **20+ Mac App Store apps** via `mas` (native macOS apps) + +### 🔧 **Configuration Management** +- **Shell setup**: Zsh with Antidote, Powerlevel10k, history sync +- **Development tools**: Git hooks, SSH templates, NPM config +- **Application configs**: LaunchBar, Hazel, Bartender, Karabiner +- **Obsidian vault**: Complete knowledge management system + +### 🖥️ **macOS System Configuration** +- **System preferences**: Dock, Finder, keyboard, security +- **Security hardening**: Firewall, privacy, authentication +- **Keyboard shortcuts**: Mission Control, app shortcuts +- **Developer settings**: Safari dev tools, Terminal enhancements + +### 🛡️ **Backup & Security Strategy** +- **Encrypted backups** for sensitive files (SSH keys, credentials) +- **History management** with daily snapshots and retention +- **Git hooks** for security and code quality +- **Application data** backup and restore scripts + +## 📁 Repository Structure + +``` +dotfiles/ +├── engage # 🖖 Master installation script +├── Brewfile # Package management (brew/cask/mas) +├── README.md # This file +├── .gitconfig # Git configuration +├── .npmrc # NPM defaults +├── .zshrc # Shell configuration +├── .vimrc # Vim configuration +├── bin/ # Custom scripts +│ ├── backup-dotfiles # Quick dotfiles backup +│ └── check-app-configs # Configuration status checker +├── git/ # Git configuration +│ └── hooks/ # Global git hooks +├── macos/ # macOS system configuration +│ ├── setup-macos.sh # Master macOS setup +│ ├── defaults.sh # System preferences +│ ├── security.sh # Security hardening +│ └── keyboard-shortcuts.sh # Custom shortcuts +├── macos-apps/ # macOS app configurations +│ └── backup-app-configs.sh # App settings backup +├── obsidian/ # Obsidian knowledge vault +│ ├── setup-obsidian.sh # Vault configuration +│ └── community-plugins.json # Essential plugins +├── scripts/ # Installation scripts +│ └── symlinks.sh # Dotfile linking +├── shell/ # Shell enhancements +│ └── history-sync.zsh # History management +└── ssh/ # SSH configuration + ├── config.example # SSH config template + └── README.md # SSH setup guide +``` + +## 🎯 Core Philosophy + +This system balances **automation** with **choice**: + +- **Smart defaults** that work out of the box +- **Interactive modes** for customization +- **Modular design** - use what you need +- **Security first** - encrypted backups, secure defaults +- **Documentation** - clear guides and examples + +Inspired by the best dotfiles repositories but designed for real-world complexity. + +## 📱 Essential Applications Included + +### Development +- **iTerm2** + **Kitty** - Terminal emulators +- **BBEdit** - Text editor with deep macOS integration +- **GitHub Desktop** - Git GUI +- **Docker** - Containerization + +### Productivity +- **Obsidian** - Knowledge management powerhouse +- **1Password** - Password management +- **LaunchBar** - Application launcher +- **Hazel** - Automated file organization +- **Drafts** - Quick capture and text processing + +### Utilities +- **Karabiner-Elements** - Keyboard customization +- **Bartender** - Menu bar organization +- **Keka** - Archive utility +- **Oversight** - Privacy monitoring +- **Signal** - Secure messaging + +### Creative & Media +- **VLC** - Media player +- **HandBrake** - Video transcoding +- **Transmit** - File transfer +- **Calibre** - E-book management + +## 🛠️ Advanced Usage + +### Manual Installation Steps + +If you prefer granular control: + +```bash +# 1. Install packages only +brew bundle install --file=~/dotfiles/Brewfile + +# 2. Set up dotfiles +~/dotfiles/scripts/symlinks.sh + +# 3. Configure macOS +~/dotfiles/macos/setup-macos.sh + +# 4. Set up applications +~/dotfiles/macos-apps/backup-app-configs.sh +``` + +### Customization + +**Modify the Brewfile** to add/remove applications: +```ruby +# Add new CLI tool +brew "your-tool" + +# Add new application +cask "your-app" + +# Add Mac App Store app +mas "App Name", id: 123456789 +``` + +**Customize macOS defaults** in `macos/defaults.sh`: +```bash +# Change dock position +defaults write com.apple.dock orientation -string "left" + +# Adjust key repeat speed +defaults write NSGlobalDomain KeyRepeat -int 1 +``` + +### Backup Strategy + +**Before making changes:** +```bash +# Backup current dotfiles +~/dotfiles/bin/backup-dotfiles + +# Backup macOS settings +~/dotfiles/macos/backup-defaults.sh + +# Backup sensitive files (encrypted) +~/dotfiles/backup-scripts/backup-sensitive.sh +``` + +## 🔐 Security Features + +- **SSH keys** encrypted with GPG +- **Firewall** enabled with stealth mode +- **Privacy settings** optimized +- **Git hooks** prevent secrets in commits +- **Secure defaults** for Safari and system +- **Application permissions** documented + +## 🧠 Obsidian Knowledge System + +Includes a sophisticated personal knowledge management setup: + +- **13 essential plugins** for advanced functionality +- **Template system** with Templater integration +- **Daily/weekly/monthly** review cycles +- **Christopher Alexander** pattern language philosophy +- **Multilingual support** (EN/ES/FR/CA) + +## 🤝 Contributing + +This is a personal dotfiles repository, but ideas and improvements are welcome: + +1. **Fork** the repository +2. **Create** a feature branch +3. **Test** thoroughly on a fresh macOS installation +4. **Submit** a pull request with clear description + +## 📜 License + +MIT License - Use, modify, and share freely. + +## 🙏 Acknowledgments + +Inspired by: +- [Mathias Bynens' dotfiles](https://github.com/mathiasbynens/dotfiles) +- [ptb/mac-setup](https://github.com/ptb/mac-setup) +- [Homebrew Bundle](https://github.com/Homebrew/homebrew-bundle) +- The Star Trek universe for the best command ever: **"Engage!"** + +--- + +**Live long and prosper!** 🖖 + +*Made with ❤️ for the macOS community* \ No newline at end of file diff --git a/backup-scripts/backup-sensitive.sh b/backup-scripts/backup-sensitive.sh new file mode 100755 index 0000000..4db8c63 --- /dev/null +++ b/backup-scripts/backup-sensitive.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# Backup script for sensitive dotfiles +# This handles files that shouldn't be stored directly in git + +set -euo pipefail + +DOTFILES_DIR="$HOME/dotfiles" +BACKUP_DIR="$DOTFILES_DIR/backups" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}Starting sensitive files backup...${NC}" + +# Create backup directory +mkdir -p "$BACKUP_DIR" + +# Function to backup a file/directory with encryption +backup_encrypted() { + local source="$1" + local name="$2" + + if [ -e "$source" ]; then + echo -e "${YELLOW}Backing up $name...${NC}" + tar -czf - "$source" | gpg --symmetric --cipher-algo AES256 -o "$BACKUP_DIR/${name}_${TIMESTAMP}.tar.gz.gpg" + echo -e "${GREEN}✓ $name backed up and encrypted${NC}" + else + echo -e "${RED}✗ $source not found${NC}" + fi +} + +# Backup SSH keys and config (encrypted) +backup_encrypted "$HOME/.ssh" "ssh" + +# Backup shell history +cp "$HOME/.zsh_history" "$BACKUP_DIR/zsh_history_${TIMESTAMP}" +echo -e "${GREEN}✓ Shell history backed up${NC}" + +# Create a sanitized SSH config for git +if [ -f "$HOME/.ssh/config" ]; then + echo -e "${YELLOW}Creating sanitized SSH config...${NC}" + # Remove sensitive host details but keep structure + sed -E 's/(HostName|User|IdentityFile) .*/\1 /' "$HOME/.ssh/config" > "$DOTFILES_DIR/ssh/config.example" + echo -e "${GREEN}✓ SSH config template created${NC}" +fi + +# List what needs manual backup +echo -e "\n${YELLOW}Remember to manually backup:${NC}" +echo "- Any private keys stored outside ~/.ssh" +echo "- Any credentials in ~/.aws, ~/.gcloud, etc." +echo "- Application-specific secrets" + +echo -e "\n${GREEN}Backup complete!${NC}" +echo -e "Encrypted backups stored in: $BACKUP_DIR" +echo -e "To decrypt: gpg -d file.tar.gz.gpg | tar -xzf -" \ No newline at end of file diff --git a/bin/README.md b/bin/README.md new file mode 100644 index 0000000..27161f5 --- /dev/null +++ b/bin/README.md @@ -0,0 +1,24 @@ +# Custom Scripts + +This directory contains custom scripts that will be symlinked to `~/bin`. + +## Setup + +1. The symlink script will link all scripts from this directory to `~/bin` +2. Make sure `~/bin` is in your PATH (add to `.zshrc`): + ```bash + export PATH="$HOME/bin:$PATH" + ``` + +## Adding New Scripts + +1. Create your script in `~/dotfiles/bin/` +2. Make it executable: `chmod +x script_name` +3. Run the symlink script to link it to `~/bin` + +## Script Guidelines + +- Start with proper shebang: `#!/usr/bin/env bash` or `#!/usr/bin/env zsh` +- Add help/usage information +- Use meaningful names +- Document what the script does \ No newline at end of file diff --git a/bin/backup-dotfiles b/bin/backup-dotfiles new file mode 100755 index 0000000..c7fff48 --- /dev/null +++ b/bin/backup-dotfiles @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Quick backup of important dotfiles + +set -euo pipefail + +DOTFILES_DIR="$HOME/dotfiles" +BACKUP_DIR="$DOTFILES_DIR/backups" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo -e "${GREEN}Backing up dotfiles...${NC}" + +# Create backup directory +mkdir -p "$BACKUP_DIR" + +# Files to backup +files=( + "$HOME/.zshrc" + "$HOME/.gitconfig" + "$HOME/.vimrc" + "$HOME/.ssh/config" + "$HOME/.config/karabiner/karabiner.json" +) + +# Create tarball +tar_file="$BACKUP_DIR/dotfiles_backup_${TIMESTAMP}.tar.gz" + +for file in "${files[@]}"; do + if [ -f "$file" ]; then + echo -e "${YELLOW}Adding: $file${NC}" + fi +done + +tar -czf "$tar_file" \ + --exclude="*.log" \ + --exclude=".git" \ + "${files[@]}" 2>/dev/null || true + +echo -e "${GREEN}Backup created: $tar_file${NC}" + +# Keep only last 10 backups +cd "$BACKUP_DIR" +ls -t dotfiles_backup_*.tar.gz | tail -n +11 | xargs -r rm + +echo -e "${GREEN}Done!${NC}" \ No newline at end of file diff --git a/bin/check-app-configs b/bin/check-app-configs new file mode 100755 index 0000000..6f2a990 --- /dev/null +++ b/bin/check-app-configs @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# Check for changes in application configurations + +set -euo pipefail + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +echo -e "${GREEN}Checking application configuration changes...${NC}\n" + +# Function to check if file has changed +check_config() { + local app_name="$1" + local source_path="$2" + local backup_path="$3" + + if [ ! -e "$source_path" ]; then + echo -e "${RED}✗ $app_name: Source not found${NC}" + return + fi + + if [ ! -e "$backup_path" ]; then + echo -e "${YELLOW}⚠ $app_name: No backup exists${NC}" + return + fi + + if diff -q "$source_path" "$backup_path" >/dev/null 2>&1; then + echo -e "${GREEN}✓ $app_name: Up to date${NC}" + else + echo -e "${YELLOW}⚠ $app_name: Has changes${NC}" + fi +} + +# Check each application +echo "Checking configurations..." + +# NPM +if [ -f ~/.npmrc ] && [ -f ~/dotfiles/.npmrc ]; then + check_config "NPM config" ~/.npmrc ~/dotfiles/.npmrc +fi + +# SSH +if [ -f ~/.ssh/config ]; then + echo -e "${YELLOW}! SSH config: Manual check required (contains sensitive data)${NC}" +fi + +# LaunchBar +if [ -d "$HOME/Library/Application Support/LaunchBar" ]; then + # Check if backup exists + if [ -d "$HOME/dotfiles/macos-apps/LaunchBar" ]; then + echo -e "${YELLOW}! LaunchBar: Run backup script to check for changes${NC}" + else + echo -e "${YELLOW}⚠ LaunchBar: No backup exists${NC}" + fi +fi + +# Hazel +if [ -f "$HOME/Library/Application Support/Hazel/hazelrules.db" ]; then + check_config "Hazel rules" \ + "$HOME/Library/Application Support/Hazel/hazelrules.db" \ + "$HOME/dotfiles/macos-apps/Hazel/hazelrules.db" +fi + +# Git config +check_config "Git config" ~/.gitconfig ~/dotfiles/git/.gitconfig + +echo -e "\n${GREEN}Check complete!${NC}" +echo -e "To backup changed configs, run: ${YELLOW}~/dotfiles/macos-apps/backup-app-configs.sh${NC}" \ No newline at end of file diff --git a/engage b/engage new file mode 100755 index 0000000..818050f --- /dev/null +++ b/engage @@ -0,0 +1,333 @@ +#!/usr/bin/env bash +# 🖖 ENGAGE - Complete macOS dotfiles installation +# "Make it so!" - Captain Jean-Luc Picard + +set -euo pipefail + +# Colors and symbols +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +MAGENTA='\033[0;35m' +CYAN='\033[0;36m' +BOLD='\033[1m' +NC='\033[0m' + +# Star Trek ASCII art +cat << 'EOF' + ______ + | ____| + | |__ _ __ __ _ __ _ __ _ ___ + | __| | '_ \ / _` |/ _` |/ _` |/ _ \ + | |____| | | | (_| | (_| | (_| | __/ + |______|_| |_|\__, |\__,_|\__, |\___| + __/ | __/ | + |___/ |___/ + +🖖 "Engage!" - Complete macOS Setup +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +EOF + +echo "" +echo -e "${CYAN}${BOLD}Welcome to the Universal macOS Setup System${NC}" +echo -e "${YELLOW}From zero to fully configured in minutes...${NC}" +echo "" + +# Check if we're on macOS +if [[ "$OSTYPE" != "darwin"* ]]; then + echo -e "${RED}❌ This script is designed for macOS only${NC}" + exit 1 +fi + +# Function to check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Function to ask yes/no with default +ask() { + local prompt="$1" + local default="${2:-y}" + local response + + while true; do + if [[ "$default" == "y" ]]; then + read -p "$prompt (Y/n): " response + response=${response:-y} + else + read -p "$prompt (y/N): " response + response=${response:-n} + fi + + case "$response" in + [Yy]*) return 0 ;; + [Nn]*) return 1 ;; + *) echo "Please answer yes or no." ;; + esac + done +} + +# Phase indicator +phase() { + echo "" + echo -e "${MAGENTA}${BOLD}━━━ $1 ━━━${NC}" +} + +# Success indicator +success() { + echo -e "${GREEN}✅ $1${NC}" +} + +# Warning indicator +warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +# Error indicator +error() { + echo -e "${RED}❌ $1${NC}" +} + +# Progress indicator +progress() { + echo -e "${BLUE}🔄 $1${NC}" +} + +# ============================================================================= +# Pre-flight checks +# ============================================================================= + +phase "Pre-flight Systems Check" + +# Check for Command Line Tools +if ! command_exists git; then + progress "Installing Xcode Command Line Tools..." + xcode-select --install + echo "Please complete the Command Line Tools installation and run this script again." + exit 1 +fi +success "Command Line Tools installed" + +# Check for Homebrew +if ! command_exists brew; then + progress "Installing Homebrew..." + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + # Add Homebrew to PATH for this session + if [[ -f /opt/homebrew/bin/brew ]]; then + eval "$(/opt/homebrew/bin/brew shellenv)" + elif [[ -f /usr/local/bin/brew ]]; then + eval "$(/usr/local/bin/brew shellenv)" + fi +fi +success "Homebrew ready" + +# ============================================================================= +# Installation Menu +# ============================================================================= + +phase "Mission Configuration" + +echo "Select your mission parameters:" +echo "" + +# Installation options +INSTALL_PACKAGES=false +INSTALL_APPS=false +SETUP_DOTFILES=false +SETUP_MACOS=false +SETUP_SECURITY=false +BACKUP_CURRENT=false + +if ask "📦 Install CLI tools and development packages?"; then + INSTALL_PACKAGES=true +fi + +if ask "🖥️ Install applications (casks + Mac App Store)?"; then + INSTALL_APPS=true +fi + +if ask "🔗 Set up dotfiles and symlinks?"; then + SETUP_DOTFILES=true +fi + +if ask "⚙️ Configure macOS system preferences?"; then + SETUP_MACOS=true +fi + +if ask "🛡️ Apply security hardening?"; then + SETUP_SECURITY=true +fi + +if ask "💾 Backup current configurations first?" n; then + BACKUP_CURRENT=true +fi + +echo "" +echo -e "${CYAN}Mission parameters confirmed. Engaging...${NC}" + +# ============================================================================= +# Backup Phase +# ============================================================================= + +if [[ "$BACKUP_CURRENT" == true ]]; then + phase "Creating Backup" + + progress "Backing up current dotfiles..." + if [[ -f "$HOME/dotfiles/bin/backup-dotfiles" ]]; then + bash "$HOME/dotfiles/bin/backup-dotfiles" + fi + + progress "Backing up macOS settings..." + if [[ -f "$HOME/dotfiles/macos/backup-defaults.sh" ]]; then + bash "$HOME/dotfiles/macos/backup-defaults.sh" + fi + + success "Backup complete" +fi + +# ============================================================================= +# Package Installation Phase +# ============================================================================= + +if [[ "$INSTALL_PACKAGES" == true ]]; then + phase "Installing Development Tools" + + progress "Updating Homebrew..." + brew update + + progress "Installing command-line tools..." + brew bundle install --file="$HOME/dotfiles/Brewfile" --no-mas --no-cask + + success "CLI tools installed" +fi + +# ============================================================================= +# Application Installation Phase +# ============================================================================= + +if [[ "$INSTALL_APPS" == true ]]; then + phase "Installing Applications" + + # Install Mac App Store CLI if not present + if ! command_exists mas; then + progress "Installing mas (Mac App Store CLI)..." + brew install mas + fi + + # Check if signed into Mac App Store + if ! mas account >/dev/null 2>&1; then + warning "Not signed into Mac App Store" + echo "Please sign in to the Mac App Store and run 'mas install' commands manually" + echo "Or run: brew bundle install --file=$HOME/dotfiles/Brewfile" + fi + + progress "Installing cask applications..." + brew bundle install --file="$HOME/dotfiles/Brewfile" --no-brew --no-mas + + if mas account >/dev/null 2>&1; then + progress "Installing Mac App Store applications..." + brew bundle install --file="$HOME/dotfiles/Brewfile" --no-brew --no-cask + fi + + success "Applications installed" +fi + +# ============================================================================= +# Dotfiles Configuration Phase +# ============================================================================= + +if [[ "$SETUP_DOTFILES" == true ]]; then + phase "Configuring Dotfiles" + + progress "Creating symlinks..." + bash "$HOME/dotfiles/scripts/symlinks.sh" + + progress "Setting up shell enhancements..." + # Reload shell configuration + if [[ -f "$HOME/.zshrc" ]]; then + source "$HOME/.zshrc" 2>/dev/null || true + fi + + progress "Setting up Obsidian configuration..." + if [[ -f "$HOME/dotfiles/obsidian/setup-obsidian.sh" ]]; then + bash "$HOME/dotfiles/obsidian/setup-obsidian.sh" + fi + + success "Dotfiles configured" +fi + +# ============================================================================= +# macOS Configuration Phase +# ============================================================================= + +if [[ "$SETUP_MACOS" == true ]]; then + phase "Configuring macOS System" + + if ask "Use interactive mode for system preferences?" y; then + bash "$HOME/dotfiles/macos/defaults-interactive.sh" + else + bash "$HOME/dotfiles/macos/defaults.sh" + fi + + success "macOS system configured" +fi + +# ============================================================================= +# Security Configuration Phase +# ============================================================================= + +if [[ "$SETUP_SECURITY" == true ]]; then + phase "Applying Security Configuration" + + progress "Hardening system security..." + bash "$HOME/dotfiles/macos/security.sh" + + progress "Setting up keyboard shortcuts..." + bash "$HOME/dotfiles/macos/keyboard-shortcuts.sh" + + success "Security configuration applied" +fi + +# ============================================================================= +# Mission Complete +# ============================================================================= + +phase "Mission Status Report" + +echo "" +echo -e "${GREEN}${BOLD}🎉 MISSION ACCOMPLISHED! 🎉${NC}" +echo "" +echo -e "${CYAN}Your macOS system has been successfully configured.${NC}" +echo "" +echo -e "${YELLOW}Final Steps:${NC}" +echo "1. 🔄 Restart your terminal or run: source ~/.zshrc" +echo "2. 🔐 Review SSH configuration: ~/.ssh/config" +echo "3. 🧩 Install Obsidian plugins manually (see ~/dotfiles/obsidian/)" +echo "4. 🔍 Review security settings in System Preferences" +echo "5. 🚀 Log out and back in for all changes to take effect" +echo "" + +if [[ "$INSTALL_APPS" == true ]]; then + echo -e "${YELLOW}Application Notes:${NC}" + echo "• Configure 1Password and import data" + echo "• Set up LaunchBar activation key" + echo "• Import Hazel rules if you have backups" + echo "• Configure Bartender menu bar layout" + echo "" +fi + +echo -e "${CYAN}${BOLD}\"Make it so!\" - Setup complete. 🖖${NC}" +echo "" + +# Optional: Open useful apps +if ask "Open useful applications to get started?" n; then + open -a "System Preferences" + open -a "iTerm" 2>/dev/null || open -a "Terminal" + if [[ -d "/Applications/1Password.app" ]]; then + open -a "1Password" + fi +fi + +echo -e "${GREEN}Live long and prosper! 🖖✨${NC}" \ No newline at end of file diff --git a/git/hooks/README.md b/git/hooks/README.md new file mode 100644 index 0000000..f7f6fdf --- /dev/null +++ b/git/hooks/README.md @@ -0,0 +1,28 @@ +# Git Hooks + +This directory contains global git hooks that can be used across all repositories. + +## Setup + +1. Configure git to use this directory for hooks: +```bash +git config --global core.hooksPath ~/dotfiles/git/hooks +``` + +2. Make hooks executable: +```bash +chmod +x ~/dotfiles/git/hooks/* +``` + +## Available Hooks + +- `pre-commit`: Run before each commit +- `commit-msg`: Validate commit messages +- `pre-push`: Run before pushing + +## Per-Repository Hooks + +To use repository-specific hooks instead of global ones: +```bash +git config --local core.hooksPath .git/hooks +``` \ No newline at end of file diff --git a/git/hooks/pre-commit b/git/hooks/pre-commit new file mode 100755 index 0000000..c42d64b --- /dev/null +++ b/git/hooks/pre-commit @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# Global pre-commit hook +# Runs checks before allowing a commit + +set -euo pipefail + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo "Running pre-commit checks..." + +# Check for debugging keywords +if git diff --cached --name-only | xargs grep -E "(console\.log|debugger|binding\.pry|TODO:|FIXME:|XXX:)" 2>/dev/null; then + echo -e "${YELLOW}Warning: Found debugging keywords or TODOs${NC}" + echo "Continue anyway? (y/n)" + read -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Check for large files (>5MB) +for file in $(git diff --cached --name-only); do + if [ -f "$file" ]; then + size=$(wc -c < "$file") + if [ $size -gt 5242880 ]; then + echo -e "${RED}Error: $file is larger than 5MB${NC}" + echo "Consider using Git LFS for large files" + exit 1 + fi + fi +done + +# Check for secrets (basic check) +if git diff --cached --name-only | xargs grep -E "(password|secret|token|api_key)\s*=\s*[\"'][^\"']+[\"']" 2>/dev/null; then + echo -e "${RED}Warning: Possible secrets detected!${NC}" + echo "Please review your changes carefully." + echo "Continue anyway? (y/n)" + read -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +echo -e "${GREEN}Pre-commit checks passed!${NC}" \ No newline at end of file diff --git a/macos-apps/backup-app-configs.sh b/macos-apps/backup-app-configs.sh new file mode 100755 index 0000000..ed113e6 --- /dev/null +++ b/macos-apps/backup-app-configs.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash +# Backup macOS application configurations + +set -euo pipefail + +DOTFILES_DIR="$HOME/dotfiles" +APPS_DIR="$DOTFILES_DIR/macos-apps" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +echo -e "${GREEN}Backing up macOS application configurations...${NC}" + +# Create directories +mkdir -p "$APPS_DIR"/{LaunchBar,Hazel,Bartender,preferences} + +# LaunchBar +if [ -d "$HOME/Library/Application Support/LaunchBar" ]; then + echo -e "${YELLOW}Backing up LaunchBar...${NC}" + # Configuration + cp -R "$HOME/Library/Application Support/LaunchBar/Configuration" "$APPS_DIR/LaunchBar/" 2>/dev/null || true + # Custom actions (exclude cache) + rsync -av --exclude="*.cache" --exclude="*.log" \ + "$HOME/Library/Application Support/LaunchBar/Actions" \ + "$APPS_DIR/LaunchBar/" 2>/dev/null || true + # Preferences + cp "$HOME/Library/Preferences/at.obdev.LaunchBar.plist" "$APPS_DIR/preferences/" 2>/dev/null || true + echo -e "${GREEN}✓ LaunchBar backed up${NC}" +fi + +# Hazel +if [ -d "$HOME/Library/Application Support/Hazel" ]; then + echo -e "${YELLOW}Backing up Hazel rules...${NC}" + # Rules are stored in a database + cp "$HOME/Library/Application Support/Hazel/hazelrules.db" "$APPS_DIR/Hazel/" 2>/dev/null || true + # Preferences + cp "$HOME/Library/Preferences/com.noodlesoft.Hazel.plist" "$APPS_DIR/preferences/" 2>/dev/null || true + echo -e "${GREEN}✓ Hazel rules backed up${NC}" +fi + +# Bartender +if [ -d "$HOME/Library/Application Support/Bartender" ]; then + echo -e "${YELLOW}Backing up Bartender...${NC}" + # Bartender 4 stores settings in preferences + cp "$HOME/Library/Preferences/com.surteesstudios.Bartender.plist" "$APPS_DIR/preferences/" 2>/dev/null || true + echo -e "${GREEN}✓ Bartender settings backed up${NC}" +fi + +# Export readable versions of plists +echo -e "${YELLOW}Converting plists to readable format...${NC}" +cd "$APPS_DIR/preferences" +for plist in *.plist; do + if [ -f "$plist" ]; then + plutil -convert xml1 -o "${plist%.plist}.xml" "$plist" 2>/dev/null || true + fi +done + +echo -e "${GREEN}Backup complete!${NC}" +echo -e "Configs saved to: $APPS_DIR" + +# Create restore instructions +cat > "$APPS_DIR/RESTORE.md" << 'EOF' +# Restoring Application Configurations + +## LaunchBar +1. Install LaunchBar from cask +2. Quit LaunchBar +3. Copy Configuration: + ```bash + cp -R ~/dotfiles/macos-apps/LaunchBar/Configuration/* "$HOME/Library/Application Support/LaunchBar/Configuration/" + ``` +4. Copy custom actions: + ```bash + cp -R ~/dotfiles/macos-apps/LaunchBar/Actions/* "$HOME/Library/Application Support/LaunchBar/Actions/" + ``` +5. Restore preferences: + ```bash + cp ~/dotfiles/macos-apps/preferences/at.obdev.LaunchBar.plist ~/Library/Preferences/ + ``` + +## Hazel +1. Install Hazel from cask +2. Quit Hazel +3. Restore rules database: + ```bash + cp ~/dotfiles/macos-apps/Hazel/hazelrules.db "$HOME/Library/Application Support/Hazel/" + ``` +4. Restore preferences: + ```bash + cp ~/dotfiles/macos-apps/preferences/com.noodlesoft.Hazel.plist ~/Library/Preferences/ + ``` + +## Bartender +1. Install Bartender from cask +2. Quit Bartender +3. Restore preferences: + ```bash + cp ~/dotfiles/macos-apps/preferences/com.surteesstudios.Bartender.plist ~/Library/Preferences/ + ``` +4. Restart Bartender + +## Note +After restoring preferences, you may need to: +- Restart the applications +- Re-authorize/license the apps +- Log out and back in for some settings to take effect +EOF \ No newline at end of file diff --git a/macos/README.md b/macos/README.md new file mode 100644 index 0000000..3c0f825 --- /dev/null +++ b/macos/README.md @@ -0,0 +1,144 @@ +# macOS System Configuration + +This directory contains scripts to configure macOS system preferences, security settings, and keyboard shortcuts. + +## Scripts Overview + +### Main Scripts +- `setup-macos.sh` - Master script that runs all configurations +- `defaults.sh` - Complete system defaults (automatic) +- `defaults-interactive.sh` - Interactive system defaults +- `security.sh` - Security and privacy settings +- `keyboard-shortcuts.sh` - Custom keyboard shortcuts + +### Utility Scripts +- `backup-defaults.sh` - Backup current settings before changes + +## Quick Start + +Run the master setup script: +```bash +~/dotfiles/macos/setup-macos.sh +``` + +This will: +1. Offer to backup current settings +2. Let you choose how to apply defaults +3. Configure security settings +4. Set up keyboard shortcuts + +## Individual Scripts + +### System Defaults +```bash +# Interactive mode (recommended) +~/dotfiles/macos/defaults-interactive.sh + +# Apply all at once +~/dotfiles/macos/defaults.sh +``` + +### Security Settings +```bash +~/dotfiles/macos/security.sh +``` + +### Backup Current Settings +```bash +~/dotfiles/macos/backup-defaults.sh +``` + +## What Gets Configured + +### System Defaults +- **General UI/UX**: Save panels, auto-correct, smart quotes +- **Keyboard**: Key repeat, full keyboard access +- **Trackpad**: Tap to click, gestures +- **Finder**: Show extensions, path bar, status bar, search settings +- **Dock**: Position, size, animations, auto-hide +- **Screen**: Screenshots location/format, screen saver +- **Safari**: Developer tools, privacy, security +- **Other apps**: Mail, Terminal, Activity Monitor, TextEdit + +### Security Settings +- Screen lock immediately after sleep +- Firewall enabled with stealth mode +- Disable analytics and tracking +- Secure Safari settings +- Disable unnecessary services +- Gatekeeper enabled +- FileVault check + +### Keyboard Shortcuts +- Mission Control shortcuts +- App-specific shortcuts +- Custom service shortcuts + +## Customization + +### Modifying Defaults +Edit the scripts to match your preferences: +- Dock position: Change `orientation` value +- Key repeat speed: Adjust `KeyRepeat` and `InitialKeyRepeat` +- Screenshot location: Modify `screencapture location` + +### Adding New Settings +1. Find the setting: `defaults read domain` +2. Test the change: `defaults write domain key value` +3. Add to appropriate script +4. Test with a backup + +### Useful Commands +```bash +# Find current setting +defaults read com.apple.dock orientation + +# Test a change +defaults write com.apple.dock tilesize -int 64 + +# Reset to default +defaults delete com.apple.dock tilesize + +# List all domains +defaults domains + +# Read entire domain +defaults read com.apple.dock +``` + +## Manual Configuration Still Required + +Some settings must be configured manually: +1. **System Preferences > Security & Privacy** + - FileVault encryption + - App permissions (Camera, Microphone, etc.) + - Privacy settings + +2. **System Preferences > Keyboard > Shortcuts** + - Some Mission Control shortcuts + - Service shortcuts + +3. **App-specific settings** + - Third-party app preferences + - Login items + +## Troubleshooting + +### Settings Not Taking Effect +- Some changes require logout/restart +- Try: `killall SystemUIServer` or `killall Dock` +- Clear preferences cache: `killall cfprefsd` + +### Backing Out Changes +- Restore from backup: Run backup script first +- Reset specific domains: `defaults delete domain` +- System reset: System Preferences > General > Reset + +### Finding Setting Names +- Use GUI first, then check `defaults domains` +- Monitor changes: `defaults read domain > before.txt`, make change, `defaults read domain > after.txt`, `diff before.txt after.txt` + +## References +- [macOS defaults reference](https://macos-defaults.com/) +- [Awesome macOS Command Line](https://github.com/herrbischoff/awesome-macos-command-line) +- [macOS Security Guide](https://github.com/drduh/macOS-Security-and-Privacy-Guide) \ No newline at end of file diff --git a/macos/backup-defaults.sh b/macos/backup-defaults.sh new file mode 100755 index 0000000..62bff40 --- /dev/null +++ b/macos/backup-defaults.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# Backup current macOS defaults before applying new ones + +set -euo pipefail + +BACKUP_DIR="$HOME/dotfiles/macos/backups" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +BACKUP_FILE="$BACKUP_DIR/defaults_backup_${TIMESTAMP}.txt" + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo -e "${GREEN}Backing up current macOS defaults...${NC}" + +# Create backup directory +mkdir -p "$BACKUP_DIR" + +# Domains to backup +domains=( + "NSGlobalDomain" + "com.apple.dock" + "com.apple.finder" + "com.apple.Safari" + "com.apple.screencapture" + "com.apple.screensaver" + "com.apple.ActivityMonitor" + "com.apple.TextEdit" +) + +# Backup each domain +{ + echo "# macOS Defaults Backup" + echo "# Created: $(date)" + echo "# System: $(sw_vers -productVersion)" + echo "" +} > "$BACKUP_FILE" + +for domain in "${domains[@]}"; do + echo -e "${YELLOW}Backing up $domain...${NC}" + { + echo "# =============================================" + echo "# $domain" + echo "# =============================================" + defaults read "$domain" 2>/dev/null || echo "# No settings found for $domain" + echo "" + } >> "$BACKUP_FILE" +done + +# Backup specific important settings +echo -e "${YELLOW}Backing up specific settings...${NC}" +{ + echo "# =============================================" + echo "# Specific Settings" + echo "# =============================================" + echo "# Dock position: $(defaults read com.apple.dock orientation 2>/dev/null || echo 'default')" + echo "# Dock size: $(defaults read com.apple.dock tilesize 2>/dev/null || echo 'default')" + echo "# Show hidden files: $(defaults read com.apple.finder AppleShowAllFiles 2>/dev/null || echo 'false')" + echo "# Key repeat: $(defaults read NSGlobalDomain KeyRepeat 2>/dev/null || echo 'default')" + echo "# Initial key repeat: $(defaults read NSGlobalDomain InitialKeyRepeat 2>/dev/null || echo 'default')" +} >> "$BACKUP_FILE" + +echo -e "${GREEN}✓ Backup saved to: $BACKUP_FILE${NC}" + +# Keep only last 5 backups +cd "$BACKUP_DIR" +ls -t defaults_backup_*.txt 2>/dev/null | tail -n +6 | xargs -r rm + +echo -e "${GREEN}Backup complete!${NC}" \ No newline at end of file diff --git a/macos/defaults-interactive.sh b/macos/defaults-interactive.sh new file mode 100755 index 0000000..7a3d83c --- /dev/null +++ b/macos/defaults-interactive.sh @@ -0,0 +1,195 @@ +#!/usr/bin/env bash +# Interactive macOS defaults setter +# Choose which categories to apply + +set -euo pipefail + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' + +echo -e "${BLUE}macOS Defaults Configuration${NC}" +echo "==============================" +echo "Select which settings to apply:" +echo "" + +# Ask for sudo upfront +sudo -v + +# Function to ask yes/no +ask() { + while true; do + read -p "$1 (y/n) " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + return 0 + elif [[ $REPLY =~ ^[Nn]$ ]]; then + return 1 + fi + done +} + +# General UI/UX +if ask "Apply General UI/UX settings?"; then + echo -e "${YELLOW}Applying General UI/UX settings...${NC}" + + # Expand save/print panels by default + defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode -bool true + defaults write NSGlobalDomain PMPrintingExpandedStateForPrint -bool true + + # Save to disk by default + defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false + + # Disable auto-correct and substitutions + defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false + defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false + defaults write NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled -bool false + defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false + defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false + + echo -e "${GREEN}✓ General UI/UX settings applied${NC}" +fi + +# Keyboard & Input +if ask "Apply Keyboard settings?"; then + echo -e "${YELLOW}Applying Keyboard settings...${NC}" + + # Enable full keyboard access + defaults write NSGlobalDomain AppleKeyboardUIMode -int 3 + + # Fast key repeat + defaults write NSGlobalDomain KeyRepeat -int 2 + defaults write NSGlobalDomain InitialKeyRepeat -int 15 + + # Disable press-and-hold + defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false + + echo -e "${GREEN}✓ Keyboard settings applied${NC}" +fi + +# Finder +if ask "Apply Finder settings?"; then + echo -e "${YELLOW}Applying Finder settings...${NC}" + + # Show extensions, status bar, path bar + defaults write NSGlobalDomain AppleShowAllExtensions -bool true + defaults write com.apple.finder ShowStatusBar -bool true + defaults write com.apple.finder ShowPathbar -bool true + + # Keep folders on top + defaults write com.apple.finder _FXSortFoldersFirst -bool true + + # Search current folder by default + defaults write com.apple.finder FXDefaultSearchScope -string "SCcf" + + # Disable extension change warning + defaults write com.apple.finder FXEnableExtensionChangeWarning -bool false + + # Show Library folder + chflags nohidden ~/Library + + echo -e "${GREEN}✓ Finder settings applied${NC}" +fi + +# Dock +if ask "Apply Dock settings?"; then + echo -e "${YELLOW}Which Dock position?${NC}" + echo "1) Left" + echo "2) Bottom" + echo "3) Right" + read -p "Choice (1-3): " -n 1 -r + echo + + case $REPLY in + 1) position="left";; + 2) position="bottom";; + 3) position="right";; + *) position="right";; + esac + + defaults write com.apple.dock orientation -string "$position" + + # Other Dock settings + defaults write com.apple.dock tilesize -int 48 + defaults write com.apple.dock minimize-to-application -bool true + defaults write com.apple.dock show-process-indicators -bool true + defaults write com.apple.dock launchanim -bool false + defaults write com.apple.dock autohide -bool true + defaults write com.apple.dock autohide-delay -float 0 + defaults write com.apple.dock show-recents -bool false + + echo -e "${GREEN}✓ Dock settings applied${NC}" +fi + +# Security +if ask "Apply Security settings?"; then + echo -e "${YELLOW}Applying Security settings...${NC}" + + # Require password immediately after sleep + defaults write com.apple.screensaver askForPassword -int 1 + defaults write com.apple.screensaver askForPasswordDelay -int 0 + + echo -e "${GREEN}✓ Security settings applied${NC}" +fi + +# Screenshots +if ask "Apply Screenshot settings?"; then + echo -e "${YELLOW}Where should screenshots be saved?${NC}" + echo "1) Desktop (default)" + echo "2) Pictures/Screenshots" + echo "3) Downloads" + read -p "Choice (1-3): " -n 1 -r + echo + + case $REPLY in + 2) + mkdir -p ~/Pictures/Screenshots + location="$HOME/Pictures/Screenshots" + ;; + 3) + location="$HOME/Downloads" + ;; + *) + location="$HOME/Desktop" + ;; + esac + + defaults write com.apple.screencapture location -string "$location" + defaults write com.apple.screencapture type -string "png" + defaults write com.apple.screencapture disable-shadow -bool true + + echo -e "${GREEN}✓ Screenshot settings applied${NC}" +fi + +# Development Tools +if ask "Apply Development settings (Safari, Terminal)?"; then + echo -e "${YELLOW}Applying Development settings...${NC}" + + # Safari + defaults write com.apple.Safari IncludeDevelopMenu -bool true + defaults write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool true + + # Terminal + defaults write com.apple.terminal StringEncodings -array 4 + defaults write com.apple.terminal SecureKeyboardEntry -bool true + + echo -e "${GREEN}✓ Development settings applied${NC}" +fi + +# Restart affected apps +if ask "Restart affected applications?"; then + echo -e "${YELLOW}Restarting applications...${NC}" + + for app in "Dock" "Finder" "SystemUIServer"; do + killall "${app}" &> /dev/null || true + done + + echo -e "${GREEN}✓ Applications restarted${NC}" +fi + +echo "" +echo -e "${GREEN}Configuration complete!${NC}" +echo "Some changes may require logging out or restarting." \ No newline at end of file diff --git a/macos/defaults.sh b/macos/defaults.sh new file mode 100755 index 0000000..bdd0698 --- /dev/null +++ b/macos/defaults.sh @@ -0,0 +1,287 @@ +#!/usr/bin/env bash +# macOS System Preferences +# Tested on macOS Sonoma/Sequoia +# Run: bash ~/dotfiles/macos/defaults.sh + +# Close System Preferences to prevent conflicts +osascript -e 'tell application "System Preferences" to quit' + +# Ask for administrator password upfront +sudo -v + +# Keep sudo alive +while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null & + +echo "Setting macOS defaults..." + +# ============================================================================= +# General UI/UX +# ============================================================================= + +# Expand save panel by default +defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode -bool true +defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode2 -bool true + +# Expand print panel by default +defaults write NSGlobalDomain PMPrintingExpandedStateForPrint -bool true +defaults write NSGlobalDomain PMPrintingExpandedStateForPrint2 -bool true + +# Save to disk (not iCloud) by default +defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false + +# Automatically quit printer app once print jobs complete +defaults write com.apple.print.PrintingPrefs "Quit When Finished" -bool true + +# Disable Resume system-wide +defaults write com.apple.systempreferences NSQuitAlwaysKeepsWindows -bool false + +# Disable automatic capitalization +defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false + +# Disable smart dashes +defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false + +# Disable automatic period substitution +defaults write NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled -bool false + +# Disable smart quotes +defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false + +# Disable auto-correct +defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false + +# ============================================================================= +# Trackpad, Mouse, Keyboard +# ============================================================================= + +# Trackpad: enable tap to click +defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true +defaults -currentHost write NSGlobalDomain com.apple.mouse.tapBehavior -int 1 +defaults write NSGlobalDomain com.apple.mouse.tapBehavior -int 1 + +# Enable full keyboard access for all controls +defaults write NSGlobalDomain AppleKeyboardUIMode -int 3 + +# Use scroll gesture with the Ctrl (^) modifier key to zoom +defaults write com.apple.universalaccess closeViewScrollWheelToggle -bool true +defaults write com.apple.universalaccess HIDScrollZoomModifierMask -int 262144 + +# Disable press-and-hold for keys in favor of key repeat +defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false + +# Set fast keyboard repeat rate +defaults write NSGlobalDomain KeyRepeat -int 2 +defaults write NSGlobalDomain InitialKeyRepeat -int 15 + +# ============================================================================= +# Screen +# ============================================================================= + +# Require password immediately after sleep or screen saver +defaults write com.apple.screensaver askForPassword -int 1 +defaults write com.apple.screensaver askForPasswordDelay -int 0 + +# Save screenshots to the desktop +defaults write com.apple.screencapture location -string "${HOME}/Desktop" + +# Save screenshots in PNG format +defaults write com.apple.screencapture type -string "png" + +# Disable shadow in screenshots +defaults write com.apple.screencapture disable-shadow -bool true + +# ============================================================================= +# Finder +# ============================================================================= + +# Finder: show all filename extensions +defaults write NSGlobalDomain AppleShowAllExtensions -bool true + +# Finder: show status bar +defaults write com.apple.finder ShowStatusBar -bool true + +# Finder: show path bar +defaults write com.apple.finder ShowPathbar -bool true + +# Keep folders on top when sorting by name +defaults write com.apple.finder _FXSortFoldersFirst -bool true + +# When performing a search, search the current folder by default +defaults write com.apple.finder FXDefaultSearchScope -string "SCcf" + +# Disable the warning when changing a file extension +defaults write com.apple.finder FXEnableExtensionChangeWarning -bool false + +# Enable spring loading for directories +defaults write NSGlobalDomain com.apple.springing.enabled -bool true + +# Avoid creating .DS_Store files on network or USB volumes +defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true +defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true + +# Use list view in all Finder windows by default +defaults write com.apple.finder FXPreferredViewStyle -string "Nlsv" + +# Show the ~/Library folder +chflags nohidden ~/Library + +# Show the /Volumes folder +sudo chflags nohidden /Volumes + +# ============================================================================= +# Dock +# ============================================================================= + +# Set Dock position (left, bottom, right) +defaults write com.apple.dock orientation -string "right" + +# Set the icon size of Dock items +defaults write com.apple.dock tilesize -int 48 + +# Change minimize/maximize window effect +defaults write com.apple.dock mineffect -string "scale" + +# Minimize windows into their application's icon +defaults write com.apple.dock minimize-to-application -bool true + +# Show indicator lights for open applications +defaults write com.apple.dock show-process-indicators -bool true + +# Don't animate opening applications from the Dock +defaults write com.apple.dock launchanim -bool false + +# Speed up Mission Control animations +defaults write com.apple.dock expose-animation-duration -float 0.1 + +# Don't automatically rearrange Spaces based on most recent use +defaults write com.apple.dock mru-spaces -bool false + +# Remove the auto-hiding Dock delay +defaults write com.apple.dock autohide-delay -float 0 + +# Remove the animation when hiding/showing the Dock +defaults write com.apple.dock autohide-time-modifier -float 0 + +# Automatically hide and show the Dock +defaults write com.apple.dock autohide -bool true + +# Make Dock icons of hidden applications translucent +defaults write com.apple.dock showhidden -bool true + +# Don't show recent applications in Dock +defaults write com.apple.dock show-recents -bool false + +# ============================================================================= +# Safari & WebKit +# ============================================================================= + +# Privacy: don't send search queries to Apple +defaults write com.apple.Safari UniversalSearchEnabled -bool false +defaults write com.apple.Safari SuppressSearchSuggestions -bool true + +# Show the full URL in the address bar +defaults write com.apple.Safari ShowFullURLInSmartSearchField -bool true + +# Set Safari's home page to about:blank +defaults write com.apple.Safari HomePage -string "about:blank" + +# Prevent Safari from opening safe files automatically +defaults write com.apple.Safari AutoOpenSafeDownloads -bool false + +# Enable Safari's debug menu +defaults write com.apple.Safari IncludeInternalDebugMenu -bool true + +# Enable the Develop menu and Web Inspector +defaults write com.apple.Safari IncludeDevelopMenu -bool true +defaults write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool true +defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled -bool true + +# Warn about fraudulent websites +defaults write com.apple.Safari WarnAboutFraudulentWebsites -bool true + +# Block pop-up windows +defaults write com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool false +defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool false + +# Enable "Do Not Track" +defaults write com.apple.Safari SendDoNotTrackHTTPHeader -bool true + +# ============================================================================= +# Mail +# ============================================================================= + +# Copy email addresses as "foo@example.com" instead of "Foo Bar " +defaults write com.apple.mail AddressesIncludeNameOnPasteboard -bool false + +# ============================================================================= +# Terminal & iTerm 2 +# ============================================================================= + +# Only use UTF-8 in Terminal.app +defaults write com.apple.terminal StringEncodings -array 4 + +# Enable Secure Keyboard Entry in Terminal.app +defaults write com.apple.terminal SecureKeyboardEntry -bool true + +# ============================================================================= +# Time Machine +# ============================================================================= + +# Prevent Time Machine from prompting to use new hard drives as backup volume +defaults write com.apple.TimeMachine DoNotOfferNewDisksForBackup -bool true + +# ============================================================================= +# Activity Monitor +# ============================================================================= + +# Show the main window when launching Activity Monitor +defaults write com.apple.ActivityMonitor OpenMainWindow -bool true + +# Visualize CPU usage in the Dock icon +defaults write com.apple.ActivityMonitor IconType -int 5 + +# Show all processes in Activity Monitor +defaults write com.apple.ActivityMonitor ShowCategory -int 0 + +# Sort Activity Monitor results by CPU usage +defaults write com.apple.ActivityMonitor SortColumn -string "CPUUsage" +defaults write com.apple.ActivityMonitor SortDirection -int 0 + +# ============================================================================= +# TextEdit +# ============================================================================= + +# Use plain text mode for new documents +defaults write com.apple.TextEdit RichText -int 0 + +# Open and save files as UTF-8 +defaults write com.apple.TextEdit PlainTextEncoding -int 4 +defaults write com.apple.TextEdit PlainTextEncodingForWrite -int 4 + +# ============================================================================= +# Messages +# ============================================================================= + +# Disable smart quotes in Messages.app +defaults write com.apple.messageshelper.MessageController SOInputLineSettings -dict-add "automaticQuoteSubstitutionEnabled" -bool false + +# ============================================================================= +# Kill affected applications +# ============================================================================= + +echo "Done! Restarting affected applications..." + +for app in "Activity Monitor" \ + "cfprefsd" \ + "Dock" \ + "Finder" \ + "Mail" \ + "Messages" \ + "Safari" \ + "SystemUIServer" \ + "Terminal"; do + killall "${app}" &> /dev/null || true +done + +echo "macOS defaults set successfully! 🎉" +echo "Note: Some changes require a logout/restart to take effect." \ No newline at end of file diff --git a/macos/keyboard-shortcuts.sh b/macos/keyboard-shortcuts.sh new file mode 100755 index 0000000..b75d651 --- /dev/null +++ b/macos/keyboard-shortcuts.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# macOS Keyboard Shortcuts Configuration + +set -euo pipefail + +echo "Setting up custom keyboard shortcuts..." + +# ============================================================================= +# Global Shortcuts +# ============================================================================= + +# Enable access for assistive devices (needed for some shortcuts) +# Note: This may require manual approval in System Preferences > Security & Privacy + +# Mission Control shortcuts +defaults write com.apple.symbolichotkeys AppleSymbolicHotKeys -dict-add 32 " + + enabled + value + typestandard + parameters + + 65535 + 126 + 8388608 + + + +" + +# ============================================================================= +# App-specific shortcuts (examples) +# ============================================================================= + +# Finder shortcuts +defaults write com.apple.finder NSUserKeyEquivalents -dict-add "Show Package Contents" "@\$o" + +# ============================================================================= +# Service shortcuts +# ============================================================================= + +# Create custom services directory +mkdir -p ~/Library/Services + +# Note: Some shortcuts need to be set manually in System Preferences +cat << 'EOF' > ~/dotfiles/macos/KEYBOARD_SHORTCUTS.md +# Keyboard Shortcuts Setup + +## Manual Configuration Required + +Some shortcuts must be set manually in System Preferences: + +### System Preferences > Keyboard > Shortcuts + +1. **Mission Control** + - Mission Control: Control + Up Arrow + - Application Windows: Control + Down Arrow + - Desktop Left: Control + Left Arrow + - Desktop Right: Control + Right Arrow + +2. **Launchpad & Dock** + - Launchpad: F4 (or customize) + +3. **App Shortcuts** + - All Applications: + - "Zoom": Cmd+Shift+Z (if you use this often) + +### Finder Shortcuts +- Show Package Contents: Cmd+Shift+O (already set by script) + +### Custom Services +Create workflows in Automator for: +- Open Terminal Here +- Copy Path +- Convert Images + +## Third-party App Shortcuts + +Configure these in the respective apps: + +### Karabiner-Elements +Your existing config handles: +- Cmd/Option swap for external keyboards + +### LaunchBar +- Activation: Space+Space (or Cmd+Space) + +### Bartender +- Configure menu bar item shortcuts as needed + +## Verification + +Test shortcuts after setup: +1. Mission Control (Control + Up) +2. Desktop switching (Control + Left/Right) +3. Finder package contents (Cmd+Shift+O) +EOF + +echo "Keyboard shortcuts configuration complete!" +echo "See ~/dotfiles/macos/KEYBOARD_SHORTCUTS.md for manual setup steps." \ No newline at end of file diff --git a/macos/security.sh b/macos/security.sh new file mode 100755 index 0000000..6f175e0 --- /dev/null +++ b/macos/security.sh @@ -0,0 +1,152 @@ +#!/usr/bin/env bash +# macOS Security Settings + +set -euo pipefail + +echo "Configuring macOS security settings..." + +# Ask for admin password upfront +sudo -v + +# ============================================================================= +# Screen Security +# ============================================================================= + +# Require password immediately after sleep or screen saver begins +defaults write com.apple.screensaver askForPassword -int 1 +defaults write com.apple.screensaver askForPasswordDelay -int 0 + +# Set screen saver to start after 10 minutes of inactivity +defaults -currentHost write com.apple.screensaver idleTime -int 600 + +# ============================================================================= +# Firewall +# ============================================================================= + +# Enable firewall +sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1 + +# Enable firewall stealth mode (don't respond to ICMP ping requests or closed TCP/UDP ports) +sudo defaults write /Library/Preferences/com.apple.alf stealthenabled -int 1 + +# Enable firewall logging +sudo defaults write /Library/Preferences/com.apple.alf loggingenabled -int 1 + +# ============================================================================= +# Privacy & Tracking +# ============================================================================= + +# Disable location services for system services +sudo defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false + +# Disable analytics & improvements +defaults write com.apple.SubmitDiagInfo AutoSubmit -bool false +defaults write com.apple.applicationaccess.plist com.apple.applicationaccess.feedback -bool false + +# Disable personalized ads +defaults write com.apple.AdLib forceLimitAdTracking -bool true + +# ============================================================================= +# Safari Security (if Safari is used) +# ============================================================================= + +# Enable "Do Not Track" +defaults write com.apple.Safari SendDoNotTrackHTTPHeader -bool true + +# Block pop-up windows +defaults write com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool false +defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool false + +# Disable auto-filling passwords (if you use 1Password) +defaults write com.apple.Safari AutoFillPasswords -bool false + +# Warn about fraudulent websites +defaults write com.apple.Safari WarnAboutFraudulentWebsites -bool true + +# Disable automatic opening of safe files +defaults write com.apple.Safari AutoOpenSafeDownloads -bool false + +# ============================================================================= +# System Security +# ============================================================================= + +# Disable guest account +sudo dscl . create /Users/Guest UserShell /usr/bin/false + +# Disable remote apple events +sudo systemsetup -setremoteappleevents off + +# Disable remote login (SSH) - uncomment if you don't need it +# sudo systemsetup -setremotelogin off + +# Disable wake-on modem +sudo systemsetup -setwakeonmodem off + +# Disable wake-on network access +sudo systemsetup -setwakeonnetworkaccess off + +# Disable file sharing +sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.AppleFileServer.plist 2>/dev/null || true + +# ============================================================================= +# FileVault (Disk Encryption) +# ============================================================================= + +# Check if FileVault is enabled +if ! sudo fdesetup status | grep -q "FileVault is On"; then + echo "WARNING: FileVault is not enabled!" + echo "Consider enabling FileVault for full disk encryption:" + echo "System Preferences > Security & Privacy > FileVault" +fi + +# ============================================================================= +# Gatekeeper +# ============================================================================= + +# Enable Gatekeeper +sudo spctl --master-enable + +# ============================================================================= +# Secure Empty Trash +# ============================================================================= + +# Enable secure empty trash (if available on your macOS version) +defaults write com.apple.finder EmptyTrashSecurely -bool true 2>/dev/null || true + +# ============================================================================= +# Network Security +# ============================================================================= + +# Disable Bonjour multicast advertisements +sudo defaults write /Library/Preferences/com.apple.mDNSResponder.plist NoMulticastAdvertisements -bool true + +# ============================================================================= +# Application Security +# ============================================================================= + +# Prevent automatic software updates +sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -bool false +# Note: You might want to keep this enabled and just review updates manually + +# Show all file extensions to prevent malware masquerading +defaults write NSGlobalDomain AppleShowAllExtensions -bool true + +# ============================================================================= +# Privacy - Microphone and Camera +# ============================================================================= + +echo "" +echo "Security configuration complete!" +echo "" +echo "Manual steps required:" +echo "1. System Preferences > Security & Privacy > FileVault - Enable if not already on" +echo "2. System Preferences > Security & Privacy > Privacy - Review app permissions" +echo "3. System Preferences > Screen Time - Configure if desired" +echo "4. Consider enabling 2FA for Apple ID" +echo "5. Review Location Services in System Preferences" +echo "" +echo "Third-party security tools to consider:" +echo "- LuLu (firewall) - already in your Brewfile" +echo "- OverSight (camera/mic monitor) - already in your Brewfile" +echo "- Little Snitch (network monitor)" +echo "- 1Password (password manager) - already in your Brewfile" \ No newline at end of file diff --git a/macos/setup-macos.sh b/macos/setup-macos.sh new file mode 100755 index 0000000..8d90a9e --- /dev/null +++ b/macos/setup-macos.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# Master macOS setup script + +set -euo pipefail + +MACOS_DIR="$HOME/dotfiles/macos" + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +echo -e "${BLUE}macOS System Setup${NC}" +echo "==================" +echo "" + +# Function to ask yes/no +ask() { + while true; do + read -p "$1 (y/n) " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + return 0 + elif [[ $REPLY =~ ^[Nn]$ ]]; then + return 1 + fi + done +} + +# Backup current settings +if ask "Backup current macOS settings first?"; then + echo -e "${YELLOW}Creating backup...${NC}" + bash "$MACOS_DIR/backup-defaults.sh" + echo "" +fi + +# Apply system defaults +echo -e "${YELLOW}Choose how to apply system defaults:${NC}" +echo "1) Interactive mode (recommended for first time)" +echo "2) Apply all defaults automatically" +echo "3) Skip defaults" +read -p "Choice (1-3): " -n 1 -r +echo "" + +case $REPLY in + 1) + bash "$MACOS_DIR/defaults-interactive.sh" + ;; + 2) + bash "$MACOS_DIR/defaults.sh" + ;; + *) + echo "Skipping defaults..." + ;; +esac + +echo "" + +# Security settings +if ask "Apply security settings?"; then + echo -e "${YELLOW}Applying security settings...${NC}" + bash "$MACOS_DIR/security.sh" + echo "" +fi + +# Keyboard shortcuts +if ask "Set up keyboard shortcuts?"; then + echo -e "${YELLOW}Setting up keyboard shortcuts...${NC}" + bash "$MACOS_DIR/keyboard-shortcuts.sh" + echo "" +fi + +echo -e "${GREEN}macOS setup complete!${NC}" +echo "" +echo "Summary of what was configured:" +echo "- System defaults (UI, Finder, Dock, etc.)" +echo "- Security settings (firewall, privacy, etc.)" +echo "- Keyboard shortcuts" +echo "" +echo "Next steps:" +echo "1. Log out and back in for all changes to take effect" +echo "2. Review security settings in System Preferences" +echo "3. Configure any remaining manual settings" +echo "4. Install applications: brew bundle install" \ No newline at end of file diff --git a/obsidian/setup-obsidian.sh b/obsidian/setup-obsidian.sh new file mode 100755 index 0000000..4a644c4 --- /dev/null +++ b/obsidian/setup-obsidian.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash +# Obsidian configuration setup + +set -euo pipefail + +OBSIDIAN_VAULT_PATH="$HOME/Library/Mobile Documents/iCloud~md~obsidian/Documents/David, root-and-branch" +DOTFILES_OBSIDIAN="$HOME/dotfiles/obsidian" + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +echo -e "${BLUE}Setting up Obsidian configuration...${NC}" + +# Create obsidian config directory in dotfiles +mkdir -p "$DOTFILES_OBSIDIAN" + +if [ ! -d "$OBSIDIAN_VAULT_PATH" ]; then + echo -e "${YELLOW}⚠ Obsidian vault not found at expected location${NC}" + echo "Expected: $OBSIDIAN_VAULT_PATH" + echo "Please update the path in this script if your vault is elsewhere" + exit 1 +fi + +# Copy community plugins list +if [ -f "$OBSIDIAN_VAULT_PATH/.obsidian/community-plugins.json" ]; then + cp "$OBSIDIAN_VAULT_PATH/.obsidian/community-plugins.json" "$DOTFILES_OBSIDIAN/" + echo -e "${GREEN}✓ Copied community plugins list${NC}" +fi + +# Copy app configuration (settings) +if [ -f "$OBSIDIAN_VAULT_PATH/.obsidian/app.json" ]; then + cp "$OBSIDIAN_VAULT_PATH/.obsidian/app.json" "$DOTFILES_OBSIDIAN/" + echo -e "${GREEN}✓ Copied app settings${NC}" +fi + +# Copy hotkeys +if [ -f "$OBSIDIAN_VAULT_PATH/.obsidian/hotkeys.json" ]; then + cp "$OBSIDIAN_VAULT_PATH/.obsidian/hotkeys.json" "$DOTFILES_OBSIDIAN/" + echo -e "${GREEN}✓ Copied hotkeys${NC}" +fi + +# Copy workspace +if [ -f "$OBSIDIAN_VAULT_PATH/.obsidian/workspace.json" ]; then + cp "$OBSIDIAN_VAULT_PATH/.obsidian/workspace.json" "$DOTFILES_OBSIDIAN/" + echo -e "${GREEN}✓ Copied workspace layout${NC}" +fi + +# Create plugin installation script +cat > "$DOTFILES_OBSIDIAN/install-plugins.sh" << 'EOF' +#!/usr/bin/env bash +# Install Obsidian community plugins + +echo "Installing Obsidian community plugins..." + +# Plugin list from community-plugins.json +PLUGINS=( + "calendar" + "templater-obsidian" + "dataview" + "longform" + "note-refactor-obsidian" + "obsidian-version-history-diff" + "obsidian-kanban" + "table-editor-obsidian" + "obsidian-tasks-plugin" + "obsidian-style-settings" + "obsidian-csv-table" + "tag-wrangler" +) + +VAULT_PATH="$HOME/Library/Mobile Documents/iCloud~md~obsidian/Documents/David, root-and-branch" +PLUGINS_DIR="$VAULT_PATH/.obsidian/plugins" + +if [ ! -d "$VAULT_PATH" ]; then + echo "Error: Obsidian vault not found at $VAULT_PATH" + exit 1 +fi + +mkdir -p "$PLUGINS_DIR" + +echo "Note: Obsidian community plugins must be installed through the app." +echo "This script serves as a reference for which plugins to install." +echo "" +echo "Required plugins:" +for plugin in "${PLUGINS[@]}"; do + echo " - $plugin" +done +echo "" +echo "To install:" +echo "1. Open Obsidian" +echo "2. Go to Settings > Community Plugins" +echo "3. Turn off Safe Mode" +echo "4. Browse and install each plugin from the list above" +echo "5. Enable each plugin after installation" +EOF + +chmod +x "$DOTFILES_OBSIDIAN/install-plugins.sh" + +# Create restore script +cat > "$DOTFILES_OBSIDIAN/restore-config.sh" << 'EOF' +#!/usr/bin/env bash +# Restore Obsidian configuration + +VAULT_PATH="$HOME/Library/Mobile Documents/iCloud~md~obsidian/Documents/David, root-and-branch" +DOTFILES_OBSIDIAN="$HOME/dotfiles/obsidian" + +if [ ! -d "$VAULT_PATH" ]; then + echo "Error: Obsidian vault not found at $VAULT_PATH" + exit 1 +fi + +echo "Restoring Obsidian configuration..." + +# Restore configurations +for config in community-plugins.json app.json hotkeys.json workspace.json; do + if [ -f "$DOTFILES_OBSIDIAN/$config" ]; then + cp "$DOTFILES_OBSIDIAN/$config" "$VAULT_PATH/.obsidian/" + echo "✓ Restored $config" + fi +done + +echo "" +echo "Configuration restored!" +echo "Note: You'll still need to install the community plugins manually." +echo "Run: ~/dotfiles/obsidian/install-plugins.sh for the plugin list." +EOF + +chmod +x "$DOTFILES_OBSIDIAN/restore-config.sh" + +# Create README +cat > "$DOTFILES_OBSIDIAN/README.md" << 'EOF' +# Obsidian Configuration + +This directory contains Obsidian vault configurations for the "David, root-and-branch" vault. + +## What's Included + +- `community-plugins.json` - List of installed community plugins +- `app.json` - Core application settings +- `hotkeys.json` - Custom keyboard shortcuts +- `workspace.json` - Workspace layout and panel configuration + +## Essential Plugins + +This vault relies on these community plugins: + +1. **Templater** - Advanced template system with dynamic content +2. **Dataview** - Live data aggregation and queries +3. **Calendar** - Calendar view for daily notes +4. **Longform** - Long-form writing project management +5. **Tasks** - Task management and tracking +6. **Kanban** - Board view for project organization +7. **Table Editor** - Enhanced table editing +8. **Style Settings** - Theme customization +9. **Tag Wrangler** - Tag management +10. **Note Refactor** - Note splitting and organization +11. **Version History Diff** - Compare note versions +12. **CSV Table** - CSV import/export + +## Setup on New Machine + +1. Install Obsidian from cask: `brew install --cask obsidian` +2. Open Obsidian and create/open vault +3. Run restore script: `~/dotfiles/obsidian/restore-config.sh` +4. Install plugins manually: See `install-plugins.sh` for list +5. Enable plugins in Settings > Community Plugins + +## Backup Process + +To backup current configuration: +```bash +~/dotfiles/obsidian/setup-obsidian.sh +``` + +## Vault Philosophy + +This vault follows Christopher Alexander's "Pattern Language" approach: +- Organic growth over rigid structure +- Meaning-making over productivity optimization +- Sustainable long-term use patterns +- Integration with analogue workflow (A6 notebook) + +## Key Templates + +The vault includes sophisticated templates in `98. Templates/`: +- Daily Note Template (morning/evening structure) +- Weekly/Monthly/Quarterly review cycles +- Project and people templates +- Zibaldone (fragment capture) template + +## Important Notes + +- Vault uses iCloud sync +- Templates require Templater plugin +- Dataview queries need Dataview plugin +- Daily workflow integrates with physical A6 notebook +- Multilingual content (EN/ES/FR/CA) +EOF + +echo -e "${GREEN}Obsidian setup complete!${NC}" +echo -e "Files created in: $DOTFILES_OBSIDIAN" \ No newline at end of file diff --git a/scripts/symlinks.sh b/scripts/symlinks.sh new file mode 100755 index 0000000..e75dc52 --- /dev/null +++ b/scripts/symlinks.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# Symlink dotfiles to home directory + +set -euo pipefail + +DOTFILES_DIR="$HOME/dotfiles" + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +BLUE='\033[0;34m' +NC='\033[0m' + +echo -e "${BLUE}Creating symlinks for dotfiles...${NC}" + +# Function to create symlink with backup +link_file() { + local source="$1" + local target="$2" + local backup_dir="$HOME/.dotfiles-backup/$(date +%Y%m%d_%H%M%S)" + + # Create target directory if it doesn't exist + mkdir -p "$(dirname "$target")" + + # If target exists and is not a symlink, back it up + if [ -e "$target" ] && [ ! -L "$target" ]; then + echo -e "${YELLOW}Backing up existing $target${NC}" + mkdir -p "$backup_dir" + mv "$target" "$backup_dir/" + fi + + # Remove existing symlink + [ -L "$target" ] && rm "$target" + + # Create new symlink + ln -sf "$source" "$target" + echo -e "${GREEN}✓ Linked: $target -> $source${NC}" +} + +# Shell configurations +echo -e "${YELLOW}Linking shell configurations...${NC}" +link_file "$DOTFILES_DIR/.zshrc" "$HOME/.zshrc" +link_file "$DOTFILES_DIR/.gitconfig" "$HOME/.gitconfig" +link_file "$DOTFILES_DIR/.vimrc" "$HOME/.vimrc" +link_file "$DOTFILES_DIR/.npmrc" "$HOME/.npmrc" + +# SSH config (template only - user must customize) +if [ -f "$DOTFILES_DIR/ssh/config.example" ] && [ ! -f "$HOME/.ssh/config" ]; then + echo -e "${YELLOW}Creating SSH config from template...${NC}" + mkdir -p "$HOME/.ssh" + cp "$DOTFILES_DIR/ssh/config.example" "$HOME/.ssh/config" + chmod 600 "$HOME/.ssh/config" + echo -e "${YELLOW}⚠ Edit ~/.ssh/config with your actual values${NC}" +fi + +# Config directories +echo -e "${YELLOW}Linking config directories...${NC}" +mkdir -p "$HOME/.config" + +# Link config subdirectories if they exist +for config_dir in git iterm2 kitty karabiner; do + if [ -d "$DOTFILES_DIR/config/$config_dir" ]; then + link_file "$DOTFILES_DIR/config/$config_dir" "$HOME/.config/$config_dir" + fi +done + +# Custom scripts +echo -e "${YELLOW}Linking custom scripts...${NC}" +mkdir -p "$HOME/bin" +if [ -d "$DOTFILES_DIR/bin" ]; then + for script in "$DOTFILES_DIR/bin"/*; do + if [ -f "$script" ] && [ -x "$script" ]; then + script_name=$(basename "$script") + link_file "$script" "$HOME/bin/$script_name" + fi + done +fi + +# Git hooks +echo -e "${YELLOW}Setting up global git hooks...${NC}" +if [ -d "$DOTFILES_DIR/git/hooks" ]; then + git config --global core.hooksPath "$DOTFILES_DIR/git/hooks" + echo -e "${GREEN}✓ Global git hooks configured${NC}" +fi + +# Mackup configuration +if [ -f "$DOTFILES_DIR/.mackup.cfg" ]; then + link_file "$DOTFILES_DIR/.mackup.cfg" "$HOME/.mackup.cfg" +fi + +# Shell enhancements +echo -e "${YELLOW}Setting up shell enhancements...${NC}" +if [ -f "$DOTFILES_DIR/shell/history-sync.zsh" ]; then + # Add source line to .zshrc if not already present + if ! grep -q "history-sync.zsh" "$HOME/.zshrc" 2>/dev/null; then + echo "" >> "$HOME/.zshrc" + echo "# History sync and enhancements" >> "$HOME/.zshrc" + echo "source $DOTFILES_DIR/shell/history-sync.zsh" >> "$HOME/.zshrc" + echo -e "${GREEN}✓ Added history sync to .zshrc${NC}" + fi +fi + +echo "" +echo -e "${GREEN}Symlinks created successfully! 🔗${NC}" +echo "" +echo -e "${YELLOW}Next steps:${NC}" +echo "1. Edit ~/.ssh/config with your actual values" +echo "2. Restart your shell or run: source ~/.zshrc" +echo "3. Review and customize any linked configurations" \ No newline at end of file diff --git a/shell/history-sync.zsh b/shell/history-sync.zsh new file mode 100644 index 0000000..eb5d1b1 --- /dev/null +++ b/shell/history-sync.zsh @@ -0,0 +1,49 @@ +#!/usr/bin/env zsh +# Shell history synchronization for dotfiles +# Add this to your .zshrc + +# History configuration +export HISTFILE="$HOME/.zsh_history" +export HISTSIZE=100000 +export SAVEHIST=100000 + +# Better history behavior +setopt EXTENDED_HISTORY # Write timestamp to history +setopt HIST_EXPIRE_DUPS_FIRST # Expire duplicates first +setopt HIST_IGNORE_DUPS # Don't record duplicates +setopt HIST_IGNORE_SPACE # Don't record commands starting with space +setopt HIST_VERIFY # Show command before executing from history +setopt INC_APPEND_HISTORY # Add commands immediately +setopt SHARE_HISTORY # Share history between sessions + +# Create a backup of history on each new session +if [[ -f "$HISTFILE" ]]; then + HIST_BACKUP_DIR="$HOME/.history_backups" + mkdir -p "$HIST_BACKUP_DIR" + + # Keep daily backups for the last 7 days + cp "$HISTFILE" "$HIST_BACKUP_DIR/zsh_history_$(date +%Y%m%d)" + + # Clean up old backups (keep last 7 days) + find "$HIST_BACKUP_DIR" -name "zsh_history_*" -mtime +7 -delete 2>/dev/null +fi + +# Function to sync history to dotfiles (call manually) +history_checkpoint() { + local dotfiles_history="$HOME/dotfiles/shell/zsh_history_checkpoint" + if [[ -f "$HISTFILE" ]]; then + # Keep last 10000 commands as checkpoint + tail -n 10000 "$HISTFILE" > "$dotfiles_history" + echo "History checkpoint saved to dotfiles" + fi +} + +# Function to search all history including backups +history_search_all() { + local pattern="$1" + echo "Searching current history..." + history | grep -i "$pattern" + + echo -e "\nSearching history backups..." + find "$HOME/.history_backups" -name "zsh_history_*" -exec grep -H -i "$pattern" {} \; +} \ No newline at end of file diff --git a/ssh/README.md b/ssh/README.md new file mode 100644 index 0000000..68ec596 --- /dev/null +++ b/ssh/README.md @@ -0,0 +1,52 @@ +# SSH Configuration + +## ⚠️ Security Notice +Never commit private keys to git! This directory contains only: +- Example SSH config (sanitized) +- Public keys (safe to share) +- Setup scripts + +## Setting up SSH on a new machine + +1. **Generate new SSH keys** (if needed): +```bash +# GitHub +ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/github + +# General purpose +ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519 +``` + +2. **Restore SSH config**: +```bash +cp ~/dotfiles/ssh/config.example ~/.ssh/config +# Edit ~/.ssh/config to add your actual hostnames, users, and key paths +``` + +3. **Set correct permissions**: +```bash +chmod 700 ~/.ssh +chmod 600 ~/.ssh/config +chmod 600 ~/.ssh/*_key +chmod 644 ~/.ssh/*.pub +``` + +4. **Restore existing keys** (if you have encrypted backups): +```bash +# Decrypt backup +gpg -d ~/dotfiles/backups/ssh_[timestamp].tar.gz.gpg | tar -xzf - +``` + +## SSH Config Best Practices + +- Use SSH key agent: `ssh-add -K ~/.ssh/your_key` +- Use different keys for different services +- Enable 2FA where possible +- Regularly rotate keys + +## Backup Strategy + +Run the backup script to create encrypted backups: +```bash +~/dotfiles/backup-scripts/backup-sensitive.sh +``` \ No newline at end of file diff --git a/ssh/config.example b/ssh/config.example new file mode 100644 index 0000000..f915c57 --- /dev/null +++ b/ssh/config.example @@ -0,0 +1,32 @@ +# SSH Config Template +# Copy to ~/.ssh/config and update with your actual values + +# Global defaults +Host * + AddKeysToAgent yes + UseKeychain yes + # Update with your default key + IdentityFile ~/.ssh/id_ed25519 + +# GitHub +Host github.com + HostName github.com + User git + IdentityFile ~/.ssh/github_key + IdentitiesOnly yes + +# Example: Personal Server +# Host myserver +# HostName server.example.com +# User yourusername +# Port 22 +# IdentityFile ~/.ssh/server_key +# IdentitiesOnly yes + +# Example: Work Server with Jump Host +# Host work-server +# HostName internal.work.com +# User workuser +# ProxyJump jumphost.work.com +# IdentityFile ~/.ssh/work_key +# IdentitiesOnly yes \ No newline at end of file