arquivo 001português

omp: do zero ao /vibe

data
tempo de jogo
00:13:00
local
ompai-agentstoolingterminal

Instalação, tema, provedores, modelos e o /vibe: o passo a passo do meu setup do omp em macOS, Linux e Windows.

Primeiro post de verdade aqui, e é o tutorial que eu queria ter tido: sair do zero e chegar no meu setup do omp (oh-my-pi), bonito e configurado, passo a passo. Tudo foi conferido contra a documentação e o CLI do omp (18.12.5 aqui; o caminho Linux foi testado num container Ubuntu 24.04 limpo, que instalou a 18.12.6).

PassomacOSLinux (Debian/Ubuntu)Windows
Gerenciador de pacotesHomebrewaptwinget
TerminalWarp (o meu)Warp ou qualquer um com Nerd FontWindows Terminal (ou Warp)
Nerd Fontbrew install --caskzip em ~/.local/share/fonts + fc-cachezip → Instalar
Tema do shellOh My Zsh + p10kOh My Zsh + p10ksó dentro do WSL2
ompbrew install can1357/tap/ompcurl -fsSL https://omp.sh/install | shirm https://omp.sh/install.ps1 | iex

O que é um harness

Se você só usou LLM pela janela de chat, a peça que falta é esta. O modelo, sozinho, é texto entra, texto sai. Ele não lê seu repositório, não roda comando, não lembra da semana passada. O harness é o programa em volta dele que o transforma num agente:

  • O loop do agente. O modelo pede uma chamada de ferramenta, o harness executa e devolve o resultado, e isso se repete até a tarefa acabar.
  • As ferramentas. Ler e editar arquivo, shell, busca, browser, servidores MCP.
  • O que entra no contexto. System prompt, regras do projeto (AGENTS.md), skills, memória, conteúdo de arquivos, e a compactação quando o contexto enche.
  • Permissões e aprovações. O que roda sozinho e o que precisa do seu “ok”.
  • Sessões e histórico. Retomar de onde parou.
  • Subagentes e orquestração. Dividir o trabalho entre vários agentes (no omp, isso inclui o /vibe).
  • Roteamento de modelos. Um modelo forte para pensar, um barato para o braçal.

Pensa num console: o modelo é a CPU; o harness é todo o resto, controle, memory card e leitor de disco.

Na prática, o agente age em vez de sugerir: roda o comando e lê a saída, sem você copiar e colar. Ele segura estado numa tarefa longa. E regras, skills e contexto de projeto fazem o agente seguir o seu método toda vez, sem você colar as mesmas instruções em cada conversa. Trabalho em paralelo vira subagente ou worker. Pela minha experiência, o mesmo modelo parece outro dependendo das ferramentas e de como o harness cuida do contexto.

O que ele não faz: não substitui julgamento e não transforma modelo ruim em modelo bom.

AspectoChatHarness
Roda comandosnãosim, com aprovação configurável
Edita arquivosvocê copia e coladireto no disco
Regras do projetovocê cola toda vezcarregadas sozinhas
Agentes em paralelonãosubagentes e workers
Escolha de modeloo que o app oferecequalquer provedor, um por tarefa

Exemplos da categoria: Claude Code, Codex CLI, opencode, Aider, o agente do Cursor e o omp.

Por que o omp

Pra mim, o omp ganha por juntar tudo isso num lugar só: dezenas de provedores (por variável de ambiente, login OAuth ou qualquer gateway compatível), modelos locais detectados sozinhos, papéis de modelo com nível de thinking por papel, subagentes customizáveis em markdown, o /vibe, skills, memória entre sessões, MCP, modos de aprovação, ofuscação de segredos, perfis isolados e sessões que dá para retomar. E ainda é bonito no terminal, que é metade deste post.

1. Pré-requisitos e terminal

O omp não precisa de runtime: o Homebrew e os scripts oficiais entregam um binário pronto. O Bun (≥ 1.3.14, segundo o README) só entra se você preferir instalar com bun install -g @oh-my-pi/pi-coding-agent.

O terminal precisa aceitar uma fonte customizada. No macOS eu uso o Warp, que também tem versão para Linux e Windows. No Windows, o padrão sensato é o Windows Terminal.

macOS (Homebrew, comando oficial do brew.sh, e o Warp)

BASH
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install --cask warp

Linux (o básico que os próximos passos usam; terminal: Warp pelo site ou o que você já usa)

BASH
sudo apt update && sudo apt install -y curl git unzip fontconfig

Windows (PowerShell; o Windows Terminal também vem da Microsoft Store)

