Communitygithub.com

MBehtemam/montagent-skills

Traga visuais gerados por código, animações Lottie, cenas 3D ou vídeo-fonte estabilizado para o Montagent como filmagens sem perdas, ou um SVG estático como um PNG, cada um com uma receita de reconstrução. Carregue para uma aparência fora da lista de efeitos, entrada de visuais generativos, SVG, Lottie ou modelo 3D, ou estabilização de vídeo-fonte, travamento de quadro de referência, ping-pong e câmera lenta.

O que é montagent-skills?

Esta skill do Montagent, descrita no SKILL.md, oferece cinco rotas para pré-renderizar conteúdo gerado externamente e integrá-lo como filmagens ou imagens estáticas no projeto, tudo fora do pipeline de renderização principal. As rotas são: 'code-drawn piece', para visuais gerados por código; 'SVG route', para imagens SVG estáticas convertidas em PNG; 'Lottie route', para animações Lottie; '3D scene route', para cenas 3D (como modelos .glb); e 'stabilize route', para estabilizar vídeos fonte. A skill é útil porque o Montagent não aceita shaders ou scripts diretamente (ADR-0017), nem arquivos SVG, Lottie ou modelos 3D como fontes nativas (ADRs-0171, 0167, 0233). Para contornar isso, cada rota especifica um processo de 'build spec' que descreve como gerar os quadros, codificá-los em um arquivo de filme (MOV) ou PNG (com codec ProRes 4444 para transparência), e colocá-los como elementos `video` ou `image` comuns no projeto, com suporte a receitas de reconstrução para verificar a integridade dos dados. A skill é compatível com qualquer ferramenta de desenho ou rasterização (como resvg, ThorVG) e enfatiza regras comuns de tamanho, fontes e receitas para garantir resultados consistentes.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MBehtemam/montagent-skills/tree/HEAD/skills/montagent-prerender

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Pré-renderizar: visuais gerados e filmagens estabilizadas

Cinco rotas, um conjunto de regras comuns. Uma peça desenhada por código torna-se filmagem, colocada como um video: leia-a primeiro. Um SVG estático torna-se um PNG, colocado como uma image: pule para a rota SVG. Uma animação Lottie torna-se filmagem também, desenhada com um player novo por quadro: pule para a rota Lottie. Uma cena 3D torna-se filmagem transparente ou um PNG estático: pule para a rota de cena 3D. A estabilização de vídeo-fonte cria um novo clipe: pule para a rota de estabilização. Tudo executa fora da renderização, então cada pintor decodifica os mesmos pixels.

O Montagent não possui arquivo de shader ou script (ADR-0017). Uma aparência fora da lista de effects é desenhada em seu próprio código, codificada uma vez como filmagem e colocada como um video comum. O formato, o esquema e o pintor permanecem como estão (ADR-0156 §7, ADR-0233).

Quando usar

Use a rota nomeada primeiro. Leia a lista effects em montagent://schema/index.json: quando um membro compõe a aparência (desfoque, sombra, matiz, um blend, uma mask com chave), use-o. Pré-renderize apenas quando nenhum membro, pintura ou blend compõe a aparência: distorções, mosaico, flare de lente, partículas, um padrão procedural ou um modelo/cena 3D externo.

Use a rota SVG quando receber um desenho vetorial (um logotipo, um ícone, uma ilustração) como arquivo SVG, ou quando uma imagem estática for mais fácil de desenhar como SVG. Nenhum elemento aceita um arquivo SVG (ADR-0171). Um SVG que anima (SMIL ou CSS) não é desta rota: ele rasteriza como um único quadro estático e o movimento é perdido. Em vez disso, anime a própria scale, rotation e opacity da imagem colocada.

Use a rota de cena 3D quando receber um ativo 3D (.glb, .gltf, .obj, .fbx, .blend, .c4d) ou uma cena 3D. Nenhum elemento aceita um modelo 3D ou passagem multicanal (ADR-0167, ADR-0233). A renderização headless produz filmagens ProRes 4444 / PNG transparentes fora da renderização, prontas para colocação direta em 2D.

