Files
David F GliddenandClaude Opus 4.6 066a47a26b Audit and optimize for CapableMind development
Brewfile: stripped to essential tools (~600MB freed), removed boost,
cmake, aerc, newsboat, fontforge, starship, and 24 auto-dependencies.
Added caffeine, ollama, fastfetch, ocrmypdf, tea, sshpass, vitetris.
Dropped 1password, iterm2, github-desktop, hazel, swiftbar, oversight.

Shell: fixed all stale references (fzf, zoxide, starship, old paths,
Homebrew node aliases). Updated project paths to ~/_Dev/. Added
CapableMind aliases (cm, bmf, bmf-health, bmf-status, bmf-logs).

Configs: removed iterm2, neofetch, swiftbar configs. Added capablemind
(launchd plists, MCP example, bmf-start script). Updated SSH config
with git.skemantix.com. Added CLAUDE.md to dotfiles.

Scripts: consolidated 3 backup scripts into 1 (backup-all-secrets.sh),
added pass store backup. Added setup-capablemind.sh for full environment
reconstruction. Updated symlinks.sh for new config structure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 23:45:33 +01:00

350 lines
12 KiB
Bash

# ░█▀▀░█░█░█▀█░█▀▀░▀█▀░▀█▀░█▀█░█▀█░█▀▀
# ░█▀▀░█░█░█░█░█░░░░█░░░█░░█░█░█░█░▀▀█
# ░▀░░░▀▀▀░▀░▀░▀▀▀░░▀░░▀▀▀░▀▀▀░▀░▀░▀▀▀
## I. PDF Compression #######################
pdfcompress ()
{
gs -q -dNOPAUSE -dBATCH -dSAFER -sDEVICE=pdfwrite -dCompatibilityLevel=1.3 -dPDFSETTINGS=/screen -dEmbedAllFonts=true -dSubsetFonts=true -dColorImageDownsampleType=/Bicubic -dColorImageResolution=144 -dGrayImageDownsampleType=/Bicubic -dGrayImageResolution=144 -dMonoImageDownsampleType=/Bicubic -dMonoImageResolution=144 -sOutputFile=$1.compressed.pdf $1;
}
## II. Weather #######################
wttr() {
# Usage: wttr [location]
# Examples: wttr -> your IP-based location
# wttr 75012 -> Paris 12e
# wttr 23190 -> Crozant
local location=${1:-}
curl -s "wttr.in/${location}?n"
}
## III. Updates (system, brew, etc) #######################
## Description: Performs system updates, Homebrew cleanup, moon phase logging, and dotfile sync ###########################
function sysupdate() {
local start_time=$(date +%s)
echo "🔧 Starting full system update at $(date)"
# Ensure sudo credentials are fresh
if ! sudo -vn 2>/dev/null; then
echo "🔒 sudo authentication required..."
sudo -v
fi
echo "🍎 Updating macOS Software..."
sudo softwareupdate -i -a
echo "🍺 Updating Homebrew packages..."
brew update
brew upgrade
brew cleanup
brew autoremove
# Mac App Store updates
echo "🍎 Updating Mac App Store apps..."
if command -v mas >/dev/null; then
local mas_outdated=$(mas outdated)
if [[ -n "$mas_outdated" ]]; then
echo "📱 Updating MAS apps:"
echo "$mas_outdated" | while read -r line; do
echo " $line"
done
mas upgrade || echo "⚠️ Some MAS updates may require manual intervention"
else
echo "✅ All MAS apps are up to date"
fi
else
echo "⚠️ mas not installed - install with: brew install mas"
fi
# fzf removed — no longer installed
# Fix Zsh completion security warnings
echo "🔒 Checking Zsh completion security..."
if [[ -d "/opt/homebrew/share/zsh" ]]; then
# Fix common Homebrew Zsh permission issues
chmod 755 /opt/homebrew/share/zsh /opt/homebrew/share/zsh/site-functions 2>/dev/null || true
fi
echo "🧹 Checking for broken symlinks..."
find /usr/local/bin "$HOME/bin" "$HOME/.local/bin" -xtype l 2>/dev/null
echo "🌓 Moon phase at update time:"
if command -v curl &>/dev/null && command -v jq >/dev/null; then
# Use API key from SwiftBar script
local api_key="6ec71a8170214d828c08ba8bf2ca29e9"
moon_json=$(curl -s "https://api.ipgeolocation.io/astronomy?apiKey=$api_key" 2>/dev/null)
if [[ $? -eq 0 ]] && [[ -n "$moon_json" ]]; then
moon_phase=$(echo "$moon_json" | jq -r '.moon_phase // "Unknown"' | tr '_' ' ')
illum=$(echo "$moon_json" | jq -r '.moon_illumination_percentage // "Unknown"')
# Add moon emoji based on phase
local moon_emoji="🌙"
case "$moon_phase" in
"new moon") moon_emoji="🌑" ;;
"waxing crescent") moon_emoji="🌒" ;;
"first quarter") moon_emoji="🌓" ;;
"waxing gibbous") moon_emoji="🌔" ;;
"full moon") moon_emoji="🌕" ;;
"waning gibbous") moon_emoji="🌖" ;;
"last quarter") moon_emoji="🌗" ;;
"waning crescent") moon_emoji="🌘" ;;
esac
echo "$moon_emoji $moon_phase (${illum}%)"
else
echo "🌙 Moon phase unavailable"
fi
else
echo "🌙 Moon phase tracking disabled (missing curl or jq)"
fi
if [ -d "$HOME/dotfiles" ]; then
echo "📝 Committing dotfile changes..."
cd ~/dotfiles || return
git add . && git commit -m "🔧 Auto-commit from sysupdate on $(date '+%Y-%m-%d %H:%M')" && git push
brew bundle dump --force --file="$HOME/dotfiles/Brewfile"
cd - >/dev/null || return
fi
echo "📊 System Info:"
echo "💻 $(uname -a)"
echo "📅 macOS: $(sw_vers | grep ProductVersion)"
echo "🧠 Memory: $(top -l 1 -s 0 | grep PhysMem)"
# Optional post-update hook
if [ -x "$HOME/.zsh/hooks/post-update" ]; then
"$HOME/.zsh/hooks/post-update"
fi
echo "🕓 Duration: $(($(date +%s) - $start_time))s"
osascript -e 'display notification "Update complete!" with title "System Maintenance" subtitle "All systems go 🚀"'
}
# 💤 Quiet version (no output, same functionality)
function quietupdate() {
local start_time=$(date +%s)
sudo -vn 2>/dev/null || sudo -v
sudo softwareupdate -i -a >/dev/null
brew update >/dev/null && brew upgrade >/dev/null && brew cleanup >/dev/null && brew autoremove >/dev/null
[ -d "$HOME/dotfiles" ] && cd ~/dotfiles && git add . && git commit -m "auto sysupdate" && git push && brew bundle dump --force --file="$HOME/dotfiles/Brewfile" && cd - >/dev/null
if [ -x "$HOME/.zsh/hooks/post-update" ]; then "$HOME/.zsh/hooks/post-update"; fi
osascript -e 'display notification "Quiet update complete!" with title "System Maintenance"'
}
# ═══════════════════════════════════════════════════════════════════════════════
# Modern, workspace-aware man page viewer
# - Kitty/tmux/iTerm split panes, syntax highlighting via bat
# - Optional qman integration for interactive TOC/search
# - Order-flexible + apropos search
# ═══════════════════════════════════════════════════════════════════════════════
man() {
if [[ $# -eq 0 ]]; then
echo "Usage:"
echo " man <command> [section]"
echo " man [section] <command>"
echo " man ? <search-term> # apropos search"
return 1
fi
# Apropos mode
if [[ "$1" == "?" ]]; then
shift
/usr/bin/man -k "$@"
return
fi
# Support both orders: man 2 open OR man open 2
local cmd section
if [[ "$1" =~ ^[0-9]+$ && -n "$2" ]]; then
section="$1"; cmd="$2"
else
cmd="$1"; section="${2:-}"
fi
# Verify page exists
if ! /usr/bin/man -w ${section:+$section} -- "$cmd" >/dev/null 2>&1; then
echo "❌ No manual entry for '$cmd'${section:+ in section $section}"
echo "💡 Try: man ? $cmd"
return 1
fi
# Choose backend
local display_cmd
if command -v qman >/dev/null 2>&1; then
display_cmd="qman ${section:+$section }-- '$cmd'"
else
local bat_path; bat_path=$(command -v bat 2>/dev/null || true)
if [[ -n "$bat_path" ]]; then
display_cmd="export MANWIDTH=\$(tput cols); /usr/bin/man ${section:+$section} '$cmd' 2>/dev/null \
| col -bx \
| '$bat_path' --language=man --style=grid --theme=\${BAT_THEME:-Nord} \
--paging=always --terminal-width=\$(tput cols) --wrap=auto"
else
display_cmd="export MANWIDTH=\$(tput cols); MANPAGER='less -R' /usr/bin/man ${section:+$section} '$cmd'"
fi
fi
# Handle different terminal environments
if [[ -n "${KITTY_WINDOW_ID:-}" ]]; then
kitty @ launch \
--location=vsplit \
--title="📖 $cmd${section:+ ($section)}" \
--cwd=current \
--bias=${KITTY_BIAS:-60} \
zsh -lc "$display_cmd" >/dev/null
elif [[ -n "${TMUX:-}" ]]; then
tmux split-window -v -l ${TMUX_HEIGHT:-40%} "$display_cmd"
elif [[ "${TERM_PROGRAM}" == "iTerm.app" ]]; then
osascript -e "
tell application \"iTerm\"
tell current window
tell current session
split vertically with default profile
tell last session
write text \"$display_cmd\"
set name to \"📖 $cmd${section:+ ($section)}\"
end tell
end tell
end tell
end tell" >/dev/null 2>&1
else
echo "📖 Displaying man page inline:"
eval "$display_cmd"
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# DOTFILES MANAGEMENT FUNCTIONS
# ═══════════════════════════════════════════════════════════════════════════════
# Quick navigation to dotfiles directory
dot() {
cd ~/dotfiles
[[ $# -gt 0 ]] && "$@"
}
# Quick edit common configs with automatic reload
zedit() {
${EDITOR:-nano} ~/.zshrc && source ~/.zshrc
echo "✅ .zshrc reloaded"
}
aedit() {
${EDITOR:-nano} ~/dotfiles/shell/aliases.zsh && source ~/.zshrc
echo "✅ aliases reloaded"
}
fedit() {
${EDITOR:-nano} ~/dotfiles/shell/functions.zsh && source ~/.zshrc
echo "✅ functions reloaded"
}
pedit() {
${EDITOR:-nano} ~/dotfiles/shell/paths.zsh && source ~/.zshrc
echo "✅ paths reloaded"
}
# Backup critical configs with timestamp
backup-configs() {
local backup_dir="$HOME/.config-backups/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
echo "📦 Backing up critical configs to: $backup_dir"
# SSH keys (if they exist)
if [[ -d ~/.ssh ]]; then
cp -R ~/.ssh "$backup_dir/" 2>/dev/null || true
echo " ✓ SSH configuration"
fi
# Shell history
if [[ -f ~/.zsh_history ]]; then
cp ~/.zsh_history "$backup_dir/" 2>/dev/null || true
echo " ✓ Shell history"
fi
# GPG keys (if they exist)
if [[ -d ~/.gnupg ]]; then
cp -R ~/.gnupg "$backup_dir/" 2>/dev/null || true
echo " ✓ GPG configuration"
fi
echo "✅ Configs backed up to: $backup_dir"
}
# ═══════════════════════════════════════════════════════════════════════════════
# LICENSE MANAGEMENT FUNCTIONS FOR PASS
# ═══════════════════════════════════════════════════════════════════════════════
# License management: add a license entry with optional attached file
license-add() {
if [ $# -lt 1 ]; then
echo "Usage: license-add <product-name> [license-file-path]"
return 1
fi
local product="$1"
local entry="licenses/$product"
local dir="$HOME/.password-store/${entry}.gpg.d"
echo "→ Paste activation code or license metadata for '$product', then press Ctrl+D:"
pass insert -m "$entry" || return 1
if [ $# -eq 2 ]; then
local filepath="$2"
local filename="$(basename "$filepath")"
mkdir -p "$dir"
gpg -o "$dir/${filename}.gpg" -e -r "$(gpg --list-secret-keys --with-colons | awk -F: '/^uid:/ {print $10; exit}')" "$filepath"
echo "✔️ Encrypted license file saved as: $dir/${filename}.gpg"
else
echo "✔️ Code-only license entry created for '$product'."
fi
}
# Edit a license entry in the pass store
license-edit() {
if [ $# -ne 1 ]; then
echo "Usage: license-edit <product-name>"
return 1
fi
local product="$1"
pass edit "licenses/$product"
}
# List all stored licenses
license-list() {
pass ls licenses/ | sed 's/^licenses\///' | sort
}
# Show license details and attached files for a product
license-info() {
if [ $# -ne 1 ]; then
echo "Usage: license-info <product-name>"
return 1
fi
local product="$1"
local entry="licenses/$product"
local pass_file="$HOME/.password-store/${entry}.gpg"
local attach_dir="$HOME/.password-store/${entry}.gpg.d"
if [ ! -f "$pass_file" ]; then
echo "❌ No license entry found for '$product'"
return 1
fi
echo "🔐 License entry: $product"
echo "----------------------------------------"
pass show "$entry"
echo
if [ -d "$attach_dir" ]; then
echo "📎 Attached encrypted file(s):"
find "$attach_dir" -type f -name '*.gpg' -exec basename {} \;
else
echo "📎 No attached files."
fi
}