POWERSHELL
winget install --id Microsoft.WindowsTerminal -e

2. Nerd Font

Uma Nerd Font é uma fonte de programação com milhares de ícones extras embutidos: logo do git, pasta, setas powerline, spinners. O omp usa esses ícones quando você liga symbolPreset: nerd, o status line tem um preset nerd, e o Powerlevel10k do passo 3 também depende deles. Sem a fonte, os ícones viram quadradinhos.

Eu uso a JetBrains Mono Nerd Font, na variante NL (sem ligaduras), cujo nome de família é JetBrainsMonoNL Nerd Font.

macOS

BASH
brew install --cask font-jetbrains-mono-nerd-font

Linux (método manual do projeto nerd-fonts; fc-list confirma)

BASH
mkdir -p ~/.local/share/fonts
curl -fsSLo /tmp/JetBrainsMono.zip \
  https://github.com/ryanoasis/nerd-fonts/releases/latest/download/JetBrainsMono.zip
unzip -oq /tmp/JetBrainsMono.zip -d ~/.local/share/fonts/JetBrainsMono
fc-cache -fv
fc-list | grep -i "JetBrainsMonoNL Nerd Font"

No Arch, o pacote oficial é sudo pacman -S ttf-jetbrains-mono-nerd.

Windows (baixe JetBrainsMono.zip em github.com/ryanoasis/nerd-fonts/releases/latest, extraia, selecione os .ttf e clique com o botão direito → Instalar). Depois, no settings.json do Windows Terminal (Configurações com Shift pressionado), a fonte vale para todos os perfis em profiles.defaults:

JSON
{
  "profiles": {
    "defaults": {
      "font": { "face": "JetBrainsMonoNL Nerd Font", "size": 13 }
    }
  }
}

Se você usa WSL2, a fonte é instalada no Windows: quem desenha os ícones é o Windows Terminal, não o Linux.

Selecionar no terminal. No Warp (qualquer sistema), escolha JetBrainsMonoNL Nerd Font nas configurações de aparência. No macOS o meu ~/.warp/settings.toml fica assim:

TOML
[appearance.text]
font_family = "JetBrainsMonoNL Nerd Font"
font_size = 13.0

[appearance.themes]
theme = "dark"

[appearance.cursor]
cursor_display_type = "bar"

Em outro terminal (iTerm2, Ghostty, Kitty, GNOME Terminal…), o princípio é o mesmo: a fonte do terminal tem que ser uma Nerd Font.

3. A cara do shell (opcional)

Eu uso Oh My Zsh com o tema Powerlevel10k. Não é necessário para o omp, mas faz parte da cara do meu terminal. Zsh, Oh My Zsh e p10k são coisa de shell Unix: no Windows eles funcionam dentro do WSL2, não no PowerShell.

macOS: o zsh já é o shell padrão; nada a instalar.

Linux (e Windows dentro do WSL2: instale com wsl --install num PowerShell de administrador, reinicie, abra o Ubuntu e siga daqui)

BASH
sudo apt install -y zsh git curl
chsh -s "$(which zsh)"   # vale no próximo login

macOS, Linux e WSL2: a partir daqui é igual. Oh My Zsh e Powerlevel10k como tema dele, com os comandos dos READMEs oficiais:

BASH
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
  "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k"

No ~/.zshrc, troque o tema (eu deixo só o plugin git):

BASH
ZSH_THEME="powerlevel10k/powerlevel10k"
plugins=(git)

Abra um terminal novo; o wizard começa sozinho. Se não começar, rode p10k configure. As minhas escolhas foram: nerdfont-v3 + powerline, ícones pequenos, estilo rainbow, relógio 24h, separadores angulares, duas linhas, transient prompt e instant prompt. O wizard grava tudo em ~/.p10k.zsh. No Warp, o prompt do p10k só aparece com honor_ps1 = true em [terminal.input].

4. Instalando o omp

macOS (é como eu instalo)

BASH
brew install can1357/tap/omp

Linux (script oficial; instala em ~/.local/bin, que precisa estar no PATH)

BASH
curl -fsSL https://omp.sh/install | sh
export PATH="$HOME/.local/bin:$PATH"   # coloque no ~/.zshrc ou ~/.bashrc

Windows (PowerShell, script oficial; dentro do WSL2, use o comando do Linux)

POWERSHELL
irm https://omp.sh/install.ps1 | iex

Em qualquer sistema, confira com omp --version. omp setup roda o wizard de onboarding; depois é só omp dentro de um projeto. Tudo do usuário mora em ~/.omp/agent/ (omp config path mostra onde): config.yml, models.yml, mcp.json, .env, skills/, agents/.

