1. # .zshrc
  2. # Ensure Homebrew (and kubectl, etc.) are in PATH for non-login shells (e.g. tmux panes)
  3. if [[ -x /opt/homebrew/bin/brew ]]; then
  4. eval "$(/opt/homebrew/bin/brew shellenv)"
  5. elif [[ -x /usr/local/bin/brew ]]; then
  6. eval "$(/usr/local/bin/brew shellenv)"
  7. fi
  8.  
  9. # Cursor may invoke this helper when probing shell state.
  10. # Keep a no-op fallback so startup never errors if integration is missing.
  11. if ! typeset -f dump_zsh_state >/dev/null 2>&1; then
  12. dump_zsh_state() { :; }
  13. fi
  14.  
  15. # Cursor Agent: proper command detection (run once: curl -L https://iterm2.com/shell_integration/zsh -o ~/.iterm2_shell_integration.zsh)
  16. if [[ -n $CURSOR_TRACE_ID ]]; then
  17. PROMPT_EOL_MARK=""
  18. test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh"
  19. precmd() { print -Pn "\e]133;D;%?\a" }
  20. preexec() { print -Pn "\e]133;C;\a" }
  21. fi
  22.  
  23. # Simpler theme in Cursor (ZSH_THEME only applies if you use oh-my-zsh; this repo uses Starship below)
  24. if [[ -n $CURSOR_TRACE_ID ]]; then
  25. ZSH_THEME="robbyrussell"
  26. else
  27. ZSH_THEME="powerlevel10k/powerlevel10k"
  28. fi
  29.  
  30. # p10k: only load when not in Cursor
  31. if [[ ! -n $CURSOR_TRACE_ID ]]; then
  32. [[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
  33. fi
  34.  
  35. # History: big, shared across sessions, no dupes, with timestamps
  36. HISTSIZE=50000
  37. SAVEHIST=50000
  38. HISTFILE=~/.zsh_history
  39. setopt EXTENDED_HISTORY # save timestamp and duration
  40. setopt INC_APPEND_HISTORY # write to history file immediately
  41. setopt SHARE_HISTORY # share history across sessions
  42. setopt HIST_IGNORE_ALL_DUPS # drop older duplicate entries
  43. setopt HIST_IGNORE_SPACE # ignore commands starting with space
  44. setopt HIST_REDUCE_BLANKS # trim extra blanks
  45. setopt NO_BEEP # turn off terminal beep
  46.  
  47. if [[ -o interactive ]] && [[ "$TERM" != "dumb" ]] && command -v starship &>/dev/null; then
  48. eval "$(starship init zsh)"
  49. fi
  50.  
  51. # Auto-start tmux in normal terminals only (never inside Cursor/VS Code — avoids "Unable to resolve your shell environment")
  52. if [[ -t 1 ]] && command -v tmux &>/dev/null && [ -z "$TMUX" ] && [[ "$TERM_PROGRAM" != "vscode" && "$TERM_PROGRAM" != "Cursor" && -z $CURSOR_TRACE_ID ]]; then
  53. if tmux has-session 2>/dev/null; then
  54. exec tmux attach-session
  55. else
  56. exec tmux new-session
  57. fi
  58. fi
  59.  
  60. # General aliases
  61. alias ls="lsd"
  62. alias vim="nvim"
  63. alias f="fuck"
  64. alias cat="bat"
  65.  
  66. # Git (optional short aliases)
  67. alias g="git"
  68. alias gst="git status"
  69. alias gco="git checkout"
  70. alias gd="git diff"
  71. alias gl="git pull"
  72. alias gp="git push"
  73. alias gb="git branch"
  74. alias glog="git log --oneline -20"
  75.  
  76. # Kubectl aliases (k = kubectl; kg* = get, kd = describe, kdel = delete, kaf = apply -f)
  77. alias k="kubectl"
  78. alias kgp="kubectl get pods"
  79. alias kgs="kubectl get svc"
  80. alias kgd="kubectl get deploy"
  81. alias kgn="kubectl get nodes"
  82. alias kga="kubectl get all"
  83. alias kgpw="kubectl get pods -w"
  84. alias kd="kubectl describe"
  85. alias kdp="kubectl describe pod"
  86. alias kdel="kubectl delete"
  87. alias kaf="kubectl apply -f"
  88. alias kdf="kubectl delete -f"
  89. alias kctx="kubectl config use-context"
  90. alias kns="kubectl config set-context --current --namespace"
  91. alias klog="kubectl logs"
  92. alias kexec="kubectl exec -it"
  93. alias k9="k9s"
  94.  
  95. # Tmux aliases
  96. alias t="tmux"
  97. alias ta="tmux attach"
  98. alias tat="tmux attach -t"
  99. alias tnew="tmux new-session"
  100. alias tls="tmux list-sessions"
  101. alias tkill="tmux kill-session"
  102. alias tkillall="tmux kill-server"
  103.  
  104. # Tmux helper functions
  105. tdev() {
  106. # Create or attach to a development session
  107. if tmux has-session -t dev 2>/dev/null; then
  108. tmux attach -t dev
  109. else
  110. tmux new-session -s dev
  111. fi
  112. }
  113.  
  114. twork() {
  115. # Create or attach to a work session
  116. if tmux has-session -t work 2>/dev/null; then
  117. tmux attach -t work
  118. else
  119. tmux new-session -s work
  120. fi
  121. }
  122.  
  123. # Kubectl + fzf: switch context or namespace by picking from list
  124. kctxf() {
  125. local ctx
  126. ctx=$(kubectl config get-contexts -o name | fzf -q "$*")
  127. [[ -n "$ctx" ]] && kubectl config use-context "$ctx"
  128. }
  129. knsf() {
  130. local ns
  131. ns=$(kubectl get namespaces -o name | sed 's|namespace/||' | fzf -q "$*")
  132. [[ -n "$ns" ]] && kubectl config set-context --current --namespace "$ns"
  133. }
  134.  
  135. if command -v thefuck &>/dev/null; then
  136. eval "$(thefuck --alias)"
  137. fi
  138. if command -v mcfly &>/dev/null; then
  139. eval "$(mcfly init zsh)"
  140. fi
  141. command -v zoxide &>/dev/null && eval "$(zoxide init zsh)"
  142.  
  143. # Completions (compinit -C = fast load; run "rm ~/.zcompdump && compinit" to rebuild)
  144. autoload -Uz compinit
  145. [[ -f ~/.zcompdump ]] && [[ ~/.zshrc -nt ~/.zcompdump ]] && rm -f ~/.zcompdump
  146. compinit -C
  147. if command -v kubectl &>/dev/null; then
  148. source <(kubectl completion zsh)
  149. compdef _kubectl k
  150. fi
  151. command -v helm &>/dev/null && source <(helm completion zsh)
  152.  
  153. # FZF keybindings and completion (from Homebrew; no need to run fzf/install)
  154. _fzf_prefix=$(brew --prefix 2>/dev/null)
  155. if [ -n "$_fzf_prefix" ] && [ -f "${_fzf_prefix}/opt/fzf/shell/key-bindings.zsh" ]; then
  156. source "${_fzf_prefix}/opt/fzf/shell/key-bindings.zsh"
  157. fi
  158. if [ -n "$_fzf_prefix" ] && [ -f "${_fzf_prefix}/opt/fzf/shell/completion.zsh" ]; then
  159. source "${_fzf_prefix}/opt/fzf/shell/completion.zsh"
  160. fi
  161. unset _fzf_prefix
  162.  
  163. # Better history: `hist` = fzf search & run, `hist -n` = numbered list (for !123)
  164. hist() {
  165. if [[ "$1" == -n ]]; then
  166. fc -l 1
  167. else
  168. local chosen
  169. chosen=$(fc -l 1 | fzf --tac --no-sort -q "${*:-}" | sed 's/ *[0-9]* *//')
  170. [[ -n "$chosen" ]] && print -z "$chosen"
  171. fi
  172. }
  173.  
  174. # direnv and env managers
  175. if command -v direnv &>/dev/null; then
  176. eval "$(direnv hook zsh)"
  177. fi
  178. if command -v uv &>/dev/null; then
  179. eval "$(uv generate-shell-completion zsh)"
  180. fi
  181. if command -v mise &>/dev/null; then
  182. eval "$(mise activate zsh)"
  183. fi
  184.  
  185. # Homebrew zsh plugins
  186. # zsh-autosuggestions should be sourced after completion is set up
  187. if [ -f "$(brew --prefix 2>/dev/null)"/share/zsh-autosuggestions/zsh-autosuggestions.zsh ]; then
  188. source "$(brew --prefix 2>/dev/null)"/share/zsh-autosuggestions/zsh-autosuggestions.zsh
  189. fi
  190.  
  191. # zsh-syntax-highlighting must be last
  192. if [ -f "$(brew --prefix 2>/dev/null)"/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then
  193. source "$(brew --prefix 2>/dev/null)"/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
  194. fi
  195.  
  196. # Ensure sourced .zshrc exits 0 (fixes Cursor "Unable to resolve your shell environment" when brew etc. not in PATH)
  197. true
  198. if command -v go &>/dev/null; then
  199. export PATH="$PATH:$(go env GOPATH)/bin"
  200. fi