Use a rota Lottie quando receber um arquivo JSON Lottie (uma exportação do After Effects, uma animação do LottieFiles), ou quando um movimento for mais fácil de obter de um. Nenhum elemento aceita um arquivo Lottie (ADR-0171). Isso custa três coisas. Uma resolução fixa: a filmagem é raster no tamanho em que você a renderiza. Uma cadeia de ferramentas de receita: um player Lottie instalado para reproduzir a peça (nunca para renderizar o projeto). Tamanho da filmagem: PNG em um MOV varia de cerca de 6 MB por segundo para arte suave a 141 MB por segundo para arte ruidosa, a 1080p e 25 fps, então renderize no tamanho exibido e não maior. Se o movimento for de algumas formas, animar elementos nativos rect, ellipse e path é menor e permanece nítido.

Uma peça pré-renderizada é filmagem fixa. Seu tamanho, fps e duração são definidos quando você a renderiza. Mudar a aparência significa renderizar novamente, então defina primeiro o tamanho, fps e duração do briefing e corresponda ao fps do projeto.

Regras comuns

Cada rota lê estas. Elas são escritas uma vez.

  • Tamanho. Rasterize ou desenhe no maior tamanho que a peça é exibida, após fit, scale e qualquer zoom com chave, como uma width e height literais de pixel. Nunca derive de um viewBox do SVG: um viewBox define as proporções do desenho, não seus pixels, e as ferramentas discordam sobre um arquivo sem ele. Escreva o tamanho na receita. Um zoom posterior além disso reamostra um raster, então execute a receita novamente em um tamanho maior em vez de aumentar.
  • Texto. Apenas fontes vendidas (vendored) ou texto convertido em contornos. Nunca uma fonte do sistema: uma máquina sem ela desenha algo diferente. Uma fonte que não pode ser encontrada é uma falha de construção, não um span ignorado. usvg, por exemplo, registra a falta e pula o texto, então build lê os valores font-family do SVG em relação aos arquivos de fonte que você lista em fonts, e falha no próprio aviso de fonte do rasterizador também.
  • Receita. Cópia da fonte, comandos exatos, versões das ferramentas, tamanho e um hash dos pixels decodificados, obtido através da mesma leitura que o decodificador usa. A reconstrução relata uma correspondência ou a primeira diferença, e nunca compara bytes de arquivo. A receita diz onde ela reside.

Os passos

Execute cada passo, em ordem. A peça está colocada quando o passo 5 passar.

  1. Desenhe. Escreva código, em qualquer ferramenta, que produza quadros RGBA de uma contagem fixa width, height e frames: transparente onde nada é desenhado. Ele escreve RGBA bruto no stdout, ou arquivos PNG f00000.png, f00001.png e assim por diante na pasta nomeada por PRERENDER_FRAMES_DIR. Leia seu tamanho de PRERENDER_WIDTH, PRERENDER_HEIGHT, PRERENDER_FPS e PRERENDER_FRAMES. Use aritmética inteira ou uma semente fixa, para que uma segunda execução desenhe os mesmos bytes. A peça de exemplo é a menor funcional.
  2. Especificação. Escreva uma especificação de construção ao lado do código: name, out (a pasta de mídia do projeto), width, height, fps, frames, render (o argv que executa seu código), files (todos os arquivos que o código precisa) e input de "png" quando ele escrever PNGs. Execute python3 scripts/prerender.py --help para cada chave. Adicione versions para qualquer biblioteca cuja versão mude os pixels (uma biblioteca de canvas, um navegador headless).
  3. Construa. python3 scripts/prerender.py build <spec>. Ele executa o código, codifica um <name>.mov, o decodifica e falha no primeiro quadro que difere do que seu código desenhou. Leia sua última linha: N frames, decoded = drawn.
  4. Coloque. Adicione a filmagem ao projeto como um elemento video simples (abaixo) ou execute python3 scripts/prerender.py place <project> <placing>, onde <placing> é um arquivo JSON {"source": "media/<name>.mov"} mais qualquer um de id, at, x, y, origin, width, height, fit, track, layer. Ele imprime o projeto com o elemento adicionado, então redirecione isso para um novo arquivo.
  5. Verifique. validate o projeto e corrija cada erro. Em seguida, montagent probe a filmagem e confirme que ela relata alpha (carries: true). Só então frame um tile onde a peça está e verifique se as partes transparentes mostram o que está atrás.
{
  "frame": {"width": 640, "height": 360}, "fps": 25, "background": "#101418", "duration": 480, "output": "out/pulse.mp4",
  "tracks": [
    {"name": "prerender", "layer": 10, "elements": [
      {"id": "pulse", "type": "video", "start": 0, "end": 480, "source": "media/pulse.mov", "source_start": 0, "source_end": 480, "volume": 0, "x": 320, "y": 180, "origin": "center", "width": 320, "height": 240, "fit": "contain"}
    ]}
  ]
}