Um provedor. OAuth (assinatura) é igual em todo sistema: omp login e escolha na lista (dentro da sessão, /login). Para API key, deixe a chave fora do histórico do shell:

macOS e Linux (funciona em zsh e bash)

BASH
printf 'API key: ' && read -rs K && printf '\nANTHROPIC_API_KEY=%s\n' "$K" >> ~/.omp/agent/.env && unset K
chmod 600 ~/.omp/agent/.env
omp models   # o que ficou disponível, agrupado por provedor

Windows (PowerShell 7.1+; grava uma variável de ambiente do usuário, que vale nos próximos terminais)

POWERSHELL
$k = Read-Host 'API key' -MaskInput
[Environment]::SetEnvironmentVariable('ANTHROPIC_API_KEY', $k, 'User')
Remove-Variable k

O omp lê OPENAI_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY, DEEPSEEK_API_KEY e várias outras; omp --help lista as principais.

5. Deixando o omp bonito

Daqui até o fim, tudo é igual nos três sistemas: é config do omp, não do SO. O visual fica em ~/.omp/agent/config.yml. Estes são os valores que eu mudei do padrão:

YAML
# ~/.omp/agent/config.yml — aparência
theme:
  dark: dark-dracula # tema embutido (padrão: titanium)
symbolPreset: nerd # ícones da Nerd Font (padrão: unicode)
statusLine:
  preset: nerd # ícones no status line (padrão: default)
  contextLine: annotated # uso de contexto anotado
composer:
  shape: box # editor numa caixa (padrão: band)
display:
  showTokenUsage: true # tokens por resposta
  showTurnTime: true # tempo total de cada turno, ferramentas incluídas

Ou pelo CLI, uma chave por vez (o nome precisa bater exatamente com o schema):

BASH
omp config set theme.dark dark-dracula
omp config set symbolPreset nerd
omp config set statusLine.preset nerd
omp config set statusLine.contextLine annotated
omp config set composer.shape box
omp config set display.showTokenUsage true
omp config set display.showTurnTime true

Tudo isso também está em /settings, dentro da sessão, se você preferir menu. Outras opções de statusLine.preset: default, minimal, compact, full, ascii, custom. O separador fica em statusLine.separator (powerline, powerline-thin, slash, pipe, block, none, ascii). Temas próprios são arquivos JSON em ~/.omp/agent/themes/.

Resultado esperado: ao abrir omp, o editor aparece numa caixa, o status line mostra modelo, pasta e git com ícones, e as cores são as do Dracula. Se aparecerem quadradinhos, a fonte do passo 2 não está selecionada.

6. Configs que valem a pena além do visual

As minhas, todas fora do padrão:

ChaveValorO que faz
defaultThinkingLevelmaxprofundidade de raciocínio padrão (padrão: high)
temperature0.7temperatura de amostragem (padrão: a do provedor)
memory.backendlocalextrai lições das sessões e injeta um resumo na próxima (padrão: off)
autolearn.enabledtruedeixa o agente criar e atualizar skills gerenciadas
autolearn.autoContinuetrueroda um turno privado de captura de lições ao parar; gasta token
model.loopGuard.enabledfalsedesliga o detector automático de loop no raciocínio e no texto
model.toolCallLoopGuard.threshold20chamadas idênticas seguidas antes de intervir (padrão: 5)
bash.allowCompoundCommandstrueavalia cada comando de uma cadeia && separadamente
browser.headlessfalsemostra a janela quando o agente usa o browser
computer.enabledtruelibera o controle do desktop (screenshots, input)

Duas que eu recomendo para todo mundo, mesmo não estando na minha lista:

  • secrets.enabled: true (padrão false): env vars com cara de credencial e padrões conhecidos (JWT, Bearer, chaves de cloud) viram placeholders no texto enviado ao provedor e voltam ao normal na hora de executar a ferramenta. Não pega valor curto nem o prompt estático.
  • tools.approvalMode: o padrão é yolo (roda tudo). Se você está começando, write aprova leitura e escrita e pergunta antes de executar. Subagentes sempre rodam em yolo; a aprovação que conta é a do pai.

7. Provedores e modelos

O omp trabalha com papéis, configurados em modelRoles no config.yml:

PapelPara quê
defaulta conversa principal
smoltarefas leves; workers fast do /vibe
slowraciocínio pesado
plano plan mode (/plan)
tasksubagentes e workers good do /vibe
visionanalisar imagens
commitomp commit
tiny / memorytítulos de sessão e pipeline de memória

