Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"name": "agent-fleet",
"source": "./plugins/agent-fleet"
},
{
"name": "agents-md",
"source": "./plugins/agents-md"
},
{
"name": "crew",
"source": "./plugins/crew"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Or paste `4nrry/agent-plugins` into the Claude Desktop **Add marketplace** dialo
| Plugin | What it is |
|---|---|
| [agent-fleet](plugins/agent-fleet/) | Rules for multi-agent work — model routing per phase, fan-out sizing, output schemas, and citation verification. Two hooks, because the prose alone measurably did not fire. |
| [agents-md](plugins/agents-md/) | Write, slim and audit a repo's AGENTS.md: what goes in, what comes out, per-tool limits (Claude Code, Antigravity, Codex), and a stdlib checker for missing scripts, dead paths, oversize files and the CLAUDE.md that hides AGENTS.md from Claude Code. |
| [crew](plugins/crew/) | Cheap headless workers through three agent CLIs, without fighting Claude's harness: Claude writes the task, sets scope and gate, and reviews the diff; the worker runs one slice under its own CLI's hooks, installed for the run only. Backends: agy (Antigravity CLI, Gemini; default), opencode (free Zen models, weaker shell guard) and GitHub Copilot CLI (Free plan: `--model auto` only, paid in AI credits, no shell). The verdict never reads exit 0 as success — in agy 1.3.4 timeouts, denied actions and an unmet `--json-schema` all exit 0 (observed, n=1 each). One skill per backend plus a shared delegation doc, injected by a UserPromptSubmit hook when the prompt names the CLI, and a watcher that ends the background commands agy would otherwise wait 30 min for. |
| [game-facts](plugins/game-facts/) | Pins the installed game's version before the agent answers from training memory. A UserPromptSubmit hook reads Steam appmanifests and injects appid, buildid and update date — so the version never has to be typed into the prompt. |
| [homelab](plugins/homelab/) | Software you maintain yourself on a Linux box, where the official docs stop. A Palworld dedicated server (the config the server erases on shutdown), WireGuard through NetworkManager (the IPv6 leak that passes the IP test), and tarball installs (one versioned layout, and why a self-updating app must not live in /opt). Machine state stays out of the repo. |
Expand Down
11 changes: 11 additions & 0 deletions plugins/agents-md/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "agents-md",
"displayName": "AGENTS.md",
"version": "0.1.0",
"author": {
"name": "4nrry",
"url": "https://github.com/4nrry"
},
"license": "MIT",
"description": "Escrever, enxugar e auditar o AGENTS.md de um repositorio: o que entra (comando que existe, como provar que terminou, armadilha que falha em silencio, contrato com outro repo), o que sai (arvore, lista derivavel, historia, grito em caixa alta), e onde cada coisa mora quando nao cabe. Junta as regras das docs do Claude Code, do Antigravity, do Codex e do agents.md numa tabela de limites — inclusive as duas armadilhas que mais custaram aqui: um CLAUDE.md na pasta esconde o AGENTS.md do Claude Code, e o Antigravity nao le CLAUDE.md nem expande '@arquivo' solto. Traz um checador mecanico (stdlib, --self-test) que pega comando inexistente, caminho citado que nao existe, arquivo acima do teto e CLAUDE.md que sombreia, antes de gastar agente. Sem alegacao de melhoria: nao ha run records; a origem e uma auditoria de 19 repos em que verificadores baratos acharam 11 afirmacoes falsas em 16 rascunhos ja revisados."
}
27 changes: 27 additions & 0 deletions plugins/agents-md/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# AGENTS.md

Arquivo de instrucoes de agente cresce, envelhece e para de ser seguido. Numa
auditoria de 19 repositorios, os arquivos tinham ate 974 linhas, um deles
estava 159 commits atrasado em relacao ao codigo, e sete eram invisiveis para o
Antigravity porque viviam em `CLAUDE.md`. Este plugin e o checklist que saiu
dessa limpeza, mais um checador que pega o erro barato sem gastar agente.

## Componentes

| componente | o que faz |
|---|---|
| `skills/agents-md/` | O que entra, o que sai, forma, limites por ferramenta, como auditar barato e como manter. |
| `scripts/check_agents_md.py` | Checagem mecanica de um repo: teto de tamanho, `npm run` inexistente, caminho citado que nao existe, grito, `CLAUDE.md` que esconde o `AGENTS.md`, `GEMINI.md` com `@arquivo` que o Antigravity nao expande. `--self-test`. Sai 1 quando aponta algo. |

