Harbor 1.0: Todo Servidor de Desenvolvimento no Seu Mac, a Um Atalho de Distância
Construí e lancei um utilitário nativo da barra de menus do macOS que mostra todo servidor de desenvolvimento escutando no localhost — com vitais ao vivo, ações em um clique e um release notarizado de verdade. Aqui está o que ele faz e o que foi preciso para colocá-lo no ar.
Todo desenvolvedor conhece o momento: Error: listen EADDRINUSE: address already in use :::3000.
Alguma coisa está ocupando a porta. Talvez seja o servidor do Vite de um projeto que você fechou dois dias atrás. Talvez seja um processo do Next.js que sobreviveu ao próprio terminal. Você cola a mesma reza de sempre — lsof -ti :3000 | xargs kill — e torce para matar a coisa certa.
O Harbor 1.0 existe para eu nunca mais fazer isso.
Sessenta segundos de Harbor — um motion demo feito com Remotion, coreografando footage real do painel a partir do release candidate.
O Que é o Harbor
O Harbor é um utilitário nativo da barra de menus do macOS que mostra todo servidor de desenvolvimento escutando no localhost — e deixa você agir sobre ele. Clique no bollard na sua barra de menus (ou aperte ⌘⌥P de qualquer lugar) e você recebe um painel ao vivo: cada porta em escuta, qual é o framework, há quanto tempo está rodando, quanto está custando de CPU e memória, e um selo de energia quando algo está queimando sua bateria em silêncio.

A partir desse painel, tudo está a uma ação de distância:
- Kill em um servidor — SIGTERM primeiro, escalando para SIGKILL só se preciso, com revalidação de identidade para que um PID reutilizado nunca derrube um processo inocente.
- Kill All — com uma confirmação enumerada que nomeia exatamente o que vai encerrar. Nada de varredura às cegas.
- Abrir no navegador — scheme detectado automaticamente, loopback IPv6 tratado.
- Pular para o terminal — o Harbor resolve qual terminal é dono do processo e o ativa. Funciona no Terminal, iTerm2, Warp, Ghostty, WezTerm, kitty, Alacritty e nos terminais do VS Code/Cursor.
A coisa toda é keyboard-first: setas para navegar, digitar para filtrar, Return para agir, Esc para fechar. Tem a cara e o comportamento do utilitário de sistema que ele é — claro e escuro, VoiceOver, Dynamic Type, movimento reduzido.

Enxergar Mais do Que um Número de Porta
Um número de porta sozinho não responde à pergunta real, que é: o que é isso e posso matar?
O Harbor detecta o framework por trás de cada listener — Vite, Next.js, Rails, Flask, Express e mais — e quando um servidor se esconde atrás de um worker filho (o servidor de desenvolvimento do Next faz isso em alguns setups, como nos screenshots acima), ele recua com honestidade para o selo de runtime em vez de chutar. Daemons de sistema também não fingem ser servidores de desenvolvimento: um resolvedor de portas conhecidas nomeia coisas como AirPlay e Screen Sharing, então a visão "Mostrar tudo" se lê como um inventário em vez de um mistério.
Cada linha se expande em um inspector inline: linha de comando completa, diretório de trabalho, o app dono, escopo de bind (isto está escutando no loopback ou exposto na sua rede?) e sparklines rolantes de CPU/memória desenhadas como barras discretas ancoradas no zero — para que um processo ocioso pareça ocioso em vez de parecer um sismógrafo.

