cannonball
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 8 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Você não começa do zero — chega com impulso. Guarda as peças de site que você já fez e as encontra de volta antes de gerar qualquer coisa outra vez. Agent Skills para Claude Code, Codex, Gemini CLI e Cursor.
cannonball
Você não começa do zero. Você já chega com impulso.
Plugin do Claude Code que guarda as peças de site que você já fez — e as encontra
de volta, antes de qualquer coisa ser gerada outra vez.
O acervo é seu, e começa quase vazio: vêm três peças de exemplo e mais nada.
Você alimenta com o que já tem — prompt, componente, efeito, design system, projeto
inteiro — e a partir daí as skills decidem a partir do que existe ali dentro, não de
uma lista fixa escrita por outra pessoa.
Nenhuma skill carrega número fixo. Todas leem o acervo na hora, então o mesmo motor
serve quem tem três peças e quem tem mil — e fica melhor a cada uma que entra.
O ciclo
ingerir → indexar → buscar → montar → registrar armadilha → ingerir…
Cada volta o acervo fica melhor, e as skills junto com ele. Não há número fixo em
lugar nenhum: toda skill lê o acervo na hora.
python scripts/perfil.py
É o retrato de agora — famílias, setores, stacks, cobertura por função, lacunas,
armadilhas registradas e os avisos de saúde. Toda skill começa por aí.
Instalar
Requisito único: Python 3. Os scripts importam só a biblioteca padrão — sempip install, sem node_modules, sem rede.
Claude Code
git clone https://github.com/harebeats/cannonball.git
cd cannonball
claude plugin marketplace add .
claude plugin install cannonball@cannonball
Codex, Gemini CLI, Cursor e os outros
A CLI do Agent Skills instala nos agentes que encontrar:
npx skills add harebeats/cannonball -g
-g instala para o seu usuário (~/.codex/skills, ~/.gemini/skills,~/.agents/skills…); sem ele, instala no projeto atual. Para mirar um só:
npx skills add harebeats/cannonball -g -a codex
npx skills add harebeats/cannonball -g -a gemini
npx skills list harebeats/cannonball # ver as 9 antes de instalar
Cada pasta em skills/ é autocontida — carrega o SKILL.md, o scripts/ que ele
chama, o references/ que cita e o seed/. Você pode instalar as nove ou só a que
interessa: kit-cor e kit-tipo, por exemplo, resolvem paleta e licença de fonte sem
depender de acervo nenhum.
Manual, em qualquer agente
git clone https://github.com/harebeats/cannonball.git
ln -s "$(pwd)/cannonball/skills/kit-buscar" ~/.agents/skills/kit-buscar
O símbolo mantém a instalação em dia com o seu clone. Serve para ~/.codex/skills,~/.gemini/skills, ~/.cursor/skills — a pasta muda, o resto não.
Por que funciona igual em todos. Nenhum
SKILL.mdusa variável de ambiente de
agente. Cada um resolve os próprios scripts a partir da pasta de onde foi lido, o
que é informação que todo harness dá. Ver AGENTS.md.O frontmatter fica nos seis campos da spec do Agent Skills
—name,description,license,compatibility,metadata,allowed-tools.
Campo fora da spec não é ignorado lá fora:npx skills adde a Skills API falham
com erro duro.publicar.pyrecusa exportar se algum escapar.
O acervo é criado em ~/.cannonball na primeira vez que uma skill roda, já com as
três peças de exemplo dentro.
O que vem na caixa
Três componentes originais, e eles existem tanto para a primeira busca devolver
alguma coisa quanto para servir de modelo de ficha bem escrita:
| Peça | O que resolve |
|---|---|
kit-agendamento |
serviço → data/hora → contato, com expediente, duração e antecedência como configuração |
kit-calendario |
seleção de data com teclado, idioma via Intl, disponibilidade por predicado |
kit-mapa |
localização sem chave de API, na paleta do site por filtro CSS |
Vêm com 11 armadilhas registradas — sobreposição de horário que dobra a agenda,new Date() durante a renderização quebrando hidratação entre servidor UTC e
visitante UTC−3, iframe de mapa roubando o scroll da página. Busque poragendamento e leia: é o formato que o resto do acervo deve seguir.
Nenhuma tem dependência npm nem asset externo. Toda a aparência sai de variável CSS
(--kit-*, com fallback nos tokens do site e, por último, currentColor), e texto e
regra de negócio saem de prop. Trocar de cliente é trocar configuração.
São suas depois de copiadas: edite, melhore ou apague. Nada volta a sobrescrever.
Vincule a sua pasta — é o primeiro passo, e o mais fácil de esquecer
Sem isso o acervo nasce em ~/.cannonball, que serve para experimentar mas quase
nunca é onde você quer o material a longo prazo. Faça antes de ingerir qualquer
coisa — depois é mover pasta na mão.
python scripts/vincular.py --para ~/meu-acervo
O ponteiro é gravado em ~/.cannonball/aonde, fora do plugin. Isso importa: o
plugin instalado é uma cópia em cache que a próxima atualização apaga, então qualquer
configuração gravada dentro dele se perde em silêncio.
python scripts/vincular.py # onde está agora, e quem está mandando
python scripts/vincular.py --para <pasta> --mover # leva junto o que já tem
python scripts/vincular.py --soltar # volta para o padrão
Se preferir variável de ambiente, ela vence o ponteiro:export CANNONBALL_ACERVO="/caminho/para/o/acervo".
Aponte para uma pasta versionada num repositório privado seu: o acervo é material
seu e de terceiros, e não é para redistribuir.
Por onde começar
O plugin não impõe ordem — as skills disparam sozinhas quando o assunto aparece. Mas
existe uma sequência que dá resultado muito melhor, e ela sai adaptada ao estado do
seu acervo em:
python scripts/perfil.py
Uma vez, ao instalar:
| 1 | vincular.py --para <pasta> |
diga qual pasta é o seu acervo |
| 2 | /kit-ingerir |
encha com o que você já tem — arquivo, texto colado, projeto inteiro, registro shadcn |
| 3 | /kit-curar |
depois da primeira leva grande: acha ficha fraca, que é peça invisível para a busca |
Em cada projeto novo:
| 1 | /kit-buscar |
o que eu já tenho pra isso? Dispara sozinha antes de construir |
| 2 | /kit-cor |
decida a cor antes de escolher o design system |
| 3 | /kit-tipo |
confira a licença antes de adotar a fonte |
| 4 | /kit-montar |
pergunta a stack e o tipo de hero, e monta |
| 5 | /kit-otimizar-3d |
se tem WebGL, antes de entregar |
| 6 | /kit-ingerir |
guarde o que deu certo e registre a armadilha |
A ordem de 2 e 3 não é preciosismo: escolher o design system primeiro faz a cor e a
fonte virem de brinde, e é exatamente assim que se chega no automático — e como se
descobre na entrega que a fonte é paga.
O passo 6 é o que fecha o ciclo. Sem ele o plugin é uma biblioteca parada; com ele,
cada projeto deixa o próximo mais rápido.
As duas que trabalham com prompt
Nem todo trabalho termina em código escrito aqui. Metade do que circula em web design
hoje é prompt — o brief que você leva ao v0, o texto que alguém te mandou no
Twitter, a spec que você guarda para reusar. Duas skills existem só para isso, e elas
são as portas de entrada e de saída do acervo.
/kit-prompt — o acervo vira prompt
Entrevista sobre o site e devolve um prompt de construção completo, no padrão dos
que já funcionaram: stack, fontes com licença conferida, paleta com contraste medido,
estrutura seção a seção, medidas exatas e proibições explícitas.
O resultado é texto. Você leva para o v0, o Lovable, o Cursor, outro modelo — ou
guarda no acervo para a próxima vez.
"gera um prompt pra uma landing de clínica" → o texto, pronto para levar
O que separa isso de pedir um prompt a qualquer modelo: ele é alimentado pelo seu
acervo. A paleta sai da kit-cor com contraste já medido, a fonte sai da kit-tipo
com licença já conferida, a estrutura sai de um template que já rodou. Prompt genérico
devolve site genérico.
/kit-adaptar — o prompt de fora vira seu
O caminho inverso, e o mais subestimado. Alguém te manda um prompt em inglês, sem
contexto, que constrói sabe-se lá o quê. Esta skill lê e devolve em português:
- que tipo de site é, e qual o escopo real (hero solto ou landing inteira)
- seção por seção, o que cada uma faz
- a técnica por trás (hover, cursor, scroll, WebGL, vídeo) e o que ela custa
- stack e dependências
- o mapa de assets — o caminho exato de cada arquivo que o prompt vai pedir
Essa última linha é a que economiza a tarde: prompt de fora sempre assume mídia que
você não tem. O que faltar vira placeholder descrito, não erro no meio do build.
Depois ela torce o prompt para o seu projeto — sua stack, seu setor, seu cliente.
Aceita print ou vídeo do site original junto, se você tiver.
[cola um prompt em inglês] → "o que é isso?" → "adapta pra clínica"
As duas funcionam com o acervo vazio. A kit-adaptar não depende de peça nenhuma,
e a kit-prompt fica melhor com acervo mas não precisa dele. São o caminho mais curto
para tirar valor do plugin no primeiro dia — e o que sair bom delas, você ingere.
O exemplo
exemplo/ — a SHUI, loja de streetwear com 81 produtos, 765
variantes e 99 páginas estáticas, montada de três peças do acervo: um template deu as
rotas e o carrinho, outro deu a ficha de produto, um design system deu a identidade.
E os quatro bugs que a montagem encontrou — SKU repetido entre tamanhos, opcao1
que não é a cor, next/link baixando doze páginas por clique, a mesma cor cadastrada
de cinco jeitos. Nenhum dá erro. Todos viraram armadilha nas peças de origem.
É o ciclo inteiro num lugar só: buscar → montar → tropeçar → registrar.
As skills
| Skill | Quando dispara |
|---|---|
kit-buscar |
"que hero eu tenho pra clínica?" — e sozinha, antes de construir qualquer seção |
kit-montar |
"monta uma landing pra joalheria" — do briefing ao código |
kit-prompt |
"gera um prompt pra esse site" — do briefing ao texto, para levar ao v0, Lovable, Cursor. Detalhe ↑ |
kit-adaptar |
"o que esse prompt constrói?" — lê prompt de fora, traduz, mapeia os assets e adapta ao seu projeto. Detalhe ↑ |
kit-cor |
"define a paleta", "está tudo no automático" — decide a cor antes do design system |
kit-tipo |
"que fonte usar", "essa fonte é paga?" — licença, substituto livre, par e escala |
kit-otimizar-3d |
"a cena trava no celular" — e antes de entregar qualquer projeto com WebGL |
kit-ingerir |
"guarda isso" — arquivo, texto colado, projeto inteiro, registro shadcn ou MCP |
kit-curar |
saúde do acervo: duplicatas, fichas fracas, assets mortos |
Quatro delas funcionam com o acervo vazio: kit-cor, kit-tipo,kit-otimizar-3d e kit-adaptar não dependem de peça guardada. As outras degradam
com uma frase em vez de quebrar, e mandam você ingerir.
As famílias
Um acervo mistura naturezas diferentes, e é a natureza que decide como a peça se usa:
| Família | O que é | Como se usa |
|---|---|---|
receita |
composição de peças que já deu certo | ponto de partida |
template |
projeto de site completo e rodável | você clona |
design-system |
identidade visual: paleta, tipografia, regras | você aplica |
efeito |
wrapper WebGL ou objeto 3D | você copia |
ui |
componente React pronto | você copia |
animacao |
demo isolada de uma técnica | você extrai |
html |
página completa sem build | abre no navegador |
mcp |
ficha aqui, código gerado sob medida por um servidor | você pede |
prompt |
spec em linguagem natural de uma página | você executa |
Ordem de preferência quando mais de uma serve: receita → template → código →
prompt. Prompt por último porque re-gera tudo e o resultado varia.
A combinação que dá o maior ganho, e a razão de o acervo existir:
template ou prompt dá a estrutura — rotas, seções, componentes.
design system dá a identidade — paleta, tipografia, espaçamento, regras.
Os dois eixos são independentes, então N templates × M identidades é um espaço de
combinação grande sem repetir visual entre clientes.
O que faz a busca funcionar
Cada peça tem quando_usar e nao_usar_quando. São eles que fazem a skill decidir
sozinha, em vez de devolver 12 heros para você escolher na mão.
nao_usar_quando fica fora do texto pesquisável de propósito: se entrasse,
buscar "mobile" ranquearia no topo justamente as peças que dizem "não use em mobile".
Ao guardar peça nova, esses dois campos são o trabalho que importa. Concreto vence
genérico: "clínica odontológica que quer destacar um procedimento" serve; "sites
modernos e bonitos" não serve para nada. Uma peça mal descrita continua no disco e
some da busca — e some da busca é o mesmo que não ter.
Armadilhas — o ciclo que faz o acervo aprender
nao_usar_quando responde "devo escolher esta peça?". Armadilha responde outra
coisa: "escolhi — onde vou tropeçar?".
Toda montagem descobre o que não estava em documentação nenhuma. Esse conhecimento
custou caro e não pode morrer dentro da nota de um projeto:
python scripts/armadilhas.py --add luxury-hero \
--texto "Tailwind v4: o reset '*{padding:0}' precisa ficar dentro de @layer base — solto, anula o espaçamento inteiro em silêncio" \
--origem imobiliaria-luxo-escura --grau alta
python scripts/indexar.py
A busca imprime como ARMADILHA: e o texto entra no índice — quem procura
"contraste" acha as peças que já reprovaram.
--grau separa o que trava do que incomoda: critica (página em branco, build
falhando, dado errado gravado), alta (visual quebrado, performance no chão) emedia (ajuste fino). A busca ordena por gravidade — sem isso, a que derruba o site
sai lado a lado com a que desalinha 2px.
É o que nenhum catálogo externo tem. Catálogo descreve o que a peça faz; só o seu
acervo sabe onde ela já te derrubou.
Cor e tipografia: os dois vieses previsíveis
Todo acervo montado a partir de site real herda os mesmos dois defeitos. Os dois são
mensuráveis, e as skills medem em vez de adivinhar.
Cor — mesmice. Design system vem de marca, marca converge para neutro e azul,
tema claro. Puxar design system sem ter decidido a cor devolve o lugar-comum.
python scripts/cor.py --vies # de onde vem o automático
python scripts/cor.py --paleta --fundo … --tinta … --acento …
python scripts/cor.py --contraste "#767676" "#ffffff"
O script deriva 11 papéis a partir de três decisões e mede WCAG 2.x em cada par que
existe na tela — separando o que tem mínimo obrigatório do que não tem. Divisória
decorativa não precisa de 3:1, e forçá-la produz aquela borda pesada que denuncia
site feito por régua.
Tipo — fragmentação, e o problema é legal. Site de marca paga por tipo, então o
acervo enche de fonte comercial que você não pode servir. Design system nomeia a
fonte e não diz onde carregá-la; prompt de página puxa de site de redistribuição.
python scripts/tipo.py --vies
python scripts/tipo.py --licenca "Aeonik" # comercial, CoType
python scripts/tipo.py --substituir "Roobert" # -> General Sans
python scripts/tipo.py --par "Instrument Serif"
python scripts/tipo.py --escala --base 17 --razao 1.25
Cor é de graça; tipo não é. SF Pro é o caso que mais passa batido: está
instalada em todo Mac e a licença da Apple não permite servi-la na web.
A base de licenças (scripts/fontes_licenca.json) vem com o plugin e não depende do
acervo.
MCPs que o cannonball usa
Nenhum é obrigatório — o motor funciona sozinho. Cada um fecha um buraco distinto, e
as skills só disparam a seção correspondente quando o MCP está ligado.
| MCP | Para quê | Livre | Com cota |
|---|---|---|---|
| GetLayers | composição (esqueleto de layout), background de vídeo, cena 3D nova — o que um acervo de código não tem por natureza | start, search, browse, compositions, palettes, fonts, source |
materialize; downloadProject = 3/dia |
| Motion Sites | catálogo de prompt de página inteira | list_prompts, search_prompts, get_related_prompts |
get_prompt = 3 na conta sem plano |
| OriginKit | componente gerado já na sua stack | list_components, search |
get_component |
| Higgsfield | imagem e vídeo do hero, quando o cliente não tem material | get_cost (preflight) |
generate_image, generate_video — crédito real |
Detalhes de cada um em references/. O Higgsfield é o único que gasta
dinheiro do usuário por chamada: higgsfield.md traz a
disciplina de custo, os modelos e o que a moderação reprova por engano.
O critério, não só as peças
O acervo responde "o que eu já tenho pra isso". Não responde "isso deveria
existir assim". references/fundamentos-visuais.md
cobre o segundo — o vocabulário que decide antes da peça e julga depois dela:
- as perguntas que substituem "está bonito?" — o que isso quer que eu sinta, que eu faça, e que decisões me levaram lá
- os cinco níveis — estética, organização, comunicação, persuasão, memória — e o teto de cada um
- seis níveis de movimento, nove tipos de contraste, cinco usos da cor, psicologia de forma
- seis técnicas de geração de conceito, para quando o briefing está pobre
- sete testes executáveis, todos de minutos e sem ferramenta
Os testes são a parte que mais rende, e estão ligados como passo 7.9 dakit-montar: o passo 8 registra o que quebrou; o 7.9 pega o que não quebra e
mesmo assim falha. O melhor deles inverte o instinto — cubra a mensagem
principal, veja o que sobrou roubando atenção, e reduza antes de apagar.
Comandos
python scripts/perfil.py # o retrato de agora
python scripts/buscar.py "landing de clínica odontológica"
python scripts/buscar.py --setor joias --estrutura scroll-cinematica
python scripts/buscar.py --listar setor
python scripts/ingerir.py <arquivo> --analisar # peça avulsa
python scripts/ingerir_projeto.py <pasta> --analisar # projeto inteiro
python scripts/ingerir_design.py <arquivo> --analisar # design system
python scripts/ingerir_registro.py --url <url>.json # componente de registro shadcn
python scripts/ingerir_mcp.py --catalogo <c>.json # catálogo servido por MCP
python scripts/lote.py <lote>.json --simular # muitos projetos de uma vez
python scripts/receita.py criar <slug> --pecas a,b,c # salvar uma composição
python scripts/capturar.py --tudo # preview das peças que rodam sozinhas
python scripts/capturar.py --url <url> --viewport 390x844 --saida <png>
python scripts/painel.py --abrir # o acervo com miniatura
python scripts/curar.py # saúde do acervo
python scripts/curar.py --assets # testa as URLs externas
python scripts/curar.py --autoteste # checa o detector de import
python scripts/publicar.py --autoteste # checa a rede anti-vazamento
python scripts/indexar.py # SEMPRE depois de ingerir ou editar ficha
indexar.py no fim não é opcional: os scripts gravam no disco, mas a busca lêacervo/index.json. Sem reindexar, nada muda.
O preview — o acervo deixou de ser só texto
Peça que roda sozinha ganha preview.png ao lado da ficha: família html, eanimacao/template com um index.html dentro.
python scripts/capturar.py --tudo && python scripts/indexar.py
python scripts/painel.py --abrir
Usa o Chrome que já está na máquina, em headless — sem Playwright, sem dependência
nova. Aponte outro binário com CANNONBALL_CHROME.
A captura é julgada antes de ser gravada. Um PNG válido não prova nada: canvas
WebGL que não inicializou, página que não carregou e loader que nunca saiu produzem
imagem perfeita e inútil. O script mede variação de cor e brilho, e recusa com o
motivo escrito. Recusa é informação, não erro.
Componente React solto fica de fora: precisaria de build. São 159 peças capturáveis
hoje, e as 130 animações são justamente onde "como é que isso fica?" mais dói.
O mesmo script serve à revisão do passo 7.9 da /kit-montar, apontado para a página
que você acabou de construir:
python scripts/capturar.py --url http://localhost:3000 --viewport 1440x900 --saida /tmp/d.png
python scripts/capturar.py --url http://localhost:3000 --viewport 390x844 --saida /tmp/m.png
Assets pesados ficam fora
Template e animação guardam só o código. Imagem, vídeo e fonte continuam no
projeto original — o campo projeto_origem diz onde, e curar.py verifica se o
caminho ainda existe. Num template típico 99% do peso é mídia, que não cabe no git e
é trocada por material do cliente de qualquer forma.
Se a pasta de material mudar de lugar:
python scripts/relocalizar.py --verificar
python scripts/relocalizar.py --assets-de "<raiz antiga>" --assets-para "<raiz nova>"
python scripts/indexar.py
Depois de editar scripts ou skills
O plugin instalado é uma cópia. Force a atualização:
claude plugin marketplace update cannonball
claude plugin uninstall cannonball@cannonball && claude plugin install cannonball@cannonball
Coisas que mordem
- A extensão mente. Arquivo
.mdcontendo TSX puro é comum. A classificação é
sempre por conteúdo, nunca por extensão. @/lib/utils(a funçãocn) não é pacote npm, é arquivo que precisa existir no
projeto. Quase todo componente de origem shadcn importa isso.- Componente de registro puxa outros. A busca imprime
PRECISA JUNTO:— colar sem
a base quebra o import, e o erro não diz que falta uma peça, diz que falta um módulo. motioneframer-motionsão a mesma lib com nomes diferentes. Misturar
instala duas vezes. Padronize emmotion, que é o sucessor.- Componente autorado em Framer convertido para Next.js deixa resíduo (shim
RenderTarget, JSDoc@framer*,props: any) e exige Tailwind v4. - A peça sai do acervo por cópia, e import relativo não sabe disso. Escrito para
o layout do acervo, ele quebra no destino comModule not found— que parece falta
de pacote npm e não falta de peça.curar.pytem uma seção só para isso e, quando
o alvo já está no acervo com outro id, imprime o de-para. - Asset em bucket temporário morre.
curar.py --assetstesta de verdade; a busca
avisaASSET MORTOna hora da escolha, não na entrega. - Fonte de
db.onlinewebfonts.comé redistribuição de fonte comercial. Verifique
a licença antes de entregar a cliente.
Publicar sua própria versão
O acervo é seu e não deve ir junto num repositório público — peça de terceiro,
projeto de cliente e prompt comprado não são seus para redistribuir.
python scripts/publicar.py --para ../cannonball-publico --listar
python scripts/publicar.py --para ../cannonball-publico
Exporta o motor (scripts, skills, referências) e o seed/ das três peças de exemplo,
e recusa a exportação se qualquer material privado escapar para o destino.
O que fica de fora: acervo/, _fonte/ e todo artefato de importação em massa.
Histórico
O que mudou em cada versão, e por quê: CHANGELOG.md.
Créditos
A disciplina de ficha da /kit-ingerir — mecanismo numa frase, três pilhas, regra
ancorada na falha que evita, números em vez de adjetivos — vem doweb-technique-to-skill do Meng To (MIT),
traduzida para o vocabulário do acervo. O repo dele é a metade oposta deste: acervo
curado de técnica de web design, sem motor de busca.
O §15 da /kit-otimizar-3d — depurar shader extraindo os valores internos como
pixel, em vez de mexer na constante até a imagem melhorar — vem doshader-debugging do vgpu da
vercel-labs (MIT). O vgpu é WebGPU/WGSL e não é dependência daqui: o que foi
trazido é o método, reescrito para WebGL2/GLSL, mais a correção que ele traz sobre
captura headless no Linux.
Licença
MIT — ver LICENSE. A licença cobre o motor. O que você guardar no
acervo continua sob a licença de origem de cada peça.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found