O sufixo :nível define o thinking por papel (off, minimal, low, medium, high, xhigh, max, auto): default: deepseek/deepseek-v4-flash:max. smol e slow sem valor herdam o default. Para trocar: /model abre o hub, Ctrl+P alterna entre os modelos dos papéis, Shift+Tab alterna o thinking, e omp --model opus aceita busca aproximada.

Gateway próprio (qualquer endpoint compatível com OpenAI ou Anthropic) vai em ~/.omp/agent/models.yml:

YAML
providers:
  my-gateway:
    baseUrl: https://gateway.example/v1
    api: openai-completions # ou anthropic-messages, openai-responses…
    apiKey: MY_GATEWAY_API_KEY # nome da env var; o omp usa o valor dela
    authHeader: true # Authorization: Bearer <chave>
    models:
      - id: vendor/big-model # o id que o endpoint espera
        name: Big Model
        reasoning: true
        thinking: { mode: effort, efforts: [low, high, max], defaultLevel: high }
        input: [text, image]
        contextWindow: 1048576
        maxTokens: 131072

apiKey é “nome de env var ou literal”: se bater com uma variável preenchida, vale o valor dela. Um erro de YAML faz o omp ignorar o arquivo inteiro, então sempre confira com omp models my-gateway. E antes de declarar um provedor, rode omp models <nome>: se ele já vem embutido, só falta a credencial.

O que eu uso:

  • Papel default: deepseek/deepseek-v4-flash:max, pelo provedor DeepSeek embutido. Tudo que herda o default (os workers fast, por exemplo) roda nele.
  • Sessão principal e diretor do /vibe: Claude Opus (anthropic/claude-opus-5-5). O omp permite trocar o modelo só da sessão sem mexer no papel default: Alt+P escolhe um modelo temporário para a sessão, e omp --model opus faz o mesmo na linha de comando.
  • Gateway no models.yml com DeepSeek V4.1 Flash, Nemotron 3.5 Super VL 120B e GLM-5.3 Flash, todos com 1M de contexto, a escada de effort declarada e custo preenchido para o omp contabilizar.

8. /vibe

/vibe transforma a sessão num diretor. O diretor fica só com read, um todo opcional e cinco ferramentas de controle; quem busca, edita e roda são workers persistentes em background, cada um com a própria transcrição.

Diagrama do /vibe: o diretor dispara workers fast e good, que trabalham no workspace; o diretor verifica lendo os arquivos
O diretor lê e decide; os workers fazem.
TEXT
/vibe                       # entra no modo
/vibe migra o parser        # entra e já manda a primeira diretiva
/vibe                       # sai (encerra os workers)
TierAgentePapelUso
fastsonic@smolexecução mecânica, volume, rascunho
goodtask@taskjulgamento, design, revisar o fast

O diretor usa vibe_spawn (cria um worker com brief e tier), vibe_send (corrige o rumo ou manda o próximo passo), vibe_wait, vibe_kill e vibe_list. Você só fala com ele em linguagem natural.

Para escolher os modelos dos tiers, a documentação sugere aliases:

YAML
task:
  agentModelOverrides:
    sonic: '@fast_worker'
    task: '@good_worker'
modelRoles:
  fast_worker: my-gateway/vendor/fast-model
  good_worker: my-gateway/vendor/big-model:high

Esse override vale para todo subagente sonic e task, não só para o /vibe. No meu caso não configurei nada: o fast herda o default (DeepSeek V4 Flash) e o good cai no modelo ativo do diretor (Opus). Braçal barato, julgamento caro.

Como brifar. O worker não vê a conversa do diretor. Dê arquivos, restrições e um critério de aceite que dê para checar:

TEXT
Objetivo: paginação por cursor em GET /api/orders.
Arquivos: src/api/orders.ts, tests/orders.test.ts. Não mexa em outros.
Aceite: `npm test -- orders` passa, com um teste novo para a última página.
Entregue: arquivos tocados e a saída do teste.

Como verificar. O próprio doc diz: worker que terminou significa que o turno acabou, não que ele acertou. O diretor lê os arquivos tocados e a saída completa em agent://<id>. Um worker por frente de trabalho, fast e good em paralelo, e o good revisando o fast quando importa.

Armadilhas: sair do /vibe encerra todos os workers; não combina com plan mode nem goal mode; com ele ativo, não dá para criar, apagar, forkar ou mover a sessão. Este post, inclusive, foi rascunhado por um worker do omp numa sessão de diretor.

