Communitygithub.com

ASNNetworks/floh-skills

Habilidades de Agente por FLOH. Capacidades portáteis SKILL.md para Claude Code, Codex, Gemini CLI, Cursor e outros clientes de agente.

O que é floh-skills?

Este skill fornece um CLI chamado `pharos` que permite interagir com o Azure DevOps diretamente do terminal, autenticando-se através de uma variável de ambiente (`ADO_PAT`) em vez de um login no navegador. Ele é útil para desenvolvedores e engenheiros que desejam automatizar e executar rapidamente tarefas como consultar, criar, atualizar ou vincular itens de trabalho; gerenciar anexos, imagens inline e páginas wiki; e lidar com ganchos de serviço. O skill é portátil e compatível com Claude Code, Cursor, Codex (e outros clientes compatíveis com SKILL.md), fornecendo uma documentação completa e de fácil consulta diretamente no arquivo SKILL.md. O `pharos` é focado em eficiência e segurança. Ele evita comandos desnecessários como `--help` (que gastariam várias chamadas de API) porque toda a funcionalidade já está documentada. Ele oferece operações atômicas e seguras, como `update` que usa um `test` op no `rev` para evitar conflitos de edição, e `unlink` que encontra relações por identidade (não por posição) para evitar quebras acidentais. O skill também destaca nuances importantes do Azure DevOps, como a diferença entre anexos (arquivos na lista de Anexos) e imagens inline (no texto do campo), ou como a consulta `query` lida com estados de itens de trabalho e nomes de iteração. Ele inclui dicas de boas práticas, como usar `--dry-run` antes de operações destrutivas e entender que a exclusão permanente não está disponível intencionalmente. Em resumo, este skill capacita agentes a interagirem com o Azure DevOps de forma produtiva e confiável, minimizando chamadas desnecessárias e fornecendo uma experiência de linha de comando rica e bem documentada. Ele é ideal para equipes que usam Azure DevOps e querem integrar suas operações diárias em fluxos de trabalho automatizados ou em assistentes de IA.

Funciona com✓Claude Code✓Codex CLI✓Cursor✓Gemini CLI
npx skills add ASNNetworks/floh-skills

Perguntar na sua IA favorita

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

Prévia

Do README da skill

floh-skills preview
chart
diagram

Documentação

Trabalhando com Azure DevOps usando pharos

pharos é um CLI que oferece o Azure DevOps a partir de um shell, autenticado por uma variável de ambiente em vez de um login no navegador.

Tudo o que ele pode fazer está listado abaixo. Não execute pharos --help para descobrir — isso custa várias chamadas e esta seção tem a mesma informação.

whoami                         a quem o ADO_PAT pertence. @Me resolve para isso
types                          quais --state e --type serão ACEITOS, por tipo
query                          QUAIS itens de trabalho — atribuídos a você, em uma sprint,
                               de um tipo, ainda abertos. Itens hidratados, não ids.
task <id>                      um item de trabalho, completo: campos, comentários,
                               anexos, relações COM títulos, e o conteúdo + discussão
                               de cada página wiki vinculada
                               --children  uma EPIC e tudo abaixo dela, em
                               UMA chamada. --depth <n> para mais profundo (máx 5)
                               --compact   achata identidades, remove chaves de quadro
create <type> --title "…"      um item de trabalho. --parent vai no MESMO patch
update <id>                    alterar um campo: --state --priority --assignee
                               --title, ou --field Nome=valor para qualquer outra coisa
link <id> --parent <id>        relacionar dois itens. Também --child --related
unlink <id> --parent <id>      --predecessor --successor --duplicate
link <id> --wiki-page <caminho>   vincular uma PÁGINA WIKI a um item de trabalho — o lado do item
wiki links <caminho>           quais itens de trabalho vinculam a uma página (ADO não tem API)
wiki link <caminho> --item <id>   o lado WIKI; --item repetível
wiki unlink <caminho> --item <id>
history <id>                   o que MUDOU, campo por campo, quem e quando
iterations | areas             as sprints com suas datas, e as áreas
links                          todo tipo de relação que esta ORG tem, e qual
                               --flag o alcança (seis de ~dezoito)