O elemento é um video comum: anime opacity, scale e position, adicione effects e um blend, e coloque-o em uma faixa como qualquer clipe. A filmagem não tem som, então volume é 0. Seu end menos start é a duração da filmagem; source_end é a mesma duração.

A rota SVG

Entrada: um arquivo SVG e o tamanho em pixels das regras comuns.

  1. Venda as fontes que o texto do SVG usa, com montagent fonts vendor, e defina cada <text> nessa família com um atributo font-family. Ou converta o texto em contornos em sua ferramenta de desenho e não use nenhuma fonte.
  2. Especificação. Escreva uma especificação de construção ao lado do SVG com "input": "svg": name, out, svg, a width e height literais, render (o argv do rasterizador, com {width}, {height} e {out} onde eles vão), files, fonts e versions. Não há fps nem contagem de quadros.
  3. Rasterize. python3 scripts/prerender.py build <spec> executa o rasterizador uma vez, fora da renderização. Qualquer ferramenta que escreva um PNG RGBA serve: a linha de comando resvg, um navegador headless, Inkscape. Pule fontes do sistema e entregue as vendidas, como na especificação abaixo. Ele escreve <name>.png e sua receita, e falha em uma fonte ausente.
  4. Coloque o PNG como um elemento image simples (abaixo) ou execute python3 scripts/prerender.py place <project> <placing> com {"source": "media/<name>.png", "duration": <ms>} mais qualquer um de id, at, x, y, origin, width, height, fit, track, layer.
  5. Verifique. Execute validate e corrija cada erro, então frame um tile onde a imagem está e verifique se as partes transparentes mostram o que está atrás.

A especificação de exemplo, para o SVG de exemplo (formas, um gradiente e texto definido em uma fonte vendida), rasterizado em três vezes seu viewBox:

{
  "name": "mark", "out": "media", "input": "svg", "svg": "sample_art.svg", "width": 480, "height": 270,
  "render": ["resvg", "--skip-system-fonts", "--use-font-file", "Inter-Bold.ttf", "-w", "{width}", "-h", "{height}", "sample_art.svg", "{out}"],
  "files": ["sample_art.svg"], "fonts": ["Inter-Bold.ttf"],
  "versions": {"resvg": ["resvg", "--version"]}
}

O PNG tem dimensões de pixel intrínsecas, então ele entra como uma image comum, e as regras fit de ADR-0015 se aplicam como para qualquer PNG: contain com a própria proporção da caixa, ou literal. Colocá-lo em seu próprio tamanho, com fit de contain, é um desenho 1:1. Mostrá-lo maior do que o tamanho que você rasterizou e o raster é reamostrado: execute a receita novamente no tamanho maior.

{
  "frame": {"width": 640, "height": 360}, "fps": 25, "background": "#101418", "duration": 2000, "output": "out/mark.mp4",
  "tracks": [
    {"name": "art", "layer": 10, "elements": [
      {"id": "mark", "type": "image", "start": 0, "end": 2000, "source": "media/mark.png", "x": 320, "y": 180, "origin": "center", "width": 480, "height": 270, "fit": "contain"}
    ]}
  ]
}

Execute validate. A imagem é uma comum: anime opacity, scale e position, adicione effects, coloque-a em uma faixa.

A rota Lottie

