Oh-My-Zsh — anatomia e plugins essenciais

TL;DR

Oh-My-Zsh é um framework de config pra Zsh: você clona em ~/.oh-my-zsh/, source no .zshrc, e ganha um loader que ativa plugins via array plugins=(...). Plugins essenciais (git, zsh-autosuggestions, zsh-syntax-highlighting, direnv) cobrem 90% das necessidades. Ordem importa: zsh-syntax-highlighting DEVE ser o último no array.

O que é / Como funciona

OMZ não é Zsh

Oh-My-Zsh é um overlay de configuração para o Zsh — não um shell diferente. Sem OMZ, Zsh funciona normalmente com suas configurações em ~/.zshrc. Com OMZ instalado, esse mesmo .zshrc passa a conter um source "$ZSH/oh-my-zsh.sh" que ativa o framework: plugin loader, temas, funções helper e aliases automáticos.

A distinção importa porque confundir OMZ com Zsh leva a erros de diagnóstico. Se o Zsh travar, verifique primeiro se é o shell ou um plugin OMZ.

O que OMZ agrega sobre o Zsh puro:

  • Plugin loader (ativa plugins via array plugins=(...))
  • 300+ plugins embarcados
  • 150+ temas embarcados
  • Funções helper reutilizáveis (ex: current_branch, take)
  • Update automático periódico

Layout de ~/.oh-my-zsh/

~/.oh-my-zsh/
├── oh-my-zsh.sh          # entrypoint: source este arquivo no .zshrc
├── lib/                  # funções helper carregadas automaticamente
│   ├── completion.zsh    # configura compinit
│   ├── history.zsh       # defaults de history
│   ├── git.zsh           # funções de Git usadas pelo tema
│   └── ...
├── plugins/              # plugins embarcados (não edite)
│   ├── git/
│   │   └── git.plugin.zsh
│   ├── direnv/
│   │   └── direnv.plugin.zsh
│   └── ...
├── themes/               # temas embarcados (não edite)
│   ├── robbyrussell.zsh-theme
│   └── ...
├── custom/               # SEU terreno — sobrevive a updates
│   ├── plugins/          # plugins externos (zsh-autosuggestions, etc.)
│   ├── themes/           # temas externos (Powerlevel10k, etc.)
│   └── example.zsh       # aliases e overrides pessoais
└── cache/                # completion cache e controle de update

A pasta custom/ nunca é sobrescrita pelo omz update. Tudo que você cria ou clona aqui persiste entre atualizações do framework.

Sequência de inicialização de oh-my-zsh.sh