fields [--type T]              o que um campo vai ACEITAR — valores permitidos
attach <id> <arquivo>          colocar um ARQUIVO em um item de trabalho (lista de Anexos)
detach <id> <url-ou-guid>      remover um. --yes. Ou --name <arquivo>
download <id-do-item|guid|url>    ler um de volta. Um ID DE ITEM DE TRABALHO com --name <arquivo>,
                               ou --all --out <dir>. --out ou nada é escrito
image <arquivo>                enviar uma IMAGEM para uso dentro de texto. Imprime o
                               markdown para colar. NÃO é o mesmo que attach
people [consulta]              quem pode ser @mencionado, com a forma @<guid>
delete <id> --yes              → Lixeira (sem exclusão permanente, de propósito)
restore <id>                   trazer de volta
deleted                        o que está na Lixeira, com nomes.
                               --top <n> — retorna 50 por padrão e relata
                               o total verdadeiro como "count"
wiki list | tree | read <caminho> | write <caminho> | delete <caminho>
wiki move <caminho> <novo caminho>    mover uma página; subpáginas vêm junto
wiki rename <caminho> <novo nome>  a mesma chamada, apenas folha. AMBAS precisam de --yes
wiki duplicate <caminho> [para]     um verbo que o Azure DevOps não tem. "<caminho> - Cópia N"
wiki image <arquivo>              uma imagem para uma PÁGINA ou comentário de página. Endpoint
                               diferente de `image`, e o nome é único
wiki import <arquivo...>        .md .txt .docx .pdf .rtf .html -> páginas. Um
                               .pptx é recusado, de propósito — veja abaixo
                               --under <caminho> --as <nome>
comment list | add | edit | delete   <alvo> é um id de item de trabalho OU um caminho wiki
comment react | unreact | reactors   like dislike heart hooray smile confused
hooks list | check | create | repoint | delete    ganchos de serviço em tempo real.
                               `check` precisa de --hub <url>; `list` mostra a URL
                               já em uso
plan <arquivo>                 um plano de implementação → uma árvore de itens de trabalho
setup                          org, projeto, token → chaveiro + perfil do shell

Entrada de texto: --text / --file / --stdin. Global: --pretty para humanos, --yes para verbos destrutivos, --dry-run para pré-visualizar.

ADO_ORG, ADO_PROJECT e ADO_PAT já estão no ambiente após a configuração. Não os verifique antes de trabalhar; uma falta se anuncia como "kind": "config" no código de saída 2, que é a única vez que importa.

Encontrando o trabalho: pharos query

Não recorra a curl e ao endpoint WIQL. Este skill costumava fornecer uma receita exata para isso, porque não havia um verbo de consulta. Agora existe um, e ele faz a parte que a receita não conseguia: WIQL retorna apenas ids, então a receita te dava dezesseis números crus e uma chamada por item para fazê-los significar algo.

pharos query --mine                       # atribuído a você, ainda aberto
pharos query --sprint "Sprint 1"          # --sprint current para @currentIteration
pharos query --type Epic --state Doing    # ambos repetíveis
pharos query --assignee "[email protected]"
pharos query --tag api --all              # --all inclui trabalho concluído
pharos query --wiql "SELECT [System.Id] FROM WorkItems WHERE …"   # escape hatch

Flags são combinadas com AND. A saída são itens hidratados — id, tipo, título, estado, responsável, iteração, tags, prioridade, alterado — então --mine é um comando, não uma consulta seguida de uma busca por resultado. Siga com pharos task <id> apenas para os poucos que você realmente vai trabalhar.

Leia o campo openness antes de reportar uma contagem. "12 abertos" é sem sentido até que você saiba o que foi contado como concluído, e o Azure DevOps permite que um template de processo renomeie cada estado. query lê as categorias de estado do próprio projeto e informa quais estados tratou como terminais; se não puder lê-los, avisa isso e recorre a um palpite, e esse é o seu sinal para passar --state explicitamente. assignedTo nomeia para quem @Me realmente resolveu — um token compartilhado ou de serviço faz com que "atribuído a mim" signifique silenciosamente outra pessoa.