9. Skills, MCP e AGENTS.md

  • AGENTS.md: o omp carrega ~/.omp/agent/AGENTS.md, .omp/AGENTS.md e um AGENTS.md solto, procurado do diretório atual até a raiz do repo (lê CLAUDE.md também). Mantenha curto: regras duras e onde está o resto.
  • Skills: um diretório com SKILL.md (name e description no frontmatter). Só nome e descrição vão para o prompt; o corpo carrega sob demanda (skill://<nome>). As suas ficam em ~/.omp/agent/skills/; com autolearn, o agente escreve as dele em ~/.omp/agent/managed-skills/. Eu tenho umas 30 minhas (classes de vulnerabilidade, metodologia, triagem, escrita de relatório) e dezenas de gerenciadas.
  • MCP: ~/.omp/agent/mcp.json, com ${VAR} expandido. Eu uso o Burp Suite, pela extensão oficial MCP Server da PortSwigger (SSE local, por padrão em http://127.0.0.1:9876), e uma base de conhecimento privada, um servidor MCP em Python sobre as minhas anotações:
JSON
{
  "mcpServers": {
    "burp": { "type": "sse", "url": "http://127.0.0.1:9876" },
    "kb": {
      "type": "stdio",
      "command": "${HOME}/kb/.venv/bin/python",
      "args": ["${HOME}/kb/server.py"],
      "env": { "KB_PATH": "${HOME}/kb/data" }
    }
  }
}

10. Um gostinho: bug bounty

Para programa grande eu abro vários terminais com omp, cada um com um papel, e eles conversam só pelo filesystem. Eu chamo isso de matilha: um orch cuida do escopo e da fila, atacantes a1..aN pegam um host por vez, e um triage valida os candidatos. Toda escrita compartilhada passa por um script bash, o bin/hb:

TEXT
~/hunting/
├── PROTOCOL.md            # o contrato: papéis, lease, rate, prova
├── bin/hb                 # o barramento
├── scope/<program>/       # eligible.txt, deny.txt
└── state/
    ├── queue.jsonl        # fila append-only
    ├── claims/<host>/     # lease por mkdir atômico (dono + epoch)
    ├── findings.jsonl     # tudo nasce "candidate"
    ├── dead-ends.md       # negativos verificados + controle usado
    ├── intel.md           # padrão reutilizável: "[tag] fato → ação"
    └── loot/F-0001/       # request.txt, response.txt

O loop de um atacante:

BASH
HOST=$(bin/hb next a1) || exit 0     # lease atômico do próximo host
bin/hb inscope "$HOST" || { bin/hb release "$HOST" a1; exit 3; }
grep -i "$HOST" state/dead-ends.md state/intel.md   # não repetir teste morto
ffuf -u "https://$HOST/FUZZ" -w wordlists/base.txt -ac -rate 20 -t 10 -o "recon/$HOST/ffuf.json"
bin/hb finding a1 "$HOST" idor "https://$HOST/api/orders?id=2" "BOLA em /orders" "200 com pedido da conta B"
bin/hb done "$HOST" a1 findings "1 candidate"

Os guardrails são executáveis, não promessas do modelo:

  • Escopo: hb inscope devolve exit 0, 2 ou 3; deny vence allow; host não listado não é tocado.
  • Rate: cap explícito por ferramenta, request manual a 1/s por host, e 403/429 em rajada pausa o host por 10 minutos.
  • Prova antes de alegação: sem request e response em state/loot/, é só candidato. A triagem reproduz do zero com controle negativo, num modelo de outra família.
  • Revisão humana: o agente pode rascunhar o relatório, mas a reprodução manual, a revisão e o envio são meus.

Isso rende um post só para ele. Fica para o próximo.

Fechando

O harness não pensa por você, mas faz o seu método rodar igual toda vez, e com um terminal que dá gosto de olhar. Recapitulando:

  1. Um terminal com fonte customizável: Warp (macOS/Linux/Windows) ou Windows Terminal.
  2. JetBrainsMono Nerd Font: brew install --cask no macOS, zip + fc-cache no Linux, zip → Instalar no Windows; selecionada no terminal.
  3. (Opcional) zsh + Oh My Zsh + Powerlevel10k, p10k configure (no Windows, dentro do WSL2).
  4. omp: brew install can1357/tap/omp, curl -fsSL https://omp.sh/install | sh ou irm https://omp.sh/install.ps1 | iex; depois omp setup e omp login ou uma API key.
  5. Tema e ícones: theme.dark, symbolPreset, statusLine.preset, composer.shape.
  6. Memória, segredos e aprovação.
  7. Papéis de modelo e, se precisar, um gateway no models.yml.
  8. /vibe quando o básico estiver chato de tão confiável.