## O que o checador nao sabe

Caminho citado relativo a outro repo (contrato do backend vizinho, por exemplo)
aparece como inexistente: e falso positivo esperado, confira antes de mexer.
Fila, porta, env var e nome de modulo ficam fora do alcance de um regex; para
esses, a skill descreve um verificador barato por arquivo.

## O que isto nao estabelece

Nao ha run records. Os numeros acima sao da auditoria que originou o plugin,
nao de uma comparacao com e sem a skill; pela regra do `bench/PROTOCOL.md`,
isso proibe qualquer alegacao de melhoria.
102 changes: 102 additions & 0 deletions plugins/agents-md/scripts/check_agents_md.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env python3
"""Mechanical checks for a repo's agent-instruction files. No model, no network.

Usage: check_agents_md.py <repo-dir> exit 1 when anything is flagged
check_agents_md.py --self-test
"""
import json
import pathlib
import re
import sys
import tempfile

MAX_LINES, MAX_BYTES = 150, 10_000
ANTIGRAVITY_FILE_CAP = 24_000
SHOUT = re.compile(r"\b(CRITICAL|ALWAYS USE FIRST|YOU MUST|NEVER EVER)\b")
NPM_RUN = re.compile(r"\b(?:npm run|pnpm run|yarn run|bun run)\s+([a-z][\w:.-]*)")
TICKED_PATH = re.compile(r"`([\w./-]+/[\w.-]+\.[a-z]{1,6})`")
BARE_IMPORT = re.compile(r"^\s*@(?!\[)([\w./-]+)\s*$", re.M)


def check(repo: pathlib.Path) -> list[str]:
out = []
agents = repo / "AGENTS.md"
for shadow in ("CLAUDE.md", ".claude/CLAUDE.md", "CLAUDE.local.md"):
p = repo / shadow
if agents.exists() and p.exists() and "@AGENTS.md" not in p.read_text(encoding="utf-8"):
out.append(f"{shadow}: exists, so Claude Code skips AGENTS.md (no @AGENTS.md import)")
gem = repo / "GEMINI.md"
if gem.exists():
for m in BARE_IMPORT.finditer(gem.read_text(encoding="utf-8")):
out.append(f"GEMINI.md: '@{m.group(1)}' is not inlined by Antigravity (only @[label](path) is)")
pkg = repo / "package.json"
scripts = set()
if pkg.exists():
try:
scripts = set(json.loads(pkg.read_text(encoding="utf-8")).get("scripts", {}))
except ValueError:
out.append("package.json: does not parse")
files = [agents] + sorted((repo / "docs" / "agents").glob("*.md"))
for f in files:
if not f.exists():
continue
text = f.read_text(encoding="utf-8")
name = f.relative_to(repo).as_posix()
lines, size = text.count("\n") + (not text.endswith("\n") and bool(text)), len(text.encode())
if f == agents and (lines > MAX_LINES or size > MAX_BYTES):
out.append(f"{name}: {lines} lines / {size} bytes (cap {MAX_LINES} / {MAX_BYTES})")
if size > ANTIGRAVITY_FILE_CAP:
out.append(f"{name}: over {ANTIGRAVITY_FILE_CAP} bytes, Antigravity truncates it")
for s in sorted(set(NPM_RUN.findall(text))):
if pkg.exists() and s not in scripts:
out.append(f"{name}: `npm run {s}` but package.json has no script '{s}'")
for p in sorted(set(TICKED_PATH.findall(text))):
if "<" in p or "*" in p:
continue
if not (repo / p).exists() and not (f.parent / p).exists():
out.append(f"{name}: cites `{p}`, which does not exist")
for n, line in enumerate(text.splitlines(), 1):
if SHOUT.search(line):
out.append(f"{name}:{n}: shouting ({SHOUT.search(line).group(1)})")
return out