Quando o .zshrc executa source "$ZSH/oh-my-zsh.sh", a ordem interna simplificada é:

  1. Verifica update — consulta cache/ pra ver se está na frequência configurada
  2. Source lib/* — carrega helpers, defaults de history, completion, etc.
  3. compinit — inicializa o sistema de completion do Zsh
  4. Loop sobre plugins=(...) — para cada nome:
    • Procura $ZSH_CUSTOM/plugins/<nome>/<nome>.plugin.zsh (custom) primeiro
    • Fallback: $ZSH/plugins/<nome>/<nome>.plugin.zsh (embarcado). É por isso que custom vence override.
    • Source o arquivo encontrado
  5. Source do tema — carrega o .zsh-theme configurado em ZSH_THEME
  6. Customizações do usuário — o que vier depois do source no .zshrc

Esse fluxo explica por que zsh-syntax-highlighting deve ser o último plugin — ele precisa encontrar todos os widgets ZLE já registrados pelos plugins anteriores.

Array de plugins

# ~/.zshrc
plugins=(
  git
  direnv
  zsh-autosuggestions
  zsh-syntax-highlighting   # SEMPRE último entre os syntax-related
)

Regras do array:

  • Elementos separados por espaços (ou newlines) — nunca vírgulas
  • OMZ resolve o caminho em dois lugares: $ZSH/plugins/<nome>/ (embarcado) e $ZSH_CUSTOM/plugins/<nome>/ (custom)
  • Plugins externos precisam ser clonados manualmente antes de funcionar

Plugins essenciais

git (embarcado)

O plugin mais usado do OMZ. Fornece dezenas de aliases curtos para Git e algumas funções utilitárias usadas pelos temas:

AliasComando completo
gstgit status
gcogit checkout
gpgit push
glgit pull
gloggit log --oneline --decorate --graph
gagit add
gcmsggit commit -m

A função current_branch retorna a branch atual e é usada pelos temas pra montar o prompt.

zsh-autosuggestions (externo — zsh-users/zsh-autosuggestions)

Sugere comandos enquanto você digita, exibindo uma sugestão em cinza inline logo após o cursor. A sugestão é baseada no history do Zsh (e opcionalmente em completions).

Aceitar sugestão:

  • (right-arrow) ou End — aceita a sugestão inteira
  • Ctrl-F — aceita a sugestão inteira (alternativa)
  • Ctrl-→ (forward-word) — aceita parcialmente até a próxima palavra

Configuração útil:

# Personaliza estilo visual (fg=8 é cinza, default)
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=8,underline"
 
# Estratégia de sugestão: history (default), completion, ou ambas
ZSH_AUTOSUGGEST_STRATEGY=(history completion)
 
# Desativa sugestões pra comandos muito longos (performance)
ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=20

zsh-syntax-highlighting (externo — zsh-users/zsh-syntax-highlighting)

Colore comandos enquanto você digita, antes de pressionar Enter:

  • Verde — comando válido (existe no $PATH ou é builtin)
  • Vermelho — comando inválido (não encontrado)
  • Underline — path existente no filesystem

O efeito imediato é capturar typos antes de executar. Se o comando ficou vermelho, tem erro de digitação. Cores específicas de aliases, globbing e expressões variam por tema/config; o highlighter default não distingue aliases de comandos normais com cor separada.

Por que deve ser o último plugin: o plugin funciona envolvendo (wrapping) widgets ZLE. Se sourced antes de outros plugins que registram widgets com zle -N, ele não captura esses widgets e perde o highlight em comandos adicionados por eles. Em Zsh 5.8+, usa add-zle-hook-widget, então os hooks rodam na ordem de registro — zsh-syntax-highlighting deve registrar por último.

direnv (embarcado)

Integra o utilitário direnv ao Zsh. Cria o hook que direnv precisa para carregar/descarregar variáveis de ambiente automaticamente ao entrar e sair de diretórios com .envrc.

Exemplo: entrar em ~/projetos/api/ que tem .envrc com export DATABASE_URL=... — o direnv carrega a variável automaticamente. Sair do diretório a descarrega.

Requer direnv instalado (brew install direnv ou via package manager). O plugin só cria o hook — o utilitário em si é externo.

Plugins debatíveis (com tradeoff)

fast-syntax-highlighting

Alternativa mais rápida ao zsh-syntax-highlighting, com mais tipos de highlight (paths, globbing, expressões). O nome é enganoso — não é compatível com zsh-syntax-highlighting.

Conflito

NUNCA use fast-syntax-highlighting e zsh-syntax-highlighting juntos. Os dois envolvem os mesmos widgets ZLE e o resultado é cores quebradas ou degradação de performance. Escolha um.

fzf-tab

Substitui o menu de completion padrão do Zsh por uma interface fuzzy (fzf). Muito popular em setups avançados — permite navegar completions com preview interativo.

Posição no array: deve vir antes de zsh-syntax-highlighting, mas depois de outros plugins de completion. A ordem recomendada: zsh-autosuggestionsfzf-tabzsh-syntax-highlighting.

Requer fzf instalado.

zsh-autocomplete

Plugin de marlonrichert que sobrepõe completamente o sistema de completion do Zsh: exibe opções em tempo real enquanto você digita, sem pressionar Tab. É uma mudança significativa de comportamento.

Caveats importantes:

  • Altera o fluxo de Tab — o comportamento default do OMZ muda radicalmente
  • Conflita com fzf-tab (os dois competem pelo controle de completions)
  • Requer Zsh 5.8+
  • A ordem de source importa: deve ser sourced antes de plugins que sobrescrevem bindings, o que conflita com a regra do zsh-syntax-highlighting
  • Usuários que migram de zsh-autocomplete para fzf-tab frequentemente precisam limpar a config de completion

Use com cautela em setups OMZ. Avalie antes de adotar em ambiente de produção.

Modo de update

# ~/.zshrc — antes do source do OMZ
zstyle ':omz:update' mode reminder    # avisa quando tem update (default)
zstyle ':omz:update' mode auto        # atualiza silenciosamente
zstyle ':omz:update' mode disabled    # nunca atualiza automaticamente
zstyle ':omz:update' frequency 7      # frequência em dias (default: 13)

Na prática

Instalar OMZ

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

O script faz backup do .zshrc existente (renomeia para .zshrc.pre-oh-my-zsh), clona o repo em ~/.oh-my-zsh/ e cria um novo .zshrc com configuração básica.

Instalar plugin externo (zsh-autosuggestions)

git clone https://github.com/zsh-users/zsh-autosuggestions \
  ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

Depois adicionar zsh-autosuggestions ao array plugins=(...) no .zshrc e recarregar:

source ~/.zshrc

Instalar zsh-syntax-highlighting

git clone https://github.com/zsh-users/zsh-syntax-highlighting \
  ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

Ordem recomendada no array

plugins=(
  git
  direnv
  zsh-autosuggestions
  fzf-tab                       # se usar — antes do syntax-highlight
  zsh-syntax-highlighting       # ÚLTIMO
)

Inspecionar o setup atual

omz plugin list                 # lista todos os plugins disponíveis
omz plugin info git             # mostra README do plugin git
omz update                      # roda update manual imediato

Recarregar sem fechar terminal

source ~/.zshrc

Em inglês: source the file (executar/recarregar o arquivo de config no shell atual). Diferente de abrir um novo terminal, que também sourceia o .zshrc, mas perde o estado da sessão atual.

Armadilhas

(1) Double-load: fast-syntax-highlighting + zsh-syntax-highlighting

Causa: os dois plugins envolvem os mesmos widgets ZLE. Foram projetados como alternativas, não como complementos.

Sintoma: cores quebradas, highlight incorreto ou lentidão perceptível ao digitar.

Como detectar: verificar o array plugins=(...) no .zshrc — se ambos aparecerem simultaneamente, o conflito está confirmado.

Solução: escolha apenas um. Remova o outro do array e do custom/plugins/ se estiver clonado.

# ERRADO — conflito garantido
plugins=(
  zsh-autosuggestions
  fast-syntax-highlighting
  zsh-syntax-highlighting
)
 
# CORRETO — escolha um
plugins=(
  zsh-autosuggestions
  zsh-syntax-highlighting
)

(2) zsh-syntax-highlighting não é o último plugin

Causa: o plugin funciona envolvendo widgets ZLE no momento em que é sourced. Plugins carregados depois podem registrar novos widgets que o syntax-highlighter não captura.

Sintoma: highlight deixa de funcionar para comandos ou funcionalidades introduzidas por plugins listados após zsh-syntax-highlighting no array.

Como detectar: testar um alias ou builtin adicionado por um plugin posterior — se ficar sem cor ou vermelho (inválido), a ordem está errada.

Solução: mover zsh-syntax-highlighting para o último lugar no array.

# ERRADO
plugins=(
  zsh-syntax-highlighting   # sourced antes dos outros
  zsh-autosuggestions
  git
)
 
# CORRETO
plugins=(
  git
  zsh-autosuggestions
  zsh-syntax-highlighting   # SEMPRE último
)

(3) zsh-autocomplete conflita com o fluxo de completion padrão

Causa: zsh-autocomplete substitui o comportamento default de Tab e várias widgets de completion do compsys, conflitando com o setup default do OMZ e com fzf-tab se ambos estiverem ativos.

Sintoma: Tab deixa de funcionar como esperado; menu de completion some, duplica ou exibe entradas misturadas. Ao usar fzf-tab e zsh-autocomplete juntos, os dois competem pelo controle do mesmo mecanismo.

Como detectar: zle -l | grep complete — ver múltiplos widgets conflitantes registrados. omz plugin list confirma quais plugins estão ativos.

Solução: escolha apenas um entre zsh-autocomplete e fzf-tab. Ao migrar para fzf-tab depois de ter usado zsh-autocomplete, remova o cache ~/.zcompdump e recarregue o shell para forçar regeneração pelo compinit.

(4) Bracketed-paste quebra com URLs e aspas

Causa: o bracketed-paste-magic (ativo por default no OMZ) processa o texto colado para escapar caracteres especiais, mas interpreta erroneamente aspas e caracteres de URL como sequências de escape.

Sintoma: colar https://example.com?foo=bar&baz=1 vira lixo no prompt — caracteres parecem escapados ou a linha fica corrompida.

Como detectar: colar uma URL com & ou ? no prompt e observar se o resultado diverge do texto copiado.

Solução: adicionar antes do source do OMZ no .zshrc:

DISABLE_MAGIC_FUNCTIONS="true"

(5) NVM/SDKMan tornam o shell lento

Causa: nvm e ferramentas similares carregam scripts pesados no startup, executando scripts de centenas de linhas toda vez que um terminal abre.

Sintoma: tempo de abertura de um novo terminal passa de ~100ms para vários segundos. Parece culpa do OMZ, mas o gargalo é o script de inicialização do NVM/SDKMan.

Como detectar: time zsh -i -c exit antes e depois de comentar a linha de source do NVM no .zshrc. Se o tempo cair drasticamente, o culpado é o NVM.

Solução: lazy-load — só carrega o NVM quando node é chamado pela primeira vez:

# Lazy-load NVM — não carrega no startup
node() {
  unfunction node
  export NVM_DIR="$HOME/.nvm"
  [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
  node "$@"
}

Em inglês

  • framework de shellshell framework. “Oh-My-Zsh is a shell framework built on top of Zsh.”
  • recarregar (o arquivo)source (the file). “Source your .zshrc to apply changes without restarting the terminal.”
  • atalhoshortcut. “The plugin adds a shortcut for git status.”
  • atualizarupdate. “Run omz update to update Oh-My-Zsh and its plugins.”
  • conflito de pluginsplugin conflict. “Using both syntax highlighters causes a plugin conflict.”
  • tematheme. “Powerlevel10k is the most customizable theme in the OMZ ecosystem.”
  • personalizaçãocustomization. “Put your customizations in the custom/ folder so they survive updates.”
  • carregador de pluginsplugin loader / plugin manager. “OMZ ships its own plugin loader — no external plugin manager needed.”
  • sugestão inlineinline suggestion. “The plugin shows an inline suggestion in gray as you type.”
  • realce de sintaxesyntax highlighting. “Syntax highlighting colors commands before you press Enter.”

Veja também

Referências