PUBLICAÇÃO DA COMUNIDADE
Publicar skill no AI Skills
Empacota e publica skills no AI Skills (aiskills.bonorasw.com.br), no espaço /arthurbonora: monta skill.json + SKILL.md + LICENSE, valida contra o schema, publica via API com token, confere o resultado e sabe versionar, retirar versão e forkar. Use quando pedirem para publicar, subir, atualizar, versionar ou retirar uma skill no AI Skills / aiskills.bonorasw.com.br / no meu espaço.
arthurbonora/publicar-skill-aiskills · MIT · v1.0.0
Instruções da skill
---
name: publicar-skill-aiskills
description: "Empacota e publica skills no AI Skills (aiskills.bonorasw.com.br), no espaço /arthurbonora: monta skill.json + SKILL.md + LICENSE, valida contra o schema, publica via API com token, confere o resultado e sabe versionar, retirar versão e forkar. Use quando pedirem para publicar, subir, atualizar, versionar ou retirar uma skill no AI Skills / aiskills.bonorasw.com.br / no meu espaço."
---
# Publicar skill no AI Skills
Publica skills no catálogo **AI Skills** (`https://aiskills.bonorasw.com.br`), no espaço padrão **`/arthurbonora`**.
Cada skill é um repositório em `/{usuario}/{skill}/` com histórico de versões. **Versão publicada é imutável** — não existe sobrescrever, só publicar versão nova ou retirar.
Escreva em português do Brasil, direto.
## Antes de qualquer coisa
```bash
BASE=https://aiskills.bonorasw.com.br
[ -n "$AISKILLS_TOKEN" ] && echo "token presente" || echo "TOKEN AUSENTE"
```
O token vem da variável de ambiente `AISKILLS_TOKEN`, criada em `/account/` (aparece uma única vez, vale 90 dias, publica **somente no espaço do dono**). Se não existir, pare e peça ao usuário para gerar o token e exportá-lo — **nunca** peça a senha, nunca coloque o token na URL, em arquivo do pacote, em log ou no relatório.
Confira também se o identificador já existe no espaço:
```bash
curl -sS $BASE/api/v1/users/arthurbonora/skills
curl -sS $BASE/api/v1/users/arthurbonora/skills/<skill>/index.json
```
Se existir, a publicação é **atualização**: mantenha o `id` e aumente a `version`.
## Estrutura obrigatória do pacote
```
<identificador>/
skill.json
SKILL.md
LICENSE
references/ # opcional
scripts/ # opcional, distribuído como arquivo, nunca executado pelo servidor
assets/ # opcional
```
Identificador: minúsculas ASCII, números e hífens, sem hífen duplo, até 64 caracteres (`^[a-z0-9]+(?:-[a-z0-9]+)*$`).
### `skill.json` — campos todos obrigatórios
```json
{
"id": "minha-skill",
"name": "Nome legível",
"description": "O que faz e quando usar.",
"version": "1.0.0",
"author": "arthurbonora",
"license": "MIT",
"category": "desenvolvimento",
"tags": ["exemplo"],
"compatibility": ["agent-skills"],
"dependencies": [],
"permissions": [],
"changelog": "Primeira publicação."
}
```
Regras do schema (`/schemas/skill.schema.json`), validar **antes** de enviar:
- `description`: 10 a 1024 caracteres — e deve deixar claro **quando** usar a skill
- `version`: semver estrito `X.Y.Z`
- `category`: mesmo padrão de slug do `id`; use uma das já existentes no catálogo — `infraestrutura`, `desenvolvimento`, `produtividade`, `dados`
- `tags`: 1 a 12, únicas, até 40 caracteres cada
- `compatibility`: `["agent-skills"]`
- `dependencies` e `permissions`: listas de frases (até 30 itens); declare os requisitos **reais** (acesso a terminal, rede, credenciais de terceiros)
- `changelog`: obrigatório, até 2000 caracteres
- Nenhum campo extra é aceito (`additionalProperties: false`)
- `author` é sobrescrito pelo usuário autenticado no servidor
### `SKILL.md`
Frontmatter YAML com `name` **idêntico ao `id`** e `description` **idêntica à do `skill.json`**. Divergir nesses dois campos é a causa mais comum de `400`.
### `LICENSE`
Texto integral da licença declarada. Publique só o que o usuário tem direito de distribuir.
### Nunca inclua
Credenciais, `.env`, arquivos privados, diretórios ocultos, virtualenvs, links simbólicos.
## Validação local antes de publicar
```bash
python3 - <<'PY'
import json,re,sys,pathlib
d=pathlib.Path("<identificador>")
m=json.loads((d/"skill.json").read_text())
req=["id","name","description","version","author","license","category",
"tags","compatibility","dependencies","permissions","changelog"]
err=[f"faltando: {k}" for k in req if k not in m]
if not re.fullmatch(r"[a-z0-9]+(-[a-z0-9]+)*", m.get("id","")): err.append("id inválido")
if not re.fullmatch(r"(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)", m.get("version","")): err.append("version inválida")
if not 10 <= len(m.get("description","")) <= 1024: err.append("description fora de 10..1024")
txt=(d/"SKILL.md").read_text()
fm=txt.split("---")[1] if txt.startswith("---") else ""
if f"name: {m['id']}" not in fm: err.append("frontmatter name != id")
if m["description"] not in fm: err.append("frontmatter description != skill.json")
if not (d/"LICENSE").exists(): err.append("LICENSE ausente")
print("\n".join(err) or "OK")
PY
```
Confira também os limites: **2 MiB** de conteúdo por pacote, 100 arquivos, 100 versões por repositório, 50 repositórios e 100 MiB por usuário, 30 publicações por hora.
## Publicar
### ZIP (recomendado; obrigatório se houver binário)
O ZIP precisa conter a **pasta** `<identificador>/` na raiz.
```bash
zip -r <identificador>.zip <identificador> -x '*/.*' '*/__pycache__/*'
curl --fail-with-body -sS \
-H "Authorization: Bearer $AISKILLS_TOKEN" \
-F "package=@<identificador>.zip" \
$BASE/api/v1/skills/publish
```
### JSON (só texto UTF-8)
```bash
curl --fail-with-body -sS \
-H "Authorization: Bearer $AISKILLS_TOKEN" \
-H "Content-Type: application/json" \
--data @payload.json \
$BASE/api/v1/skills/publish
```
`payload.json`: `{ "metadata": {...}, "skill_md": "...", "license_text": "...", "files": {"references/x.md": "..."} }`
Para publicar numa versão de repositório específico (exige ser dono):
`POST /api/v1/users/arthurbonora/skills/<skill>/versions`
## Depois de publicar
`201` devolve `owner`, `namespace`, `page_url`, `manifest_url`, `download_url`, `skill_url` e checksum (links relativos à raiz do site). Confirme e só então reporte sucesso:
```bash
curl -sS $BASE/api/v1/users/arthurbonora/skills/<skill>/index.json
curl -sSI $BASE/api/v1/users/arthurbonora/skills/<skill>/versions/<versao>/download.zip
```
Entregue ao usuário: a URL da página `/arthurbonora/<skill>/`, a versão publicada e o checksum.
## Erros
| Código | Significado | O que fazer |
| --- | --- | --- |
| 400 | pacote inválido | reveja schema, frontmatter e estrutura de pastas |
| 401 | token ausente/inválido | token expirado (90 dias) — peça um novo em `/account/` |
| 403 | sem permissão / CSRF | só dá para publicar no próprio espaço |
| 409 | versão já existe | aumente a `version`; nunca tente sobrescrever |
| 413 | corpo grande demais | 2 MiB de conteúdo, 4 MiB de corpo HTTP |
| 429 | limite de taxa | espere; o limite é 30 publicações/hora |
Nunca contorne um erro removendo validação ou reenviando em loop: leia o corpo da resposta (`--fail-with-body` já imprime) e corrija a causa.
## Atualizar uma versão
Mesmo `id`, `version` maior, `changelog` descrevendo o que mudou. Patch para correção de texto, minor para novos checks ou recursos, major para mudança incompatível de comportamento.
## Retirar uma versão
Só com pedido explícito do usuário e com motivo concreto — o pacote histórico continua acessível e continua contando para o armazenamento.
```bash
curl --fail-with-body -sS -X POST \
-H "Authorization: Bearer $AISKILLS_TOKEN" -H "Content-Type: application/json" \
-d '{"reason":"<motivo concreto>"}' \
$BASE/api/v1/users/arthurbonora/skills/<skill>/versions/<versao>/withdraw
```
## Fork para o próprio espaço
```bash
curl --fail-with-body -sS -X POST \
-H "Authorization: Bearer $AISKILLS_TOKEN" -H "Content-Type: application/json" \
-d '{"kind":"community","owner":"alice","slug":"minha-skill","version":"1.0.0"}' \
$BASE/api/v1/skills/fork
```
Para skill do catálogo curado: `"kind":"curated"` com `"owner":""`. O fork cria repositório novo e histórico independente; identificador já existente no espaço retorna conflito.
## Cuidados
- Publicação da comunidade passa só por validação automática de formato — **não** é revisão humana nem auditoria de segurança. Revise o conteúdo antes de subir.
- O nome de usuário é público e permanente; o conteúdo publicado é público.
- Confirme com o usuário antes de publicar, retirar ou forkar — são ações públicas e, no caso da publicação, irreversíveis.
- Prefira token a login por senha. O fluxo de sessão (`/api/v1/auth/session` → `/api/v1/auth/login` com `X-CSRFToken`) existe, mas não é para agente.Requisitos
- Acesso de rede HTTPS a aiskills.bonorasw.com.br.
- curl, zip e python3 disponíveis no ambiente do agente.
Permissões declaradas
- Leitura do token de publicação na variável de ambiente AISKILLS_TOKEN.
- Leitura dos arquivos da skill a ser empacotada.
- Envio de requisições HTTP autenticadas para a API do AI Skills.
Avaliações
Carregando…Versões
- v1.0.0
Primeira publicação.