def self_test() -> int:
with tempfile.TemporaryDirectory() as d:
r = pathlib.Path(d)
(r / "src").mkdir()
(r / "src/main.ts").write_text("")
(r / "package.json").write_text('{"scripts": {"test": "jest"}}')
(r / "AGENTS.md").write_text("Run `npm run test`.\nSee `src/main.ts` and `src/gone.ts`.\nCRITICAL: x\n")
(r / "CLAUDE.md").write_text("old stuff\n")
(r / "GEMINI.md").write_text("@CLAUDE.md\n")
got = check(r)
want = ["CLAUDE.md: exists", "GEMINI.md: '@CLAUDE.md'", "cites `src/gone.ts`", "AGENTS.md:3: shouting"]
miss = [w for w in want if not any(w in g for g in got)]
bad = [g for g in got if "main.ts" in g or "npm run test" in g]
(r / "AGENTS.md").write_text("Run `npm run build`.\n")
(r / "CLAUDE.md").write_text("@AGENTS.md\n")
second = check(r)
if miss or bad or not any("'build'" in g for g in second) or any(g.startswith("CLAUDE.md") for g in second):
print("self-test FAILED", miss, bad, got, second)
return 1
print("self-test ok")
return 0


def main(argv: list[str]) -> int:
if argv[1:] == ["--self-test"]:
return self_test()
if len(argv) != 2 or not pathlib.Path(argv[1]).is_dir():
print(__doc__.strip())
return 2
found = check(pathlib.Path(argv[1]))
for line in found:
print(line)
if not found:
print("ok")
return 1 if found else 0


if __name__ == "__main__":
sys.exit(main(sys.argv))
109 changes: 109 additions & 0 deletions plugins/agents-md/skills/agents-md/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
name: agents-md
description: Escrever, enxugar ou auditar o AGENTS.md (ou CLAUDE.md, GEMINI.md) de um repositorio — o que entra, o que sai, tamanho, onde cada coisa mora, e como checar que o arquivo nao mente sobre o codigo. Cobre os limites de cada ferramenta (Claude Code, Antigravity, Codex), o CLAUDE.md que esconde o AGENTS.md, e um checador mecanico que pega comando inexistente, ponteiro quebrado e arquivo grande demais sem gastar agente. Use quando a tarefa mencionar AGENTS.md, CLAUDE.md, GEMINI.md, .cursorrules, instrucoes do agente, "rules token budget", arquivo de instrucoes desatualizado ou gigante, ou /init.
---

# AGENTS.md que o agente segue

Arquivo de instrucoes e contexto carregado em toda sessao. Cada linha custa
token em toda tarefa, e arquivo inchado faz o agente ignorar justamente a
regra que importa. O teste de toda linha: **se eu tirar isto, o agente erra?**
Se nao erra, sai.

## Entra

- Comandos exatos e que existem: instalar, rodar, o teste mais estreito,
lint/typecheck, migration. Agente roda o check que estiver listado.
- Como provar que terminou: o comando que da passou/falhou. Sem ele, "parece
pronto" e o unico sinal que o agente tem.
- Armadilhas que falham em silencio: o comando que passa sem testar nada, a env
var sem a qual tudo sobe errado, a config que precisa de restart.
- Contratos com outros repos que daqui nao se deduzem: fila/routing key,
header, formato de ID, porta exposta.
- Convencoes que fogem do padrao da linguagem ou do framework.
- Etiqueta do repo: branch base, nome de branch, squash ou nao, o que rodar
antes de commitar.
- Decisao de arquitetura com o porque, so quando o codigo nao explica sozinho.
- Mapa curto: onde moram as 3 a 5 coisas que se procuram toda hora.
- Ponteiro com gatilho para o que mora em outro arquivo: "antes de mexer em
X, leia `<subpasta>/AGENTS.md`" ou o `AGENTS.md` comum acima dos repos.

## Sai

- Arvore de diretorios, lista de endpoints, dump de schema, lista de
dependencias, descricao arquivo por arquivo. O agente le o codigo.
- Tutorial e documentacao de API: link, nao copia.
- O que muda toda hora: versao, contagem, "ultima atualizacao", estado de
sprint. E o primeiro trecho a ficar velho.
- Conselho obvio ("escreva codigo limpo", "use tipos").
- Changelog e historia de ticket: o git guarda.
- Instrucao de uma ferramenta so ("use o MCP X primeiro").
- Segredo, URL com token, dado de cliente.

## Forma