Entrada: um arquivo JSON Lottie, um tamanho, um fps e um intervalo de quadros. Os próprios w, h e fr do Lottie são entradas para escolher, não regras: o tamanho segue as regras comuns (o maior tamanho mostrado, como literais) e você escreve o fps e a contagem de quadros na especificação.

  1. Escolha um player que possa escrever quadros RGBA e registre seu nome e versão em versions. A skill não escolhe um: a pré-renderização executa uma vez fora da renderização e os pintores nunca veem o player. O player de exemplo é ThorVG através de pip install thorvg-python==1.1.3.
  2. Especificação. Escreva uma especificação de construção ao lado do Lottie com "input": "lottie": name, out, lottie, a width e height literais, fps, frames, render, files, fonts e versions. render é o argv do player, com {width}, {height}, {frame} e {out} onde eles vão: ele desenha um quadro como RGBA bruto em {out}. start e step opcionais definem qual quadro do Lottie cada quadro da filmagem é (quadro i é start + i * step; step padrão é o fr do Lottie dividido por fps). Execute python3 scripts/prerender.py --help para cada chave.
  3. Construa. python3 scripts/prerender.py build <spec> primeiro lê o Lottie e o recusa, nomeando cada caso, se ele usar uma expressão, um efeito de camada que o player não está registrado como desenhando (liste aqueles que estão em allow_effects), ou texto cuja fonte não tem nem caminhos de glifo incorporados nem um arquivo vendido em fonts. Um player descarta todos estes sem som, então uma construção que continuasse enviaria uma animação diferente. Em seguida, executa render uma vez por quadro, um novo processo cada vez, lê o próprio relatório do player sobre o que ele pulou (qualquer linha dizendo skipped, ignored ou unsupported é uma falha de construção: trate-a como tal), codifica um <name>.mov como o codec diz, e falha no primeiro quadro que difere do que o player desenhou.
  4. Coloque a filmagem como um elemento video simples, ou com place como em os passos. Execute validate e montagent probe o MOV: confirme que ele relata alpha (carries: true). Em seguida, frame um tile onde a peça está e verifique se as partes transparentes mostram o que está atrás.

Por que um player novo por quadro. O harness nunca avança um player. ThorVG ignora uma mudança de quadro abaixo de 0.001, então onde um seek termina depende do seek anterior, e o seek do Skottie modifica seu objeto de animação. Um quadro desenhado após outros pode diferir do mesmo quadro desenhado primeiro, e a reconstrução não corresponderia.

O codec

Um MOV com codec ProRes 4444, que carrega um canal alfa sem perdas e é decodificado quadro a quadro sem dependência de quadro futuro. Nenhum outro codec e nenhum contêiner diferente de .mov. Especifique em scripts/prerender.py como --codec prores_4444. Os pintores decodificam um quadro como RGBA, então o hash da reconstrução é tomado sobre esses bytes decodificados, não sobre os bytes do arquivo ou do codec.

A receita

Uma pasta _recipes/<name>/ ao lado da especificação, com estes arquivos:

  • spec.json — a especificação completa, como foi passada para build.
  • decoded_hash.txt — o hash SHA-256 dos pixels decodificados do primeiro quadro, codificado em hexadecimal.
  • decoded_frames_hash.txt — o hash SHA-256 de todos os pixels decodificados, concatenados.
  • (Apenas SVG) raster_command.txt — o comando de rasterização exato que foi executado.
  • (Apenas Lottie) player_log.txt — o log completo do player da última execução de build.

A receita está em .gitignore por padrão. Inclua _recipes/ no controle de versão se você precisar reconstruir ou auditar; omita-o para construções descartáveis.

Execute python3 scripts/prerender.py rebuild <name> para verificar a reconstrução: ele relata "RECONSTRUÇÃO: CORRESPONDE" ou "RECONSTRUÇÃO: DIFERE no quadro N (hash X, esperado Y)". Ele não executa o renderizador: apenas verifica o hash.

A rota de cena 3D