--all compõe com todos os outros filtros, então --mine --all é como você sabe se nada está atribuído a você de nada aberto. Um simples pharos query --all é válido e retorna todo o projeto.

--sprint aceita tanto o nome simples quanto o fieldPath e normaliza entre eles — a regra do fieldPath é sobre System.IterationPath como um valor de campo. Mas uma sprint nomeada corresponde com UNDER (sub-iterações incluídas) enquanto --sprint current corresponde com = (exato), então não são a mesma consulta.

--wiql também aceita uma consulta FROM WorkItemLinks … MODE (MustContain) e hidrata os ids da mesma forma, que é como você encontra cada item carregando um determinado tipo de relação em uma única chamada.

NÃO escreva [System.State] NOT IN GROUP 'Completed' se você recorrer a --wiql. Ele analisa, retorna 200 e corresponde a tudo — IN GROUP cobre apenas categorias de tipo de item de trabalho, e um grupo desconhecido resolve para o conjunto vazio sem erro. Medido, 2026-08-05.

Alterando um item de trabalho

pharos update 225 --state Doing              # mover o estado quando o trabalho se move
pharos update 225 --priority 1 --assignee "[email protected]"
pharos update 225 --field Microsoft.VSTS.Scheduling.RemainingWork=3
pharos attach 225 ./bestsellers.xlsx --comment "Os números"

update lê o item e aplica a alteração sob uma operação test em /rev, então alguém que escreveu entre sua leitura e sua escrita recebe um conflict em vez de perder sua edição. Definir um valor que já existe não escreve nada e informa isso — um PATCH inútil ainda incrementa System.Rev e invalida todas as outras revisões em cache no item. --dry-run mostra o antes → depois e não escreve nada. Não há --yes: uma edição de campo é uma edição comum e o Azure DevOps mantém todas as revisões.

attach envia os bytes e então os vincula como uma relação AttachedFile — duas chamadas, um comando. Anexos são imutáveis: anexar o mesmo arquivo duas vezes cria dois deles, e não há substituição nem versionamento. detach remove um; precisa de --yes, encontra o anexo por identidade em vez de por posição, e deixa os bytes no Azure DevOps, então reanexar a url o coloca de volta. Nomeie o arquivo com --name <arquivo> ou passe o GUID — e como com download, dois arquivos compartilhando um nome são RECUSADOS em vez de remover o que vier primeiro.

create coloca --parent no mesmo patch que os campos, então um filho nunca é brevemente um órfão, e aceita os mesmos nomes de flag que update.

unlink recusa em vez de adivinhar, e isso é bom saber antes de ver. O Azure DevOps remove uma relação pela sua POSIÇÃO no array, então um índice de uma leitura desatualizada corta um link diferente e a solicitação ainda é bem-sucedida. unlink encontra a relação por identidade e a remove sob uma operação test na revisão que leu. Se a relação não estiver lá, você recebe o código de saída 3 — isso significa que nada aconteceu, não que a chamada falhou.

delete move para a Lixeira e precisa de --yes; a recusa cita o título primeiro. restore <id> traz de volta e não precisa de flag.

Não há exclusão permanente aqui, deliberadamente. É o único verbo irreversível que o Azure DevOps tem, e --yes é uma flag que você aprendeu a passar. A interface web é a dona dela. Se alguém realmente precisar purgar, envie-o para lá em vez de procurar uma flag.

Imagens em texto e arquivos ao lado

Estas são duas coisas diferentes e escolher a errada é o erro que vale a pena evitar.

pharos attach 225 ./bestsellers.xlsx    # um ARQUIVO, na lista de Anexos
pharos image ./screenshot.png           # uma IMAGEM, para colocar dentro do texto

Um anexo cria uma relação AttachedFile e aparece na lista de Anexos do item de trabalho. Uma imagem inline não cria relação alguma — medido no #333, duas capturas de tela coladas em uma descrição deram relations: 0 e attachments: []. É um ![](…) no texto do campo e nada mais, que é por que a lista de Anexos está certa em não mostrar nada para isso.

Então image imprime uma linha markdown e deixa a escrita para você:

