Files
David F GliddenandClaude Opus 5 4b3e08dc7f [FIX] zsh ate the question mark before the wrapper ran
'tarbuckle opinion?' failed at '(eval):1: no matches found' — zsh expands ?, * and [ as
globs before the script is reached, and asking him a question is the natural use of the
one surface built for questions.

Three ways past it, and the wrapper's help now names all three in order of least fuss:
drop the ?, quote the phrase, or the noglob alias now in shell/.zshrc. ⚠ The alias is
listed LAST and with its limit stated, because it only helps if the calling shell is
interactive — .zshrc is not read otherwise — and that is exactly the kind of fix that
looks total and silently is not.

noglob for one command rather than 'unsetopt nomatch', which would change how every
command in the shell behaves to fix one of them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J6hZXNYSxEfZseBGTni4sf
2026-08-25 18:39:14 +02:00

216 lines
13 KiB
Bash

# ░░░░▀▀█░█▀▀░█░█░█▀▄░█▀▀
# ░░░░▄▀░░▀▀█░█▀█░█▀▄░█░░
# ░▀░░▀▀▀░▀▀▀░▀░▀░▀░▀░▀▀▀
# Refined shell configuration following durability principles
# ASCII art: TextKool (https://textkool.com/en) "Font: Pagga"
# ═══════════════════════════════════════════════════════════════════════════════
# PERFORMANCE & EARLY INITIALIZATION
# ═══════════════════════════════════════════════════════════════════════════════
# Enable Powerlevel10k instant prompt (must be near top)
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
# ═══════════════════════════════════════════════════════════════════════════════
# CORE ENVIRONMENT SETUP
# ═══════════════════════════════════════════════════════════════════════════════
# Source modular configuration files
local config_files=(
"$HOME/dotfiles/shell/environment.zsh"
"$HOME/dotfiles/shell/paths.zsh"
)
for config_file in "${config_files[@]}"; do
[[ -f "$config_file" ]] && source "$config_file"
done
# ═══════════════════════════════════════════════════════════════════════════════
# PLUGIN MANAGEMENT
# ═══════════════════════════════════════════════════════════════════════════════
# Antidote plugin manager with graceful fallback
if [[ -f "/opt/homebrew/share/antidote/antidote.zsh" ]]; then
source /opt/homebrew/share/antidote/antidote.zsh
# Load plugins from manifest
local plugin_file="$HOME/dotfiles/shell/.zsh-plugins.txt"
if [[ -f "$plugin_file" ]]; then
antidote load < "$plugin_file"
elif [[ -z "${P10K_INSTANT_PROMPT-}" ]]; then
echo "⚠️ Plugin manifest not found: $plugin_file"
fi
elif [[ -z "${P10K_INSTANT_PROMPT-}" ]]; then
echo "⚠️ Antidote not found. Install with: brew install antidote"
fi
# ═══════════════════════════════════════════════════════════════════════════════
# PROMPT CONFIGURATION
# ═══════════════════════════════════════════════════════════════════════════════
# Powerlevel10k configuration
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
# Run 'p10k configure' to reconfigure prompt
# ═══════════════════════════════════════════════════════════════════════════════
# SHELL BEHAVIOR & OPTIONS
# ═══════════════════════════════════════════════════════════════════════════════
# Directory navigation
setopt auto_cd # Type directory name to cd into it
setopt auto_pushd # Make cd push old directory onto stack
setopt pushd_ignore_dups # Don't push duplicates onto stack
setopt pushd_minus # Make pushd work like cd
# Command correction and expansion
setopt correct # Spelling correction for commands
setopt correct_all # Spelling correction for arguments
setopt interactive_comments # Allow comments in interactive shell
setopt extended_glob # Enable extended globbing
setopt glob_dots # Don't require leading . in filename to be matched
# History configuration (extended)
setopt extended_history # Record timestamp and duration
setopt hist_expire_dups_first # Expire duplicates first
setopt hist_ignore_all_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
setopt hist_reduce_blanks # Remove superfluous blanks
# Job control
setopt auto_resume # Single word commands can resume jobs
setopt long_list_jobs # List jobs in long format
setopt notify # Report status of background jobs immediately
# ═══════════════════════════════════════════════════════════════════════════════
# COMPLETION SYSTEM
# ═══════════════════════════════════════════════════════════════════════════════
# Initialize completion system (suppress warnings during instant prompt)
autoload -Uz compinit
if [[ -n "${P10K_INSTANT_PROMPT-}" ]]; then
compinit -d ~/.zcompdump 2>/dev/null
else
compinit
fi
# Completion options
setopt complete_in_word # Complete from both ends of word
setopt always_to_end # Move cursor to end after completion
setopt auto_menu # Show completion menu on successive tab
setopt auto_list # Automatically list choices on ambiguous completion
setopt auto_param_slash # Add trailing slash for directory completions
# Completion styling
zstyle ':completion:*' menu select
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*'
# ═══════════════════════════════════════════════════════════════════════════════
# TOOL INTEGRATIONS
# ═══════════════════════════════════════════════════════════════════════════════
# (fzf and zoxide removed — not installed)
# ═══════════════════════════════════════════════════════════════════════════════
# GNU COREUTILS (interactive-only PATH)
# ═══════════════════════════════════════════════════════════════════════════════
# Prevent GMP and other formulae from breaking by keeping gnubin off build PATH.
# Only activate in interactive shells.
if [[ $- == *i* ]]; then
export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH"
fi
# ═══════════════════════════════════════════════════════════════════════════════
# NODE VERSION MANAGEMENT
# ═══════════════════════════════════════════════════════════════════════════════
# NVM integration with lazy loading for performance
[[ -f "$HOME/dotfiles/shell/nvm.zsh" ]] && source "$HOME/dotfiles/shell/nvm.zsh"
# Ensure claude-code is accessible (after nvm setup)
if [[ -d "$HOME/.nvm/versions/node/v22.16.0/bin" ]] && [[ ! -v NVM_LOADED ]]; then
# Add claude-code's Node bin to PATH as fallback
# This ensures claude-code works even before nvm is fully loaded
export PATH="$HOME/.nvm/versions/node/v22.16.0/bin:$PATH"
fi
# ═══════════════════════════════════════════════════════════════════════════════
# CUSTOM FUNCTIONS & ALIASES
# ═══════════════════════════════════════════════════════════════════════════════
# Load enhanced functions and aliases
local shell_files=(
"$HOME/dotfiles/shell/functions.zsh"
"$HOME/dotfiles/shell/aliases.zsh"
)
for shell_file in "${shell_files[@]}"; do
if [[ -f "$shell_file" ]]; then
source "$shell_file"
elif [[ -z "${P10K_INSTANT_PROMPT-}" ]]; then
echo "⚠️ Shell configuration missing: $shell_file"
fi
done
# Legacy files removed - using dotfiles versions
# ═══════════════════════════════════════════════════════════════════════════════
# CONTEXT AWARENESS
# ═══════════════════════════════════════════════════════════════════════════════
# Detect and set initial context
detect_context
# Display context-aware welcome message (interactive shells only)
if [[ $- == *i* ]] && [[ -z "$VSCODE_INJECTION" ]]; then
case "$CURRENT_CONTEXT" in
"work") echo "🏢 Work context activated" ;;
"chamber") echo "🔮 Chamber context activated" ;;
"vault") echo "📚 Vault context activated" ;;
"dotfiles") echo "⚙️ Dotfiles context activated" ;;
esac
fi
# ═══════════════════════════════════════════════════════════════════════════════
# PERFORMANCE OPTIMIZATION
# ═══════════════════════════════════════════════════════════════════════════════
# Fast mode for non-interactive shells
[[ $- != *i* ]] && unsetopt zle && return
# ═══════════════════════════════════════════════════════════════════════════════
# LOCAL CUSTOMIZATIONS
# ═══════════════════════════════════════════════════════════════════════════════
# Machine-specific configurations
[[ -f "$HOME/.zshrc.local" ]] && source "$HOME/.zshrc.local"
# Development environment configurations
[[ -f "$HOME/.env.local" ]] && source "$HOME/.env.local"
# ═══════════════════════════════════════════════════════════════════════════════
# LEGACY & MIGRATION SUPPORT
# ═══════════════════════════════════════════════════════════════════════════════
# Temporary: Handle pipx path duplication (remove after migration)
typeset -U path PATH
# Note: This configuration follows the μέτρον principle
# - Each section has clear purpose and boundaries
# - Graceful degradation when tools are missing
# - Performance considerations for different use cases
# - Modular structure for maintainability
# Tarbuckle — call him by name with an actual question.
# zsh treats `?` (and `*`, `[`) as globs, so `tarbuckle opinion?` dies at
# "no matches found" before the wrapper is ever reached. noglob suspends filename
# generation for this command only. Not `unsetopt nomatch`, which would change how
# every command in the shell behaves to fix one of them.
alias tarbuckle='noglob tarbuckle'