-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdot_zshrc.tmpl
More file actions
692 lines (593 loc) · 22.5 KB
/
dot_zshrc.tmpl
File metadata and controls
692 lines (593 loc) · 22.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
# =============================================================================
# ~/.zshrc — Zsh Interactive Shell Configuration
# Managed by chezmoi. Edit dot_zshrc.tmpl in the dotfiles repo, not this file.
#
# PERFORMANCE BUDGET (measured on Apple Silicon, 2026-03):
# Target: <100ms — imperceptible to humans
# Current: ~60ms — measured with: /usr/bin/time zsh -i -c exit
# Profile: zsh -i -c 'zmodload zsh/zprof; source ~/.zshrc; zprof'
#
# TOP COST BREAKDOWN (zprof):
# compdef calls ~17ms 36% — completion defs from plugins
# __antidote_setup ~12ms 25% — plugin loading (irreducible floor)
# _cache_eval×4 ~3ms 7% — zoxide/direnv/thefuck (cached, fast)
# p10k ~1ms 1% — instant prompt hides this entirely
#
# KEY OPTIMIZATIONS APPLIED:
# • p10k instant prompt — renders prompt before zshrc finishes loading
# • brew shellenv cached — avoids `brew shellenv` fork on every start
# • _cache_eval — caches slow tool init (zoxide, direnv, thefuck)
# • mise --shims — replaces hook activation (~14ms) with PATH prepend
# • kubectl/helm/ansible — deferred via kind:defer in .zsh_plugins.txt
# • compinit NOT called here — handled once by use-omz (was #1 bottleneck ~250ms)
# • ZSH_DISABLE_COMPFIX — skips compaudit security check (~16ms)
# • SSH keys loaded in bg — avoids ssh-add blocking startup (~11ms)
# • NVM lazy-loaded — only initialized when `nvm` is first called
# =============================================================================
# Enable Powerlevel10k instant prompt. Should stay at the very top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
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
# Ensure PATH entries are unique (auto-deduplication)
typeset -U path
# OPENSPEC:START
# OpenSpec shell completions configuration - fpath only, compinit handled by use-omz
fpath=("$HOME/.zsh/completions" $fpath)
# OPENSPEC:END
# Powerlevel10k shell integration
typeset -g POWERLEVEL9K_TERM_SHELL_INTEGRATION=true
alias python=python3
{{ if eq .chezmoi.os "darwin" -}}
# Homebrew environment (cached to ~/.cache/brew-shellenv.zsh for speed)
# Auto-regenerates when Homebrew is updated -- no manual maintenance needed
_brew_cache="${XDG_CACHE_HOME:-$HOME/.cache}/brew-shellenv.zsh"
{{ if eq .chezmoi.arch "arm64" -}}
_brew_bin="/opt/homebrew/bin/brew"
{{ else -}}
_brew_bin="/usr/local/bin/brew"
{{ end -}}
if [[ -x "$_brew_bin" ]]; then
if [[ ! -f "$_brew_cache" ]] || [[ "$_brew_bin" -nt "$_brew_cache" ]]; then
"$_brew_bin" shellenv > "$_brew_cache" 2>/dev/null
fi
source "$_brew_cache"
fi
unset _brew_cache _brew_bin
{{ else if eq .chezmoi.os "linux" -}}
# Linuxbrew environment (if installed)
if [ -f /home/linuxbrew/.linuxbrew/bin/brew ]; then
_brew_cache="${XDG_CACHE_HOME:-$HOME/.cache}/brew-shellenv.zsh"
_brew_bin="/home/linuxbrew/.linuxbrew/bin/brew"
if [[ ! -f "$_brew_cache" ]] || [[ "$_brew_bin" -nt "$_brew_cache" ]]; then
"$_brew_bin" shellenv > "$_brew_cache" 2>/dev/null
fi
source "$_brew_cache"
unset _brew_cache _brew_bin
fi
{{ end -}}
# Skip OMZ compaudit security check (safe on single-user machine, saves ~16ms)
export ZSH_DISABLE_COMPFIX=true
# Disable OMZ auto-update check (saves ~6ms; we manage plugins via antidote, not OMZ)
export DISABLE_AUTO_UPDATE=true
# Disable OMZ magic functions (url pasting slowdown fix from HN discussion)
export DISABLE_MAGIC_FUNCTIONS=true
# Autosuggestions performance tweaks (set before plugin loads)
export ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=20
export ZSH_AUTOSUGGEST_MANUAL_REBIND=1
# ============================================================================
# ANTIDOTE - Plugin Manager
# ============================================================================
{{ if eq .chezmoi.os "darwin" -}}
if [ -f /opt/homebrew/opt/antidote/share/antidote/antidote.zsh ]; then
source /opt/homebrew/opt/antidote/share/antidote/antidote.zsh
elif [ -f /usr/local/opt/antidote/share/antidote/antidote.zsh ]; then
source /usr/local/opt/antidote/share/antidote/antidote.zsh
fi
{{ else if eq .chezmoi.os "linux" -}}
if [ -f /usr/share/zsh-antidote/antidote.zsh ]; then
source /usr/share/zsh-antidote/antidote.zsh
fi
{{ end -}}
{{ if eq .chezmoi.os "darwin" -}}
_antidote_home="$HOME/Library/Caches/antidote"
{{ else -}}
_antidote_home="${XDG_CACHE_HOME:-$HOME/.cache}/antidote"
{{ end -}}
# Lazy-load: generate static file only when plugins.txt changes
# We also check if the antidote cache directory is missing (e.g. wiped by macOS/CleanMyMac)
zsh_plugins=${ZDOTDIR:-$HOME}/.zsh_plugins
if [[ ! ${zsh_plugins}.zsh -nt ${zsh_plugins}.txt ]] || [[ ! -d "$_antidote_home" ]]; then
antidote bundle <${zsh_plugins}.txt >${zsh_plugins}.zsh
fi
source ${zsh_plugins}.zsh
unset _antidote_home
# NOTE: compinit is handled by getantidote/use-omz (deferred compinit).
# Do NOT call compinit again here -- it was the #1 bottleneck (~250ms).
# PATH setup (consolidated, typeset -U path prevents duplicates)
export PATH=$HOME/bin:$HOME/.local/bin:/usr/local/bin:$PATH
alias tfswitch='tfswitch -b $HOME/.local/bin/terraform'
load-tfswitch() {
local tfswitchrc_path=".terraform-version"
if [ -f "$tfswitchrc_path" ]; then
tfswitch
fi
}
add-zsh-hook chpwd load-tfswitch
load-tfswitch
# You may need to manually set your language environment
export LANG=en_GB.UTF-8
# Preferred editor
export EDITOR='vim'
# True color (24-bit) support for all tools (bat, eza, vim, etc.)
# iTerm2 sets this automatically; this ensures SSH and tmux sessions also get it
export COLORTERM=truecolor
{{ if eq .chezmoi.os "darwin" -}}
# curl (using HOMEBREW_PREFIX for correct architecture path)
if [ -n "${HOMEBREW_PREFIX:-}" ]; then
export PATH="$HOMEBREW_PREFIX/opt/curl/bin:$PATH"
export LDFLAGS="-L$HOMEBREW_PREFIX/opt/curl/lib"
export CPPFLAGS="-I$HOMEBREW_PREFIX/opt/curl/include"
export PATH="$HOMEBREW_PREFIX/opt/mysql-client/bin:$PATH"
fi
{{ end -}}
# Set up fzf key bindings and fuzzy completion (cached for speed)
# Auto-regenerates when fzf is updated -- no manual maintenance needed
_fzf_cache="${XDG_CACHE_HOME:-$HOME/.cache}/fzf.zsh"
_fzf_bin="$(whence -p fzf)"
if [[ -n "$_fzf_bin" ]] && { [[ ! -f "$_fzf_cache" ]] || [[ "$_fzf_bin" -nt "$_fzf_cache" ]]; }; then
fzf --zsh > "$_fzf_cache" 2>/dev/null
fi
[[ -f "$_fzf_cache" ]] && source "$_fzf_cache"
unset _fzf_cache _fzf_bin
# SSH Agent Configuration
# Start ssh-agent if not already running
if [ -z "$SSH_AUTH_SOCK" ]; then
eval "$(ssh-agent -s)" > /dev/null
fi
# Function to load default keys (configured via chezmoi data)
load_default_ssh_keys() {
{{ if ne .ssh_keys "" -}}
local default_keys=({{ range $key := splitList "," .ssh_keys }}{{ $key | trim | quote }} {{ end }})
{{ else -}}
local default_keys=()
{{ end -}}
for key in "${default_keys[@]}"; do
local key_path="$HOME/.ssh/keys/$key"
if [ -f "$key_path" ]; then
# Check if key is already loaded
if ! ssh-add -l 2>/dev/null | grep -q "$(ssh-keygen -lf "$key_path" 2>/dev/null | awk '{print $2}')"; then
ssh-add "$key_path" 2>/dev/null
fi
fi
done
}
# Function to add any key on demand
ssh_add_key() {
local key_name="$1"
local key_path
if [ -z "$key_name" ]; then
echo "Usage: ssh_add_key <key_name>"
echo "Available keys:"
ls ~/.ssh/keys/*.key 2>/dev/null | xargs -n1 basename | sed 's/\.key$//'
return 1
fi
# Try with .key extension first
key_path="$HOME/.ssh/keys/${key_name}.key"
if [ ! -f "$key_path" ]; then
# Try without extension
key_path="$HOME/.ssh/keys/$key_name"
fi
if [ -f "$key_path" ]; then
ssh-add "$key_path"
echo "Added key: $key_path"
else
echo "Key not found: $key_name"
echo "Available keys:"
ls ~/.ssh/keys/*.key 2>/dev/null | xargs -n1 basename | sed 's/\.key$//'
fi
}
# Auto-completion for ssh_add_key function
_ssh_add_key_completion() {
local keys=($(ls ~/.ssh/keys/*.key 2>/dev/null | xargs -n1 basename | sed 's/\.key$//'))
compadd -a keys
}
compdef _ssh_add_key_completion ssh_add_key
# Load SSH keys in background to avoid blocking shell startup (~11ms saved)
load_default_ssh_keys &!
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
# JetBrains VM options
___MY_VMOPTIONS_SHELL_FILE="${HOME}/.jetbrains.vmoptions.sh"
if [ -f "${___MY_VMOPTIONS_SHELL_FILE}" ]; then
. "${___MY_VMOPTIONS_SHELL_FILE}"
fi
# VS Code Shell Integration
if [[ "$TERM_PROGRAM" == "vscode" ]]; then
_vscode_si=""
{{ if eq .chezmoi.os "darwin" -}}
_vscode_si="/Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh"
{{ else if eq .chezmoi.os "linux" -}}
for _p in \
"/usr/share/code/resources/app/out/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh" \
"/opt/visual-studio-code/resources/app/out/vs/workbench/contrib/terminal/common/scripts/shellIntegration-rc.zsh"; do
[ -f "$_p" ] && _vscode_si="$_p" && break
done
unset _p
{{ end -}}
if [[ -f "$_vscode_si" ]]; then
. "$_vscode_si"
elif command -v code &>/dev/null; then
. "$(code --locate-shell-integration-path zsh 2>/dev/null)"
fi
unset _vscode_si
fi
{{ if ne .gcloud_project "" -}}
export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT="{{ .gcloud_project }}"
{{ end -}}
{{ if ne .gcloud_location "" -}}
export GOOGLE_CLOUD_LOCATION="{{ .gcloud_location }}"
{{ end -}}
# ============================================================================
# PRODUCTIVITY ALIASES AND FUNCTIONS
# ============================================================================
# File and Directory Navigation
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias ~='cd ~'
alias -- -='cd -'
# Enhanced ls commands (using eza, a modern ls replacement)
alias ls='eza --color=auto --icons'
alias ll='eza -alF --icons --git' # Long listing with git status
alias la='eza -a --icons'
alias l='eza -F --icons'
alias lt='eza -l --sort=modified' # Sort by time, newest last
alias lh='eza -l --icons' # Human readable sizes (eza default)
alias lsize='eza -l --sort=size' # Sort by size
alias ltree='eza --tree --level=2 --icons' # Tree view with eza
# Directory operations
alias md='mkdir -p'
alias rd='rmdir'
# Tree view
alias tree='tree -C'
alias t1='tree -L 1'
alias t2='tree -L 2'
alias t3='tree -L 3'
# Quick access to common directories
alias desktop='cd ~/Desktop'
alias downloads='cd ~/Downloads'
alias documents='cd ~/Documents'
alias projects='cd ~/projects'
# Git Enhancements (beyond what oh-my-zsh provides)
alias gst='git status'
alias gco='git checkout'
alias gcb='git checkout -b'
alias gp='git push'
alias gpl='git pull'
alias gf='git fetch'
alias gm='git merge'
alias gr='git rebase'
alias glog='git log --oneline --graph --decorate'
alias gclean='git clean -fd'
alias greset='git reset --hard HEAD'
alias gb='git branch'
alias gbd='git branch -d'
alias gbD='git branch -D'
alias gba='git branch -a'
alias gwip='git add -A && git commit -m "WIP"'
alias gunwip='git log -n 1 | grep -q -c "WIP" && git reset HEAD~1'
alias gundo='git reset --soft HEAD~1'
# Development Tools
# Python shortcuts
alias py='python3'
alias pip='pip3'
alias venv='python3 -m venv'
alias pipr='pip install -r requirements.txt'
alias pipf='pip freeze > requirements.txt'
# Docker shortcuts (using docker compose v2)
alias d='docker'
alias dc='docker compose'
alias dcu='docker compose up'
alias dcd='docker compose down'
alias dcb='docker compose build'
alias dcr='docker compose restart'
alias dps='docker ps'
alias dpsa='docker ps -a'
alias di='docker images'
alias drm='docker rm'
alias drmi='docker rmi'
alias dprune='docker system prune -f'
# System Utilities
alias psg='procs --tree' # procs: modern ps with tree view
alias myip='curl -s https://ipinfo.io/ip'
{{ if eq .chezmoi.os "darwin" -}}
alias localip='ipconfig getifaddr en0'
{{ else -}}
alias localip='hostname -I | awk "{print \$1}"'
{{ end -}}
alias ports='netstat -tuln'
alias listening='lsof -i -P | grep LISTEN'
# File operations with safety
alias cp='cp -i' # Confirm before overwriting
alias mv='mv -i' # Confirm before overwriting
alias rm='rm -i' # Confirm before deleting
alias grep='grep --color=auto'
alias fgrep='grep -F --color=auto'
alias egrep='grep -E --color=auto'
# Disk usage (using modern replacements)
alias du='dust' # dust: intuitive disk usage with bar chart
alias df='duf' # duf: colorful disk free with table layout
alias ducks='dust -r -n 10' # Show largest directories
alias diskspace='duf'
{{ if eq .chezmoi.os "darwin" -}}
# macOS Specific
alias showfiles='defaults write com.apple.finder AppleShowAllFiles YES; killall Finder'
alias hidefiles='defaults write com.apple.finder AppleShowAllFiles NO; killall Finder'
alias cleanup='rm -rf ~/.Trash/* 2>/dev/null; echo "Trash cleaned."'
alias flushdns='sudo dscacheutil -flushcache'
alias emptytrash='rm -rfv ~/.Trash/* 2>/dev/null; echo "Trash emptied."'
{{ else if eq .chezmoi.os "linux" -}}
# Linux Specific
alias flushdns='sudo systemd-resolve --flush-caches 2>/dev/null || sudo resolvectl flush-caches 2>/dev/null'
if command -v yay &>/dev/null; then
alias update='yay -Syu && antidote update'
elif command -v pacman &>/dev/null; then
alias update='sudo pacman -Syu && antidote update'
fi
alias syslog='journalctl -xe'
{{ end -}}
# Quick edit common files
alias zshrc='code ~/.zshrc'
alias hosts='sudo code /etc/hosts'
alias sshconfig='code ~/.ssh'
# History aliases
alias h='history'
alias hg='history | grep'
alias hs='history | grep'
# Process management
kport() {
if [ -z "$1" ]; then
echo "Usage: kport <port_number>"
echo "Example: kport 3000"
return 1
fi
local pids=$(lsof -ti:$1)
if [ -z "$pids" ]; then
echo "No process found running on port $1"
return 1
fi
echo "Killing processes on port $1: $pids"
echo $pids | xargs kill -15 2>/dev/null
sleep 1
local remaining=$(lsof -ti:$1 2>/dev/null)
if [ -n "$remaining" ]; then
echo "$remaining" | xargs kill -9 2>/dev/null
fi
echo "Done!"
}
# Alternative alias for killport
alias killport='kport'
# ============================================================================
# USEFUL FUNCTIONS
# ============================================================================
# Create and enter directory
mkcd() {
mkdir -p "$1" && cd "$1"
}
# Extract various archive formats
extract() {
if [ -f "$1" ] ; then
case "$1" in
*.tar.bz2) tar xjf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar e "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.7z) 7z x "$1" ;;
*) echo "'$1' cannot be extracted via extract()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
# Find files by name (using fd, a modern find replacement)
findfile() {
fd --type f "$1"
}
# Find directories by name
finddir() {
fd --type d "$1"
}
# Weather function
weather() {
local location=${1:-"Rome"}
curl -s "wttr.in/$location"
}
# Quick backup function
backup() {
cp "$1" "$1.backup.$(date +%Y%m%d_%H%M%S)"
}
# Git clone and cd into directory
gclone() {
git clone "$1" && cd "$(basename "$1" .git)"
}
# Quick note taking
note() {
echo "$(date): $*" >> ~/notes.txt
}
# Show notes
notes() {
cat ~/notes.txt
}
# Quick search in files (uses ripgrep for speed)
search() {
rg "$1" .
}
# Show file size in human readable format
sizeof() {
du -sh "$1"
}
# ============================================================================
# ENHANCED HISTORY SETTINGS
# ============================================================================
export HISTSIZE=50000
export SAVEHIST=50000
export HISTFILE=~/.zsh_history
setopt HIST_VERIFY
setopt SHARE_HISTORY
setopt APPEND_HISTORY
setopt INC_APPEND_HISTORY
setopt HIST_IGNORE_DUPS
setopt HIST_IGNORE_ALL_DUPS
setopt HIST_REDUCE_BLANKS
setopt HIST_IGNORE_SPACE
# ============================================================================
# ADDITIONAL PRODUCTIVITY SETTINGS
# ============================================================================
# Auto-correction (commands only, not arguments)
setopt CORRECT
# Better completion
setopt AUTO_LIST
setopt AUTO_MENU
setopt ALWAYS_TO_END
# Case insensitive completion
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'
# Colored completion
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
# ============================================================================
# MODERN TOOL INTEGRATIONS
# ============================================================================
# bat: syntax-highlighted cat replacement
alias cat='bat --paging=never'
alias catp='bat' # with pager (like less but with syntax highlighting)
alias batdiff='git diff --name-only --diff-filter=d | xargs bat --diff'
# Helper: cache a tool's init output, auto-regenerate when binary updates
_cache_eval() {
local name="$1" cmd="$2"
local cache="${XDG_CACHE_HOME:-$HOME/.cache}/${name}.zsh"
local bin="$(whence -p "$name")"
if [[ -n "$bin" ]] && { [[ ! -f "$cache" ]] || [[ "$bin" -nt "$cache" ]]; }; then
eval "$cmd" > "$cache" 2>/dev/null
fi
[[ -f "$cache" ]] && source "$cache"
}
# mise: dev toolchain manager — loaded via shims, not hook activation
#
# WHY NOT `mise activate zsh` (hook mode):
# Hook activation installs _mise_hook as a chpwd+precmd hook, running on
# every prompt draw and directory change. zprof measured this at ~14ms
# (29% of total startup). Eliminating it saved ~20ms wall-clock.
#
# WHY SHIMS:
# Prepending ~/.local/share/mise/shims to PATH is zero-cost at startup.
# Each shim is a small executable that invokes the right tool version on
# first call — overhead is per-invocation, not per shell start.
#
# TRADEOFF:
# No automatic version switching when cd-ing into a project directory.
# Workarounds:
# mise shell <version> — override for current session only
# mise use --global <ver> — set global default
# mise exec -- <cmd> — run command with project versions loaded
#
# TO RE-ENABLE HOOK MODE (if per-directory switching becomes essential):
# Replace the PATH line below with: _cache_eval mise "mise activate zsh"
# Then: rm ~/.cache/mise.zsh && exec zsh
if command -v mise &>/dev/null; then
export PATH="$HOME/.local/share/mise/shims:$PATH"
fi
# zoxide: smarter cd that learns from your habits (replaces OMZ z plugin)
_cache_eval zoxide 'zoxide init zsh'
alias cd='z' # seamless replacement, learns directories
alias cdi='zi' # interactive directory picker with fzf
# direnv: auto-load .envrc per directory (useful for terraform/ansible projects)
_cache_eval direnv 'direnv hook zsh'
# thefuck: correct previous command typos (type 'fuck' after a mistake)
_cache_eval thefuck 'thefuck --alias'
# lazygit: TUI for git
alias lg='lazygit'
# lazydocker: TUI for docker
alias lzd='lazydocker'
# Terraform shortcuts
alias tf='terraform'
alias tfi='terraform init'
alias tfp='terraform plan'
alias tfa='terraform apply'
alias tfs='terraform show'
alias tfo='terraform output'
alias tfv='terraform validate'
alias tfw='terraform workspace'
# Ansible shortcuts
alias ap='ansible-playbook'
alias apv='ansible-playbook --ask-vault-pass'
alias apc='ansible-playbook --check --diff' # dry run with diff
alias av='ansible-vault'
alias ave='ansible-vault encrypt'
alias avd='ansible-vault decrypt'
alias avv='ansible-vault view'
alias al='ansible-lint'
alias ai='ansible-inventory --graph'
# gping: graphical ping
alias ping='gping'
# tldr: simplified man pages (quicker than man for common usage)
alias help='tldr'
# ncdu: interactive disk usage explorer
alias diskexplore='ncdu'
# bottom: system monitor TUI (like htop but better)
alias btm='btm'
alias sysmon='btm'
{{ if eq .chezmoi.os "darwin" -}}
# Upgrade everything: brew formulae + casks + antidote plugins in one command
brewup() {
brew update
brew upgrade
brew upgrade --cask --greedy
brew cleanup
# brew cleanup deletes old antidote versions, breaking its autoload functions.
# Re-source it so 'antidote update' works in the same shell session.
local antidote_path="${HOMEBREW_PREFIX:-/opt/homebrew}/opt/antidote/share/antidote/antidote.zsh"
if [[ -f "$antidote_path" ]]; then
source "$antidote_path"
fi
antidote update
npm install -g @fission-ai/openspec@latest
}
# Zscaler VPN controls (macOS only)
# zscaler-start: opens the Zscaler.app hidden then loads all system LaunchDaemons
# (sudo required — daemons run as root)
# zscaler-kill: unloads user LaunchAgents AND system LaunchDaemons, fully
# stopping all Zscaler processes without rebooting
alias zscaler-start="open -a /Applications/Zscaler/Zscaler.app --hide; sudo find /Library/LaunchDaemons -name '*zscaler*' -exec launchctl load {} \;"
alias zscaler-kill="find /Library/LaunchAgents -name '*zscaler*' -exec launchctl unload {} \;; sudo find /Library/LaunchDaemons -name '*zscaler*' -exec launchctl unload {} \;"
{{ end -}}
# ============================================================================
# Google Cloud SDK
{{ if eq .chezmoi.os "darwin" -}}
export CLOUDSDK_PYTHON="${HOMEBREW_PREFIX:-/opt/homebrew}/bin/python3"
if [ -n "${HOMEBREW_PREFIX:-}" ] && [ -f "${HOMEBREW_PREFIX}/share/google-cloud-sdk/path.zsh.inc" ]; then
. "${HOMEBREW_PREFIX}/share/google-cloud-sdk/path.zsh.inc"
fi
if [ -n "${HOMEBREW_PREFIX:-}" ] && [ -f "${HOMEBREW_PREFIX}/share/google-cloud-sdk/completion.zsh.inc" ]; then
. "${HOMEBREW_PREFIX}/share/google-cloud-sdk/completion.zsh.inc"
fi
{{ else if eq .chezmoi.os "linux" -}}
export CLOUDSDK_PYTHON="/usr/bin/python3"
if [ -f '/opt/google-cloud-sdk/path.zsh.inc' ]; then
. '/opt/google-cloud-sdk/path.zsh.inc'
fi
if [ -f '/opt/google-cloud-sdk/completion.zsh.inc' ]; then
. '/opt/google-cloud-sdk/completion.zsh.inc'
fi
{{ end -}}
export CLOUDSDK_PYTHON_SITEPACKAGES=1
{{ if eq .chezmoi.os "darwin" -}}
test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh"
{{ end -}}