Exposição é um sinal de primeira classe. Qualquer coisa que faça bind além do loopback é sinalizada no cabeçalho do painel — esse selo de contagem de expostos é a diferença entre um servidor de desenvolvimento e um serviço de rede acidental, trazido à tona antes de você sair procurando por ele.
Para as sessões de debug em que a porta está ocupada mas nada está escutando, uma visão opt-in traz à tona sockets UDP e estados TCP não-LISTEN travados (CLOSE_WAIT, FIN_WAIT) em uma seção discreta. Desligada por padrão, porque a visão padrão deve continuar limpa.
Local-First, de Forma Verificável
O Harbor nunca liga para casa. Não há telemetria, não há conta, não há chamadas de rede além das que você pede (abrir seu servidor no navegador, checar por updates). O app é assinado com Developer ID, tem hardened-runtime, é notarizado pela Apple e sai como um DMG universal com um SHA256 publicado. Os updates chegam pelo Sparkle com appcasts assinados por EdDSA.
Nada disso é linguagem de marketing — é o checklist que deu trabalho de verdade, o que me leva à parte deste post que eu realmente queria escrever.
A História da Construção
O Harbor é Swift e SwiftUI nativos — cinco módulos SwiftPM com um grafo de dependências estritamente acíclico: modelos puros na base, enumeração e inteligência de processos numa camada de serviços, design system e UI acima, uma composition root no topo. Os protocolos moram no core; as implementações moram nos serviços; a UI depende de abstrações. É a arquitetura chata, e é chata de propósito: cada camada é testável por unidade, e a suíte de testes roda com mais de 650 testes.
A maior parte da implementação foi agent-assisted — um time de agentes de coding trabalhando em paralelo em git worktrees, cada mudança passando pelo mesmo gauntlet: build completo, suíte de testes completa, lint, format, uma review adversarial por um agente separado e uma decisão de merge humana. A lição interessante não foi que agentes escrevem código. Foi que a qualidade mora na review.
Considere uma feature: a visão opt-in para sockets UDP e não-escutando. O agente de implementação produziu uma branch limpa — testes verdes, resolução de conflitos cuidadosa ao longo de quatorze commits de drift, compatibilidade byte por byte quando o toggle estava desligado. Parecia pronta. Aí a passada de review, conduzida por um agente separado sem nenhum interesse no trabalho, encontrou quatro coisas: o toggle de configurações estava ligado a um caminho de código que o app publicado nunca chamava, então a feature inteira era inalcançável em runtime; o Kill All havia silenciosamente ampliado seu raio de destruição para incluir as novas linhas subordinadas; o parser de fallback do lsof lia errado sockets conectados e os teria sinalizado como expostos à rede; e a rotatividade normal de TCP teria travado o loop de refresh adaptativo na frequência máxima para sempre. Quatro bugs reais, um deles destrutivo, numa branch que todo portão automatizado havia abençoado.
Esse padrão se repetiu por todo o caminho. Quem escreve não é quem acha o problema — é o cético. Estruturar o trabalho para que um par de olhos novos ataque cada mudança antes de um humano decidir é a coisa de maior alavancagem em todo o workflow, e isso é exatamente tão verdadeiro para agentes quanto sempre foi para pessoas.
Dois bugs merecem suas próprias frases, porque são do tipo que você só encontra quando lança de verdade.
Primeiro: o pipeline de release assinava o app dentro do DMG, mas nunca assinava o próprio container DMG. Todo portão automatizado estava verde até que a primeira rodada totalmente credenciada — certificado real, notarização real — bateu na checagem de assinatura externa do Gatekeeper e falhou. E você não conserta depois do fato: reassinar um DMG com o ticket grampeado invalida a notarização. O pipeline foi reconstruído para assinar antes da submissão. Nenhum dry run teria achado isso; só a coisa real achou.
Segundo: durante o QA do release candidate — eu, clicando por aí feito um usuário — o painel congelou de vez em 97% de CPU. O culpado foi um livelock de layout do SwiftUI: lazy stacks remedindo contra o rect visível de uma scroll view dentro de um popover que se autodimensiona, um loop de feedback que nunca convergia quando o inspector de uma linha estava se expandindo sob o cursor. A correção foi quase constrangedora: o painel mostra dezenas de linhas, então a laziness não comprava nada. Stacks comuns, geometria estável, bug resolvido.
Lançar é uma disciplina diferente de construir. Os últimos cinco por cento — notarização, grampeamento, Gatekeeper, assinatura de updates, checksums, evidência de release — são onde os projetos paralelos normalmente vão dormir. Atravessar isso é a maior parte do que "1.0" significa.
O Bollard
A marca do Harbor é um bollard de amarração com uma corda — a coisa que um porto de fato usa para segurar embarcações no lugar com segurança, do jeito que o Harbor segura seus servidores de desenvolvimento à vista. Dois arcos de vidro-do-mar sugerem uma porta viva, em escuta. Não é de propósito uma âncora e não é de propósito um container.
![]()
Baixe o Harbor
O Harbor 1.0 é grátis, roda no macOS 14+ e é universal (Apple silicon + Intel).
- Download: Harbor.dmg do último GitHub release — checksum SHA256 publicado ao lado.
- Landing page: ftchvs.github.io/harbor
- Changelog: notas de release completas
Se uma porta está ocupada agora mesmo — e uma está, sempre tem — o Harbor vai te dizer o que é, e encerrar em um atalho.