Entrada: um arquivo de cena 3D (.glb, .gltf, .obj, .fbx, .blend, .c4d) e o tamanho em pixels das regras comuns. A cena é renderizada headless (sem janela) para produzir filmagens transparentes ou um PNG estático.

  1. Escolha um renderizador que possa produzir quadros RGBA de um formato 3D suportado, com fundo transparente. Registre seu nome e versão em versions. Renderizadores possíveis incluem Blender (via blender -b), Three.js (via Puppeteer/Playwright) ou ferramentas CLI como gltf-transform. O exemplo de referência usa Blender em modo background com saída PNG.
  2. Especificação. Escreva uma especificação de construção ao lado do ativo 3D com "input": "3d": name, out, scene (caminho para o arquivo da cena), a width e height literais, fps, frames, render (o argv do renderizador, com {width}, {height}, {scene}, {frame} e {out}), files, fonts e versions. Para cenas estáticas, defina frames como 1 e omita fps; a saída será um PNG. Para cenas animadas, produza um MOV com frames > 1. render é chamado uma vez por quadro, cada vez em um novo processo, escrevendo RGBA bruto ou PNG em {out}.
  3. Construa. python3 scripts/prerender.py build <spec> executa o renderizador para cada quadro, codifica um <name>.mov (ou <name>.png para imagens estáticas) com ProRes 4444, e verifica a saída. Para cenas animadas, ele falha se algum quadro diferir da saída do renderizador. A cena é renderizada em 32 bits por canal, com alfa, e o codec preserva isso.
  4. Coloque o MOV ou PNG como um elemento video ou image simples, ou com place como em os passos. Execute validate e montagent probe para confirmar alpha, depois frame para verificar a transparência.

Por que renderizar quadro a quadro. Um único comando que produz um filme completo pode usar um codec ou configuração que o harness não pode verificar quadro a quadro. Renderizar cada quadro separadamente permite reconstrução e verificação determinísticas, e garante que cada quadro seja independente (sem compensação de movimento temporal).

A rota de estabilização

Entrada: um clipe de vídeo-fonte (qualquer formato que o Montagent aceite como fonte) e os parâmetros de estabilização. A saída é um novo clipe com movimento suavizado e, se solicitado, travamento de quadro de referência, ping-pong ou câmera lenta.

  1. Escolha uma ferramenta de estabilização que possa analisar e estabilizar o movimento da câmera, e registre seu nome e versão em versions. Ferramentas possíveis incluem FFmpeg com vid.stab, melt (MLT), ou scripts Python com OpenCV. O exemplo de referência usa FFmpeg vid.stab para detecção e estabilização de transformação.
  2. Especificação. Escreva uma especificação de construção ao lado da fonte com "input": "stabilize": name, out, source (caminho para o clipe de origem), a width e height literais (opcionais; se omitido, a largura e altura da fonte são usadas), fps (opcional; se omitido, o fps da fonte é usado), frames (opcional; se omitido, a duração da fonte é usada), render (o argv da ferramenta de estabilização, com {source}, {width}, {height}, {fps}, {frames}, {out} e {tune} onde eles vão), files, e versions. tune é opcional e pode incluir lock (travamento de quadro de referência), pingpong (reprodução para frente e para trás) e slowdown (câmera lenta; o fator é especificado separadamente, por exemplo, "slowdown": 2 para metade da velocidade).
  3. Construa. python3 scripts/prerender.py build <spec> executa a ferramenta de estabilização, que produz um único arquivo de filme (<name>.mov) com o codec ProRes 4444. Se tune incluir pingpong, a saída será estendida para a duração do ping-pong (por exemplo, o dobro da duração para uma repetição). Se slowdown for definido, a saída será mais longa e a taxa de quadros será mantida; o movimento adapta-se à câmera lenta. O build falha se a ferramenta relatar um erro.
  4. Coloque o MOV como um elemento video simples, ou com place como em os passos. O elemento deve ter a mesma duração que a filmagem estabilizada. Se tune incluir lock, o primeiro quadro da filmagem estabilizada é um quadro de referência fixo, e a estabilização mantém esse quadro estacionário (útil para composições com texto ou gráficos sobrepostos).
  5. Verifique. Execute validate e corrija cada erro. Em seguida, montagent probe a filmagem para confirmar que ela tem a duração esperada. frame um tile em vários pontos para verificar se a estabilização está correta e se o travamento, ping-pong e câmera lenta funcionam como esperado.

Ajustes avançados. A especificação pode incluir um campo "tune": {} com parâmetros específicos da ferramenta de estabilização. Por exemplo, para FFmpeg vid.stab, tune pode incluir "shakiness": 5, "accuracy": 15, "stepsize": 6, "mincontrast": 0.3, "tripod": true (equivalente a travamento de quadro de referência). Esses valores são passados para a ferramenta conforme documentado em sua especificação.