pharos image ./chart.png --pretty
# ![chart](https://dev.azure.com/…/wit/attachments/<guid>?fileName=chart.png)

pharos update 225 --field System.Description="$(cat <<'EOF'
A receita aumentou. Veja o gráfico:

![chart](https://dev.azure.com/…/wit/attachments/<guid>?fileName=chart.png)
EOF
)"

Uma imagem wiki é um endpoint diferente e precisa de wiki image. Uma wiki é um repositório git, então um anexo lá é um ARQUIVO e seu NOME é sua identidade: envie uma segunda image.png e ela cai sobre a primeira, e toda página apontando para /.attachments/image.png muda silenciosamente de imagem. wiki image torna o nome único antes de enviar e imprime um link relativo ao repositório:

pharos wiki image ./diagram.png --pretty
# ![diagram](/.attachments/diagram-1786046773042.png)

Use esse caminho, não uma url absoluta — uma página vinculando a uma url wit/attachments renderiza para qualquer um com uma sessão e quebra para todos os outros. O mesmo markdown funciona em uma página e em um comentário de página.

Obtendo um anexo de um item de trabalho

pharos task <id> lista o que está anexado, com o GUID de cada arquivo — no JSON e em --pretty. Então pegue-o em uma chamada, pelo nome:

pharos download 41 --name Skills.pptx --out ./Skills.pptx
pharos download 41 --all --out ./attachments      # todos os anexos do item
pharos download <guid-or-url> --out ./file.bin    # quando você já tem um

--out é o que escreve. Sem ele você recebe o tamanho e nenhum arquivo — bytes brutos no stdout corromperiam o JSON que todo outro verbo imprime.

Um simples pharos download 41 é um erro de uso carregando a lista — nome, GUID e tamanho — então escolher o arquivo certo nunca custa uma segunda chamada. Dois anexos com o mesmo nome recusam em vez de adivinhar: anexos são imutáveis, então anexar um arquivo duas vezes cria dois deles e o nome não é uma identidade.

detach aceita o mesmo --name <arquivo>, então o verbo que você usa depois de ler task --pretty aceita o que ele mostrou:

pharos detach 41 --name Skills.pptx --yes      # --dry-run pré-visualiza primeiro

Ler o que está dentro é SEU trabalho, com SUAS ferramentas

download coloca bytes no disco e para por aí. Transformar um .docx, .pptx, .xlsx ou .pdf em algo que você pode ler é trabalho do seu ambiente.

Não use pharos-convert para isso. É o conversor de wiki import, compartilhado com o aplicativo macOS para que ambos produzam a mesma página a partir do mesmo arquivo — sua saída é moldada para se tornar uma página wiki, e recorrer a ela aqui acopla o que você lê ao caminho de importação do aplicativo. Ele também não consegue ler .pptx.

Duas maneiras pelas quais isso falha silenciosamente, ambas medidas em um item de trabalho real:

  • Você verificou a ferramenta no lugar errado. which markitdown contra o PATH do sistema e import docx contra o python3 do sistema ambos retornam vazios em uma máquina onde essa ferramenta está instalada — em um venv por skill. Um agente que executa essas duas verificações conclui "nada aqui" e contorna ferramentas que estavam lá o tempo todo. Olhe onde seu agente mantém suas ferramentas antes de concluir que estão ausentes.
  • Texto não vazio não é prova de que você leu o documento. Um .pptx real extraiu para sete fragmentos, cerca de 90 caracteres; a especificação inteira estava em duas PNGs embutidas. Todo leitor somente texto retorna algo para essa apresentação e parece que funcionou. Para uma apresentação de slides, ou um PDF escaneado, o payload geralmente são as imagens — extraia-as e realmente olhe para elas.

Primeiro pergunte se você lê PDFs nativamente. Se sim, isso é um comando.

Muitos agentes — Claude Code entre eles — leem um PDF visualmente, página por página, da mesma forma que uma pessoa olha para ele. Isso cobre um escaneamento sem texto nenhum, sem etapa de OCR. Se esse é o seu caso, todo o problema se reduz a uma conversão:

soffice --headless --convert-to pdf f.docx --outdir ./out    # .pptx, .xlsx também
# …

Habilidades Relacionadas