omp: do zero ao /vibe
- data
- tempo de jogo
- 00:13:00
- local
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).
| Passo | macOS | Linux (Debian/Ubuntu) | Windows |
|---|---|---|---|
| Gerenciador de pacotes | Homebrew | apt | winget |
| Terminal | Warp (o meu) | Warp ou qualquer um com Nerd Font | Windows Terminal (ou Warp) |
| Nerd Font | brew install --cask | zip em ~/.local/share/fonts + fc-cache | zip → Instalar |
| Tema do shell | Oh My Zsh + p10k | Oh My Zsh + p10k | só dentro do WSL2 |
| omp | brew install can1357/tap/omp | curl -fsSL https://omp.sh/install | sh | irm 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.
| Aspecto | Chat | Harness |
|---|---|---|
| Roda comandos | não | sim, com aprovação configurável |
| Edita arquivos | você copia e cola | direto no disco |
| Regras do projeto | você cola toda vez | carregadas sozinhas |
| Agentes em paralelo | não | subagentes e workers |
| Escolha de modelo | o que o app oferece | qualquer 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)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install --cask warpLinux (o básico que os próximos passos usam; terminal: Warp pelo site ou o que você já usa)
sudo apt update && sudo apt install -y curl git unzip fontconfigWindows (PowerShell; o Windows Terminal também vem da Microsoft Store)
winget install --id Microsoft.WindowsTerminal -e2. 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
brew install --cask font-jetbrains-mono-nerd-fontLinux (método manual do projeto nerd-fonts; fc-list confirma)
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:
{
"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:
[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)
sudo apt install -y zsh git curl
chsh -s "$(which zsh)" # vale no próximo loginmacOS, Linux e WSL2: a partir daqui é igual. Oh My Zsh e Powerlevel10k como tema dele, com os comandos dos READMEs oficiais:
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):
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)
brew install can1357/tap/ompLinux (script oficial; instala em ~/.local/bin, que precisa estar no PATH)
curl -fsSL https://omp.sh/install | sh
export PATH="$HOME/.local/bin:$PATH" # coloque no ~/.zshrc ou ~/.bashrcWindows (PowerShell, script oficial; dentro do WSL2, use o comando do Linux)
irm https://omp.sh/install.ps1 | iexEm 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)
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 provedorWindows (PowerShell 7.1+; grava uma variável de ambiente do usuário, que vale nos próximos terminais)
$k = Read-Host 'API key' -MaskInput
[Environment]::SetEnvironmentVariable('ANTHROPIC_API_KEY', $k, 'User')
Remove-Variable kO 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:
# ~/.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ídasOu pelo CLI, uma chave por vez (o nome precisa bater exatamente com o schema):
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 trueTudo 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:
| Chave | Valor | O que faz |
|---|---|---|
defaultThinkingLevel | max | profundidade de raciocínio padrão (padrão: high) |
temperature | 0.7 | temperatura de amostragem (padrão: a do provedor) |
memory.backend | local | extrai lições das sessões e injeta um resumo na próxima (padrão: off) |
autolearn.enabled | true | deixa o agente criar e atualizar skills gerenciadas |
autolearn.autoContinue | true | roda um turno privado de captura de lições ao parar; gasta token |
model.loopGuard.enabled | false | desliga o detector automático de loop no raciocínio e no texto |
model.toolCallLoopGuard.threshold | 20 | chamadas idênticas seguidas antes de intervir (padrão: 5) |
bash.allowCompoundCommands | true | avalia cada comando de uma cadeia && separadamente |
browser.headless | false | mostra a janela quando o agente usa o browser |
computer.enabled | true | libera o controle do desktop (screenshots, input) |
Duas que eu recomendo para todo mundo, mesmo não estando na minha lista:
secrets.enabled: true(padrãofalse): 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,writeaprova leitura e escrita e pergunta antes de executar. Subagentes sempre rodam emyolo; a aprovação que conta é a do pai.
7. Provedores e modelos
O omp trabalha com papéis, configurados em modelRoles no config.yml:
| Papel | Para quê |
|---|---|
default | a conversa principal |
smol | tarefas leves; workers fast do /vibe |
slow | raciocínio pesado |
plan | o plan mode (/plan) |
task | subagentes e workers good do /vibe |
vision | analisar imagens |
commit | omp commit |
tiny / memory | tí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:
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: 131072apiKey é “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 odefault(os workersfast, 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 papeldefault: Alt+P escolhe um modelo temporário para a sessão, eomp --model opusfaz o mesmo na linha de comando. - Gateway no
models.ymlcom 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.
/vibe # entra no modo
/vibe migra o parser # entra e já manda a primeira diretiva
/vibe # sai (encerra os workers)| Tier | Agente | Papel | Uso |
|---|---|---|---|
| fast | sonic | @smol | execução mecânica, volume, rascunho |
| good | task | @task | julgamento, 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:
task:
agentModelOverrides:
sonic: '@fast_worker'
task: '@good_worker'
modelRoles:
fast_worker: my-gateway/vendor/fast-model
good_worker: my-gateway/vendor/big-model:highEsse 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:
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.mde umAGENTS.mdsolto, procurado do diretório atual até a raiz do repo (lêCLAUDE.mdtambém). Mantenha curto: regras duras e onde está o resto. - Skills: um diretório com
SKILL.md(nameedescriptionno 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/; comautolearn, 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 emhttp://127.0.0.1:9876), e uma base de conhecimento privada, um servidor MCP em Python sobre as minhas anotações:
{
"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:
~/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.txtO loop de um atacante:
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 inscopedevolve exit0,2ou3; 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:
- Um terminal com fonte customizável: Warp (macOS/Linux/Windows) ou Windows Terminal.
- JetBrainsMono Nerd Font:
brew install --caskno macOS, zip +fc-cacheno Linux, zip → Instalar no Windows; selecionada no terminal. - (Opcional) zsh + Oh My Zsh + Powerlevel10k,
p10k configure(no Windows, dentro do WSL2). - omp:
brew install can1357/tap/omp,curl -fsSL https://omp.sh/install | shouirm https://omp.sh/install.ps1 | iex; depoisomp setupeomp loginou uma API key. - Tema e ícones:
theme.dark,symbolPreset,statusLine.preset,composer.shape. - Memória, segredos e aprovação.
- Papéis de modelo e, se precisar, um gateway no
models.yml. /vibequando o básico estiver chato de tão confiável.