Ping-pong e câmera lenta. Quando tune inclui "pingpong": true, a filmagem estabilizada é reproduzida para frente até o fim, depois para trás até o início, repetindo uma vez. Quando tune inclui "slowdown": N (onde N é um inteiro positivo), a filmagem é desacelerada por um fator de N: para cada quadro de entrada, N quadros de saída são gerados (interpolados ou duplicados, dependendo da ferramenta). Ping-pong e câmera lenta podem ser combinados; a duração da saída é frames * (pingpong ? 2 : 1) * slowdown.

{
  "name": "stable_clip",
  "out": "media",
  "input": "stabilize",
  "source": "source_video.mp4",
  "width": 1920,
  "height": 1080,
  "fps": 25,
  "render": ["ffmpeg", "-i", "{source}", "-vf", "vidstabdetect=shakiness=5:accuracy=15,vidstabtransform=tripod=true:zoom=0", "-an", "-y", "{out}"],
  "files": ["source_video.mp4"],
  "versions": {"ffmpeg": ["ffmpeg", "-version"]},
  "tune": {"lock": true, "pingpong": true, "slowdown": 2}
}

Neste exemplo, a fonte de 10 segundos a 25 fps (250 quadros) produz uma saída de 20 segundos (500 quadros) a 25 fps: 250 quadros para frente, depois 250 quadros para trás (ping-pong), em câmera lenta (slowdown 2 significa 500 quadros no total, mas a câmera lenta é aplicada ao movimento; a saída real é de 500 quadros à velocidade de quadro original).

A rota de peça desenhada por código

Entrada: código que desenha quadros RGBA. O código deve ser executável e produzir saída reproduzível.

  1. Escreva o código. Crie um script (Python, Node.js, etc.) que produz quadros RGBA de uma contagem fixa width, height e frames. Use as variáveis de ambiente PRERENDER_WIDTH, PRERENDER_HEIGHT, PRERENDER_FPS, PRERENDER_FRAMES e PRERENDER_FRAMES_DIR para configurar a saída. Escreva PNGs em PRERENDER_FRAMES_DIR nomeados como f00000.png, f00001.png, etc., ou escreva RGBA bruto no stdout. Use aritmética inteira ou uma semente fixa para garantir a reproduzibilidade.
  2. Especificação. Escreva uma especificação de construção ao lado do código: name, out, input como "code", width, height, fps, frames, render (o argv que executa seu código), files (todos os arquivos que o código precisa) e versions (para bibliotecas que afetam a saída). Execute python3 scripts/prerender.py --help para detalhes.
  3. Construa. python3 scripts/prerender.py build <spec>. Ele executa seu código, codifica um <name>.mov com ProRes 4444, decodifica e verifica quadro a quadro contra a saída do código. Falha no primeiro quadro que difere.
  4. Coloque. Adicione o MOV como um elemento video simples, ou use place. Execute validate e montagent probe para confirmar alpha.
  5. Verifique. validate e corrija erros. montagent probe para confirmar alpha. frame um tile para verificar a transparência.

Resumo das rotas

RotaEntradaSaídaUso principal
Peça desenhada por códigoCódigo executávelMOV (ProRes 4444)Visuais generativos, efeitos personalizados
SVGArquivo SVGPNGLogotipos, ícones, ilustrações estáticas
LottieArquivo JSON LottieMOV (ProRes 4444)Animação vetorial do After Effects
Cena 3DArquivo de cena 3DMOV ou PNGModelos 3D, cenas com transparência
EstabilizaçãoClipe de vídeoMOV (ProRes 4444)Estabilização de movimento, travamento de referência, ping-pong, câmera lenta

Solução de problemas

  • build falha com "quadro N difere": A saída do seu código é não determinística. Verifique sementes aleatórias, tempo de sistema, ou estado global. Use aritmética inteira e sementes fixas.
  • build falha com "fonte não encontrada": Certifique-se de que as fontes estão vendidas e listadas em fonts na especificação. Use montagent fonts vendor.
  • build falha com "player pulou efeito": O player Lottie não suporta o efeito. Use allow_effects para listar efeitos suportados, ou remova o efeito do Lottie.
  • probe não mostra alpha: O codec ou a saída não tem canal alfa. Use ProRes 4444 e certifique-se de que seu código desenha transparência onde necessário.
  • place adiciona o elemento na posição errada: Verifique as coordenadas x, y, origin e as chaves at (tempo). Use montagent para inspecionar o projeto.

Referências

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Habilidades Relacionadas