- Bullets curtos sob cabecalhos. Paragrafo denso e seguido pior.
- Concreto e verificavel: "rode `npm test -- foo`", nao "teste suas mudancas".
- Tom calmo, com o motivo. `IMPORTANT` em no maximo uma linha; se tudo grita,
nada se destaca, e modelos atuais aplicam frase agressiva demais.
- Duas instrucoes que se contradizem fazem o agente escolher no chute: revise o
arquivo da raiz contra os aninhados.
- Nota so para humanos vai em `<!-- comentario -->` de bloco: o Claude Code a
remove antes de carregar.

## Tamanho e onde mora

| ferramenta | o que le | limite |
|---|---|---|
| Claude Code | `CLAUDE.md`; `AGENTS.md` nativo desde 2.1.277, **so se nao houver `CLAUDE.md` nem `CLAUDE.local.md` na pasta ou acima** | recomenda < 200 linhas; carrega ate 4 MiB |
| Antigravity | `AGENTS.md`, `GEMINI.md`, `.agents/rules/`; **nao le `CLAUDE.md`**; `@arquivo` solto nao e inlinado, so `@[label](path)` | 24 KB por arquivo (corta o resto); 20 mil tokens somando tudo que esta always-on |
| Codex | `AGENTS.override.md` ou `AGENTS.md`, da raiz do git ate o cwd | para de juntar em 32 KiB somados |

- Meta: 60 a 100 linhas e menos de 6 KB. Teto: 150 linhas / 10 KB.
- `@import` nao economiza: o importado tambem carrega no inicio.
- Um arquivo so, `AGENTS.md`, para todas as ferramentas. Um `CLAUDE.md` ou
`CLAUDE.local.md` na mesma pasta ou acima esconde o `AGENTS.md` do Claude.
- O que vale para parte do codigo vai para um `AGENTS.md` aninhado na
subpasta (o mais proximo vence). Doc solto em `docs/` so se alguem o audita:
doc velho engana o agente que o le, e ninguem o confere contra o codigo.
- Procedimento de varios passos vira skill. Regra que nao pode falhar nunca
vira hook: o arquivo e orientacao, o hook e garantia.
- Arquivo global: o Claude Code le so `~/.claude/CLAUDE.md` (nao ha
`AGENTS.md` de usuario); o Antigravity le `~/.gemini/config/AGENTS.md` (ou
`GEMINI.md`). Sao dois arquivos: mantenha um e gere o outro a partir dele.
- O Claude Code procura `AGENTS.md` em todas as pastas acima do cwd; o
Antigravity e o Codex param na raiz do git. Um `AGENTS.md` comum acima dos
repos so chega a eles por ponteiro no `AGENTS.md` de cada repo.
- Workspace com varios repos abertos soma os arquivos de todos no Antigravity.
Abra o repo da tarefa, nao a pasta-mae, antes de cortar arquivo bom.

## Auditar sem torrar uso

1. Checagem mecanica primeiro, de graca:

```bash
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/check_agents_md.py" <repo>
```

Aponta: arquivo acima do teto, `npm run X` que nao existe no
`package.json`, caminho citado em crase que nao existe, palavras de grito,
`CLAUDE.md`/`CLAUDE.local.md` que escondem o `AGENTS.md`, `GEMINI.md` com
`@arquivo` que o Antigravity nao expande. Caminho relativo curto pode dar
falso positivo: confira antes de mexer.
2. Audite contra o codigo da branch padrao do origin, nao o checkout local
(que costuma estar atrasado): `git archive origin/<padrao> | tar -x -C <dir>`.
3. Para fatos que o script nao alcanca (fila, porta, env var, nome de modulo),
um agente barato (Haiku) por arquivo, que devolve **so** as afirmacoes
falsas com `path:linha`. Confira cada apontamento antes de aplicar: o
verificador acerta muito, mas nao sempre.
4. No Claude Code, `/doctor` sugere cortes e `/doctor prompt-audit` acha
comando inexistente e contradicao entre arquivos.

## Manter

- Revise no PR que muda comando, porta, fila ou layout. Arquivo velho e pior
que arquivo nenhum: o agente acredita nele.
- Acrescente uma linha quando o agente repete um erro, quando o review pega
algo que ele deveria saber, ou quando voce digita a mesma correcao de novo.
- Mudou uma regra? Veja se o comportamento mudou. Se o agente continua
ignorando, o arquivo esta longo demais ou a frase esta ambigua.
Loading