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>
This commit is contained in:
David F Glidden
2026-03-20 23:45:33 +01:00
co-authored by Claude Opus 4.6
parent e7bb361bd2
commit 066a47a26b
72 changed files with 785 additions and 2032 deletions
+6
View File
@@ -50,6 +50,12 @@ if [[ -f "$HOME/.docker/config.json" ]]; then
cp "$HOME/.docker/config.json" "$TEMP_DIR/secrets/.docker/"
fi
# Password store (pass — software licenses, credentials)
if [[ -d "$HOME/.password-store" ]]; then
echo " 🔑 Password store (pass)"
cp -r "$HOME/.password-store" "$TEMP_DIR/secrets/"
fi
# Any license files or certificates (if found)
if [[ -f "$HOME/.vuescanrc" ]]; then
echo " 📄 VueScan license"
-170
View File
@@ -1,170 +0,0 @@
#!/usr/bin/env bash
# Backup all private keys and sensitive configurations
# Following prime directive: durable, thoughtful backup strategy
set -euo pipefail
BACKUP_DIR="$HOME/dotfiles/backups"
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 "${YELLOW}🔐 Creating encrypted backup of private keys and secrets${NC}"
echo "Timestamp: $TIMESTAMP"
echo ""
# Create backup directory
mkdir -p "$BACKUP_DIR"/{ssh,gpg,docker}
# Function to create encrypted backup
create_encrypted_backup() {
local source_dir="$1"
local backup_name="$2"
local backup_path="$BACKUP_DIR/$backup_name"
if [[ -d "$source_dir" ]] || [[ -f "$source_dir" ]]; then
echo -e "${YELLOW}Backing up: $source_dir${NC}"
# Create tar archive and encrypt in one step
tar -czf - -C "$(dirname "$source_dir")" "$(basename "$source_dir")" | \
gpg --symmetric --cipher-algo AES256 --compress-algo 2 \
--output "${backup_path}/${backup_name}_${TIMESTAMP}.tar.gz.gpg"
# Create restore instructions
cat > "${backup_path}/RESTORE_INSTRUCTIONS.md" << EOF
# ${backup_name^} Restore Instructions
## Decrypting and Restoring ${backup_name^}
To restore from backup: \`${backup_name}_${TIMESTAMP}.tar.gz.gpg\`
### Step 1: Decrypt the backup
\`\`\`bash
gpg --decrypt ${backup_name}_${TIMESTAMP}.tar.gz.gpg > ${backup_name}_${TIMESTAMP}.tar.gz
\`\`\`
### Step 2: Extract the archive
\`\`\`bash
tar -xzf ${backup_name}_${TIMESTAMP}.tar.gz -C ~/
\`\`\`
### Step 3: Set correct permissions
\`\`\`bash
chmod 700 ~/$(basename "$source_dir")
find ~/$(basename "$source_dir") -type f -exec chmod 600 {} \;
\`\`\`
## Security Notes
- Keep this encrypted backup secure
- Contains private keys/sensitive data
- Test restore process periodically
## Backup Contents
This backup includes: $(basename "$source_dir")
Created: $(date)
System: $(sw_vers -productVersion)
EOF
echo -e "${GREEN}✅ Backup created: ${backup_path}/${backup_name}_${TIMESTAMP}.tar.gz.gpg${NC}"
else
echo -e "${RED}⚠️ Source not found: $source_dir${NC}"
fi
}
# Backup GPG private keys and keyring
if [[ -d "$HOME/.gnupg" ]]; then
echo -e "${YELLOW}🔑 Backing up GPG private keys and keyring...${NC}"
# Create temporary directory with essential GPG files
temp_gpg=$(mktemp -d)
mkdir -p "$temp_gpg/.gnupg"
# Copy essential GPG files (not temporary/socket files)
cp -r "$HOME/.gnupg/private-keys-v1.d" "$temp_gpg/.gnupg/" 2>/dev/null || true
cp "$HOME/.gnupg/pubring.kbx" "$temp_gpg/.gnupg/" 2>/dev/null || true
cp "$HOME/.gnupg/trustdb.gpg" "$temp_gpg/.gnupg/" 2>/dev/null || true
cp "$HOME/.gnupg/gpg.conf" "$temp_gpg/.gnupg/" 2>/dev/null || true
cp "$HOME/.gnupg/gpg-agent.conf" "$temp_gpg/.gnupg/" 2>/dev/null || true
cp "$HOME/.gnupg/dirmngr.conf" "$temp_gpg/.gnupg/" 2>/dev/null || true
# Create encrypted backup
tar -czf - -C "$temp_gpg" .gnupg | \
gpg --symmetric --cipher-algo AES256 --compress-algo 2 \
--output "$BACKUP_DIR/gpg/gpg_keyring_${TIMESTAMP}.tar.gz.gpg"
# Cleanup
rm -rf "$temp_gpg"
# Create restore instructions
cat > "$BACKUP_DIR/gpg/RESTORE_INSTRUCTIONS.md" << 'EOF'
# GPG Keyring Restore Instructions
## Decrypting and Restoring GPG Keys
To restore from backup: `gpg_keyring_TIMESTAMP.tar.gz.gpg`
### Step 1: Decrypt the backup
```bash
gpg --decrypt gpg_keyring_TIMESTAMP.tar.gz.gpg > gpg_keyring_TIMESTAMP.tar.gz
```
### Step 2: Extract to home directory
```bash
tar -xzf gpg_keyring_TIMESTAMP.tar.gz -C ~/
```
### Step 3: Set correct permissions
```bash
chmod 700 ~/.gnupg
chmod 600 ~/.gnupg/*
chmod 700 ~/.gnupg/private-keys-v1.d
chmod 600 ~/.gnupg/private-keys-v1.d/*
```
### Step 4: Restart GPG agent
```bash
gpgconf --kill gpg-agent
gpg --list-secret-keys # This will restart the agent
```
## Security Notes
- Contains your GPG private keys - highly sensitive
- Keep encrypted backup in secure location
- Test restore process periodically
## What's Included
- Private keys (private-keys-v1.d/)
- Public keyring (pubring.kbx)
- Trust database (trustdb.gpg)
- GPG configuration files
Created: $(date)
System: $(sw_vers -productVersion)
EOF
echo -e "${GREEN}✅ GPG keyring backup created${NC}"
fi
# Backup Docker configuration
if [[ -f "$HOME/.docker/config.json" ]]; then
create_encrypted_backup "$HOME/.docker" "docker"
fi
# Summary
echo ""
echo -e "${GREEN}🎉 Backup Summary:${NC}"
echo "📁 Backups stored in: $BACKUP_DIR"
echo "🔐 All backups are GPG encrypted with AES256"
echo "📋 Each backup includes restore instructions"
echo ""
echo -e "${YELLOW}💡 Recommended: Store a copy of these backups in a separate secure location${NC}"
echo -e "${YELLOW}📋 Test restore process periodically to ensure backups work${NC}"
-182
View File
@@ -1,182 +0,0 @@
#!/usr/bin/env bash
# Backup and encrypt SSH keys
set -euo pipefail
SSH_DIR="$HOME/.ssh"
BACKUP_DIR="$HOME/dotfiles/backups/ssh"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}SSH Keys Backup & Encryption${NC}"
echo "==============================="
# Check if SSH directory exists
if [ ! -d "$SSH_DIR" ]; then
echo -e "${RED}❌ SSH directory not found: $SSH_DIR${NC}"
exit 1
fi
# Check if GPG is available
if ! command -v gpg >/dev/null 2>&1; then
echo -e "${RED}❌ GPG not found. Please install GPG first.${NC}"
echo "Install with: brew install gnupg"
exit 1
fi
# Create backup directory
mkdir -p "$BACKUP_DIR"
echo -e "${YELLOW}🔍 Scanning SSH directory...${NC}"
# Find private keys (files without .pub extension and not config/known_hosts)
PRIVATE_KEYS=()
while IFS= read -r -d '' file; do
filename=$(basename "$file")
# Skip public keys, config files, and known_hosts
if [[ ! "$filename" =~ \.(pub|ppk)$ ]] && \
[[ "$filename" != "config" ]] && \
[[ "$filename" != "known_hosts" ]] && \
[[ "$filename" != "authorized_keys" ]]; then
PRIVATE_KEYS+=("$file")
fi
done < <(find "$SSH_DIR" -type f -print0)
if [ ${#PRIVATE_KEYS[@]} -eq 0 ]; then
echo -e "${YELLOW}⚠️ No private keys found to backup${NC}"
exit 0
fi
echo -e "${GREEN}Found ${#PRIVATE_KEYS[@]} private key(s):${NC}"
for key in "${PRIVATE_KEYS[@]}"; do
echo " • $(basename "$key")"
done
echo ""
# Ask for confirmation
read -p "Proceed with backup and encryption? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Backup cancelled."
exit 0
fi
# Create tarball of SSH directory
TEMP_TAR="/tmp/ssh_backup_${TIMESTAMP}.tar"
echo -e "${YELLOW}📦 Creating backup archive...${NC}"
# Create tar with only the files we want
tar -cf "$TEMP_TAR" -C "$HOME" .ssh/config 2>/dev/null || true
# Add private keys to tar
for key in "${PRIVATE_KEYS[@]}"; do
relative_path=$(echo "$key" | sed "s|$HOME/||")
tar -rf "$TEMP_TAR" -C "$HOME" "$relative_path" 2>/dev/null || true
echo " ✓ Added: $(basename "$key")"
done
# Add public keys corresponding to private keys
for key in "${PRIVATE_KEYS[@]}"; do
pub_key="${key}.pub"
if [ -f "$pub_key" ]; then
relative_path=$(echo "$pub_key" | sed "s|$HOME/||")
tar -rf "$TEMP_TAR" -C "$HOME" "$relative_path" 2>/dev/null || true
echo " ✓ Added: $(basename "$pub_key")"
fi
done
# Compress the tar
gzip "$TEMP_TAR"
TEMP_TAR="${TEMP_TAR}.gz"
# Encrypt with GPG
ENCRYPTED_FILE="$BACKUP_DIR/ssh_keys_${TIMESTAMP}.tar.gz.gpg"
echo -e "${YELLOW}🔐 Encrypting backup...${NC}"
echo "You will be prompted for a passphrase to encrypt the backup."
if gpg --symmetric --cipher-algo AES256 --compress-algo 1 --s2k-mode 3 \
--s2k-digest-algo SHA512 --s2k-count 65536 \
--output "$ENCRYPTED_FILE" "$TEMP_TAR"; then
# Clean up temporary file
rm "$TEMP_TAR"
echo -e "${GREEN}✅ SSH keys backup completed!${NC}"
echo ""
echo "Backup details:"
echo " 📁 Location: $ENCRYPTED_FILE"
echo " 📏 Size: $(du -h "$ENCRYPTED_FILE" | cut -f1)"
echo " 🔑 Encryption: AES256"
echo ""
# Create restore instructions
cat > "$BACKUP_DIR/RESTORE_INSTRUCTIONS.md" << EOF
# SSH Keys Restore Instructions
## Decrypting and Restoring SSH Keys
To restore from backup: \`ssh_keys_${TIMESTAMP}.tar.gz.gpg\`
### Step 1: Decrypt the backup
\`\`\`bash
gpg --decrypt ssh_keys_${TIMESTAMP}.tar.gz.gpg > ssh_keys_${TIMESTAMP}.tar.gz
\`\`\`
### Step 2: Extract the archive
\`\`\`bash
tar -xzf ssh_keys_${TIMESTAMP}.tar.gz -C ~/
\`\`\`
### Step 3: Set correct permissions
\`\`\`bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/*_key ~/.ssh/id_*
chmod 644 ~/.ssh/*.pub
\`\`\`
### Step 4: Add keys to SSH agent (if needed)
\`\`\`bash
ssh-add ~/.ssh/your_key_name
\`\`\`
## Security Notes
- Keep this encrypted backup in a secure location
- The backup contains your private keys - treat it as highly sensitive
- Consider storing a copy in a different location (cloud storage, external drive)
- Test the restore process periodically
## Backup Contents
This backup includes:
- SSH configuration file
- Private keys found in ~/.ssh/
- Corresponding public keys
- Proper directory structure
Created: $(date)
System: $(sw_vers -productVersion)
EOF
echo -e "${YELLOW}📋 Restore instructions created: $BACKUP_DIR/RESTORE_INSTRUCTIONS.md${NC}"
# Clean up old backups (keep last 5)
cd "$BACKUP_DIR"
ls -t ssh_keys_*.tar.gz.gpg 2>/dev/null | tail -n +6 | xargs -r rm
echo -e "${GREEN}🎉 Backup process complete!${NC}"
else
# Clean up on failure
rm -f "$TEMP_TAR"
echo -e "${RED}❌ Encryption failed!${NC}"
exit 1
fi
+173
View File
@@ -0,0 +1,173 @@
#!/usr/bin/env bash
# CapableMind development environment setup
# Run after engage (Brewfile) has installed base packages
#
# Prerequisites: Homebrew, Ollama, GPG, pass
# This script sets up: nvm/Node, Ollama models, BMF, launchd agents
set -euo pipefail
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo -e "${YELLOW}Setting up CapableMind development environment${NC}"
echo ""
# ============================================
# 1. NVM + Node.js
# ============================================
echo -e "${YELLOW}1. Node.js via nvm${NC}"
if [ -d "$HOME/.nvm" ]; then
echo -e "${GREEN} ✓ nvm already installed${NC}"
else
echo " Installing nvm..."
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
fi
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
if command -v node >/dev/null && [[ "$(node -v)" == v22.* ]]; then
echo -e "${GREEN} ✓ Node $(node -v) installed${NC}"
else
echo " Installing Node 22 LTS..."
nvm install 22
nvm alias default 22
fi
# ============================================
# 2. Ollama models
# ============================================
echo ""
echo -e "${YELLOW}2. Ollama models${NC}"
if ! command -v ollama >/dev/null; then
echo -e "${RED} ✗ Ollama not installed. Install via: brew install ollama${NC}"
else
# Required models for CapableMind
MODELS=("mxbai-embed-large" "qwen3.5:4b")
for model in "${MODELS[@]}"; do
if ollama list 2>/dev/null | grep -q "$model"; then
echo -e "${GREEN} ✓ $model already pulled${NC}"
else
echo " Pulling $model..."
ollama pull "$model"
fi
done
echo -e "${YELLOW} Note: cm-david trained models must be imported separately from clasp${NC}"
fi
# ============================================
# 3. Clone repositories
# ============================================
echo ""
echo -e "${YELLOW}3. Repositories${NC}"
DEV_DIR="$HOME/_Dev"
mkdir -p "$DEV_DIR"
declare -A REPOS=(
["BetterMemories.io"]="git@github.com:skemantix/BetterMemories.io.git"
["CapableMind-AI"]="git@github.com:skemantix/CapableMind.ai.git"
["chamber-library"]="git@github.com:skemantix/chamber-library.git"
["animal-davidglidden-eu"]="git@github.com:davidglidden/animal-davidglidden-eu.git"
)
for dir in "${!REPOS[@]}"; do
if [ -d "$DEV_DIR/$dir" ]; then
echo -e "${GREEN} ✓ $dir already cloned${NC}"
else
echo " Cloning $dir..."
git clone "${REPOS[$dir]}" "$DEV_DIR/$dir"
fi
done
# ============================================
# 4. BMF build
# ============================================
echo ""
echo -e "${YELLOW}4. Building BetterMemories (BMF)${NC}"
BMF_DIR="$DEV_DIR/BetterMemories.io"
if [ -d "$BMF_DIR" ]; then
cd "$BMF_DIR"
npm install
npm run build
echo -e "${GREEN} ✓ BMF built${NC}"
else
echo -e "${RED} ✗ BMF directory not found${NC}"
fi
# ============================================
# 5. Environment file
# ============================================
echo ""
echo -e "${YELLOW}5. CapableMind environment${NC}"
CM_DIR="$HOME/.capablemind"
mkdir -p "$CM_DIR"
if [ -f "$CM_DIR/env" ]; then
echo -e "${GREEN} ✓ env file exists${NC}"
else
cat > "$CM_DIR/env" << 'ENVEOF'
# CapableMind environment — add your API key
# ANTHROPIC_API_KEY=sk-ant-...
ENVEOF
echo -e "${YELLOW} ⚠ Created $CM_DIR/env — add your ANTHROPIC_API_KEY${NC}"
fi
# ============================================
# 6. Launchd agents
# ============================================
echo ""
echo -e "${YELLOW}6. Launchd agents${NC}"
AGENTS_DIR="$HOME/Library/LaunchAgents"
DOTFILES_CM="$HOME/dotfiles/config/capablemind"
if [ -d "$DOTFILES_CM" ]; then
for plist in "$DOTFILES_CM"/*.plist; do
name=$(basename "$plist")
if [ -f "$AGENTS_DIR/$name" ]; then
echo -e "${GREEN} ✓ $name already installed${NC}"
else
cp "$plist" "$AGENTS_DIR/"
echo -e "${GREEN} ✓ Installed $name${NC}"
echo -e "${YELLOW} Note: Edit paths in $AGENTS_DIR/$name before loading${NC}"
fi
done
else
echo -e "${YELLOW} ⚠ No capablemind config dir in dotfiles${NC}"
fi
# ============================================
# 7. Obsidian vault git mirror
# ============================================
echo ""
echo -e "${YELLOW}7. Obsidian vault sync${NC}"
VAULT_GIT="$DEV_DIR/david-root-and-branch-vault-git"
if [ -d "$VAULT_GIT" ]; then
echo -e "${GREEN} ✓ Vault git mirror exists${NC}"
else
echo -e "${YELLOW} ⚠ Vault git mirror not set up. Run ~/bin/obsidian_vault_sync.sh manually${NC}"
fi
# ============================================
# Summary
# ============================================
echo ""
echo -e "${GREEN}Setup complete.${NC}"
echo ""
echo -e "${YELLOW}Remaining manual steps:${NC}"
echo " 1. Add ANTHROPIC_API_KEY to ~/.capablemind/env"
echo " 2. Edit launchd plist paths if needed, then: launchctl load ~/Library/LaunchAgents/com.capablemind.*.plist"
echo " 3. Import trained cm-david models from clasp (if available)"
echo " 4. Run: cd ~/_Dev/BetterMemories.io && node dist/index.js (to start BMF)"
echo " 5. Reconnect MCP in Claude Code: /mcp"
+4 -3
View File
@@ -44,8 +44,6 @@ link_file "$DOTFILES_DIR/shell/.zshrc" "$HOME/.zshrc"
link_file "$DOTFILES_DIR/shell/.bashrc" "$HOME/.bashrc"
link_file "$DOTFILES_DIR/shell/.zprofile" "$HOME/.zprofile"
link_file "$DOTFILES_DIR/shell/.p10k.zsh" "$HOME/.p10k.zsh"
link_file "$DOTFILES_DIR/shell/.fzf.bash" "$HOME/.fzf.bash"
link_file "$DOTFILES_DIR/shell/.fzf.zsh" "$HOME/.fzf.zsh"
link_file "$DOTFILES_DIR/.gitconfig" "$HOME/.gitconfig"
link_file "$DOTFILES_DIR/.vimrc" "$HOME/.vimrc"
link_file "$DOTFILES_DIR/.npmrc" "$HOME/.npmrc"
@@ -78,8 +76,11 @@ fi
echo -e "${YELLOW}Linking config directories...${NC}"
mkdir -p "$HOME/.config"
# CLAUDE.md — prime directive for Claude Code
link_file "$DOTFILES_DIR/CLAUDE.md" "$HOME/CLAUDE.md"
# Link config subdirectories if they exist
for config_dir in git iterm2 kitty karabiner neofetch swiftbar; do
for config_dir in git kitty karabiner capablemind; do
if [ -d "$DOTFILES_DIR/config/$config_dir" ]; then
link_file "$DOTFILES_DIR/config/$config_dir" "$HOME/.config/$config_dir"
fi