@slipalison/claupilot
v0.3.0
Published
Use your repository's GitHub Copilot customization (.github/copilot-instructions.md, instructions, prompts, agents, skills) from Claude Code and OpenCode — without committing a single tool-specific file.
Maintainers
Readme
claupilot
Use a customização do GitHub Copilot do seu repositório a partir do Claude Code e do OpenCode — sem commitar um único arquivo específico da ferramenta.
Read this in English.
O problema
Seu time (ou empresa) padroniza o GitHub Copilot e o layout de customização .github/ —
copilot-instructions.md, instruction files, prompt files, agents customizados, skills. Você prefere
desenvolver com o Claude Code (ou o OpenCode), mas há duas restrições:
- Essa ferramenta não lê os arquivos de customização do Copilot.
- Você não pode commitar nada específico da ferramenta (
CLAUDE.md,.claude/,.opencode/, …) no repositório — e duplicar o conteúdo na mão apodrece imediatamente.
O claupilot resolve os dois. Ele faz a ponte da estrutura do Copilot para a sua ferramenta
localmente, no início da sessão, e mantém tudo que cria invisível para o git. O Claude Code é o
alvo padrão; --target opencode (ou both) faz o mesmo para o OpenCode.
O que é bridgeado
| Copilot (commitado, fonte de verdade) | Claude Code (local, nunca commitado) | Como |
|---|---|---|
| .github/copilot-instructions.md | Contexto da sessão | Injetado por hook SessionStart, como se fosse CLAUDE.md |
| AGENTS.md | Contexto da sessão | Injetado (o Copilot CLI lê os dois — o claupilot também) |
| .github/instructions/*.instructions.md | .claude/rules/*.md (rules com escopo por path) | Gerado — globs applyTo viram paths:, carregadas sob demanda pelo Claude Code |
| .github/prompts/*.prompt.md | .claude/commands/*.md → /nome | Gerado com tradução de frontmatter e variáveis |
| .github/agents/*.md, *.agent.md | .claude/agents/*.md (subagents) | Gerado com mapeamento de tools/modelo |
| .github/skills/*/SKILL.md, .agents/skills/ | .claude/skills/* | Linkado (junction/symlink) — mesmo padrão aberto Agent Skills, zero conversão |
Tudo cai em <repo>/.claude/, que o claupilot esconde do git via .git/info/exclude — um
ignore local que nunca é commitado. O git status fica limpo, o .gitignore nunca é tocado, e
nada relacionado ao Claude consegue vazar num commit ou PR.
Instalação
Requer Node.js ≥ 18 (Claude Code ≥ 2.x).
Como plugin do Claude Code (recomendado) — dentro do Claude Code:
/plugin marketplace add slipalison/claupilot
/plugin install claupilot@claupilotReinicie o Claude Code. A partir daí, toda sessão iniciada num repo com customização do Copilot é bridgeada automaticamente. Sem setup por repositório.
CLI standalone (sem plugin):
npx @slipalison/claupilot sync # bridgeia o repo atual (Claude Code)
npx @slipalison/claupilot check # dry-run: mostra o que mudaria
npx @slipalison/claupilot context # prévia do contexto que seria injetado
npx @slipalison/claupilot clean # remove tudo que o claupilot criou
npx @slipalison/claupilot sync --target opencode # bridgeia para o OpenCode
npx @slipalison/claupilot sync --target both # bridgeia para os dois de uma vezHook no nível do usuário (sem plugin, sync automático) — em ~/.claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|clear|compact",
"hooks": [
{
"type": "command",
"command": "npx --yes @slipalison/claupilot sync --hook",
"timeout": 60
}
]
}
]
}
}Como funciona (Claude Code)
início da sessão
│
▼
Hook SessionStart ──► node claupilot.mjs sync --hook
│
├─ descobre .github/{copilot-instructions.md, instructions/, prompts/, agents/, skills/}, AGENTS.md, .agents/skills/
├─ traduz frontmatter, tools, modelos, variáveis ${input:*}
├─ sincroniza .claude/{agents,commands,rules,skills} (gerenciado por marcadores, idempotente)
├─ exclui .git/info/exclude (bloco "/.claude/" gerenciado)
└─ injeta instruções de repositório como additionalContext- Instruction files viram rules nativas do Claude Code (
.claude/rules/*.md): os globs deapplyTosão traduzidos pro frontmatterpaths:, então o Claude Code carrega cada rule apenas quando toca arquivos que casam — exatamente a semântica doapplyTono Copilot.applyTo: "**"(ou ausente) vira rule incondicional; subdiretórios de instructions são espelhados. Arquivos de repositório inteiro (copilot-instructions.md,AGENTS.md) são injetados como contexto da sessão. - Skills não precisam de tradução — Agent Skills é um padrão aberto compartilhado por Copilot e
Claude. O claupilot linka
.claude/skills/<nome>→.github/skills/<nome>(junction no Windows — sem admin — symlink no Linux/macOS, cópia como fallback ou com--no-links). Edições na fonte refletem ao vivo. - Agents e prompts são arquivos gerados com camada de tradução (abaixo) e um comentário marcador identificando-os como gerenciados pelo claupilot.
Regras de tradução
Tools (nomes canônicos do Copilot, aliases documentados, vocabulário do VS Code e MCP):
| Copilot | Claude Code |
|---|---|
| execute, shell, bash, powershell | Bash (+ PowerShell) |
| read, NotebookRead | Read |
| edit, write, MultiEdit, NotebookEdit, editFiles | Edit, Write (+ NotebookEdit) |
| search, Grep, Glob, codebase, usages | Grep, Glob (+ Read para codebase) |
| web, WebSearch, WebFetch, fetch | WebSearch, WebFetch |
| agent, custom-agent, Task | Agent |
| todo, TodoWrite | TodoWrite |
| server/tool (MCP) | mcp__server__tool |
Se algum token não mapear (ex.: server/*), o campo tools é omitido por inteiro — o subagent
herda todas as tools em vez de perder capacidade silenciosamente. O motivo fica registrado num
comentário claupilot:notes dentro do arquivo gerado.
Modelos: claude-sonnet-* → sonnet, claude-opus-* → opus, claude-haiku-* → haiku.
GPT/Gemini/outros são descartados (usa-se o modelo da sessão) com nota.
Variáveis de prompt: um único ${input:x} → $ARGUMENTS; múltiplos → $1, $2, … por ordem
de aparição (o argument-hint é derivado, ou preservado quando a fonte declara um). ${selection}
vira referência em linguagem natural. Um agent: customizado num prompt file mapeia para o
subagent bridgeado de mesmo nome.
OpenCode
Tudo acima funciona também para o OpenCode — use --target opencode
(ou --target both). As mesmas fontes .github/ são bridgeadas para o layout nativo do OpenCode,
num .opencode/ local e invisível pro git:
| Copilot (commitado, fonte de verdade) | OpenCode (local, nunca commitado) | Como |
|---|---|---|
| .github/copilot-instructions.md | .opencode/opencode.json → instructions | Referenciado no lugar — sem cópia; o OpenCode resolve o path a partir da raiz do repo |
| .github/instructions/*.instructions.md | .opencode/opencode.json → instructions | Referenciado no lugar (carregam sempre — o OpenCode não tem escopo applyTo) |
| AGENTS.md | (nada) | O OpenCode lê nativamente |
| .github/prompts/*.prompt.md | .opencode/commands/*.md → /nome | Gerado; ${input:*} → $ARGUMENTS/$1..$N |
| .github/agents/*.md, *.agent.md | .opencode/agents/*.md (mode: subagent) | Gerado; allowlist de tools do Copilot → mapa permission do OpenCode |
| .github/skills/*/SKILL.md, .agents/skills/ | .opencode/skills/* | Linkado (junction/symlink) — mesmo padrão aberto Agent Skills |
Diferenças em relação à ponte do Claude Code, por design:
- Instruções são referenciadas, não copiadas. O OpenCode resolve paths relativos de
instructionsa partir da raiz do projeto mesmo quando declarados em.opencode/opencode.json, então o.github/segue como fonte única de verdade. Como o OpenCode não tem equivalente aapplyTo, os instruction files carregam sempre — o frontmatter de cada um ainda traz o glob para o modelo se auto-escopar. .opencode/opencode.jsonfaz deep-merge com qualqueropencode.jsonque você já tenha (o OpenCode faz união + dedupe deinstructions), então o claupilot nunca sobrescreve sua config. Um.opencode/opencode.jsonpré-existente que o claupilot não criou é deixado intacto (skip + aviso).- Modelos são descartados (o OpenCode usa o modelo configurado) e anotados — o OpenCode precisa
de um slug
provider/modelcom versão fixada, que uma dica do Copilot não vira com segurança.
Sync automático (recomendado) — instale o plugin do OpenCode para toda sessão re-bridgear sozinha, do jeito que o plugin do Claude Code faz:
mkdir -p ~/.config/opencode/plugin
curl -fsSL https://raw.githubusercontent.com/slipalison/claupilot/main/opencode/plugin/claupilot.js \
-o ~/.config/opencode/plugin/claupilot.jsO plugin roda claupilot sync --target opencode no início da sessão e ainda injeta os instruction
files descobertos na config em memória, para valerem imediatamente (requer Node ≥ 18 no PATH). Assim
que .opencode/ existe, o OpenCode cria seu próprio node_modules/.gitignore lá dentro — são do
OpenCode, ignorados pelo .gitignore dele, e o diretório inteiro fica escondido do git pelo claupilot.
Garantias
- Zero pegada no repositório. Nada que o claupilot escreve é visível pro git. Ele edita apenas
.git/info/exclude(que nunca é commitado) — jamais o.gitignore. - Nunca toca nos seus arquivos. Arquivos gerados carregam marcador
claupilot:managed; qualquer coisa sem marcador — seus próprios commands, agents, skills — nunca é modificada nem apagada. - Fonte de verdade continua em
.github/. Edite as fontes, não os gerados; o próximo início de sessão (ou/claupilot:sync) re-sincroniza. Fontes apagadas têm seus gerados removidos. - Idempotente e rápido. Fontes inalteradas → zero escritas, poucos milissegundos.
- Nunca quebra a sessão. Em modo hook, qualquer erro interno é engolido (logado no stderr) e a sessão inicia normalmente.
- Offline e sem dependências. Script Node de arquivo único, sem acesso à rede, zero deps de runtime.
Comandos do plugin
| Comando | O que faz |
|---|---|
| /claupilot:sync | Re-sincroniza agora e reporta o que mudou |
| /claupilot:doctor | Diagnóstico dry-run: assets descobertos, mudanças pendentes, status do git exclude |
Bom saber
- Primeiro sync num repo: skills/agents/commands/rules materializados durante o início da sessão
são descobertos pelo Claude Code no próximo início (o contexto injetado cobre o intervalo com
ponteiros MUST-read, e instruções de repositório valem imediatamente). Reinicie ou use
/clearuma vez após o primeiro bridge de um repo. - A direção inversa é nativa: o GitHub Copilot CLI já lê
.claude/skills/,CLAUDE.mde.mcp.json. O claupilot preenche a direção que falta — Claude Code lendo o layout do Copilot. - Servidores MCP: ambos leem
.mcp.jsonna raiz do repo; config MCP não precisa de bridge. - Prompt files não são suportados pelo próprio Copilot CLI (só VS Code) — o claupilot bridgeia para o Claude Code mesmo assim.
hooksdo Copilot (.github/hooks/*.json) intencionalmente não são bridgeados: executar comandos de hook entre ferramentas tem implicações de segurança. Pode virar opt-in no futuro.- Worktrees e monorepos: git worktrees são suportados (o bloco de exclude vai pro git dir
comum);
.github/aninhados em pacotes de monorepo não são varridos (apenas a raiz). - Windows: junctions no lugar de symlinks — funcionam sem Developer Mode e sem admin.
Comparação com o que já existe
rulesync, ruler
e dotagent resolvem sync multi-ferramenta sendo donos da
fonte de verdade em diretório próprio e gerando os arquivos por ferramenta — que são commitados
(ou exigem editar .gitignore). O claupilot tem o formato oposto: o layout commitado do Copilot
segue sendo a fonte de verdade, e o lado Claude Code / OpenCode é um cache local descartável e
invisível pro git. Nada para adotar, nada para commitar, nada para os colegas verem.
Desenvolvimento
npm test # suíte baseada em fixtures (node puro, sem framework)
npm run test:coverage # mesma suíte sob c8 (lcov para o SonarQube)
claude plugin validate . # valida manifests de plugin/marketplaceO CI roda a matriz de testes em Linux e Windows (Node 18/20/24), valida o manifest do plugin, faz
dry-run de publish no npm e roda SonarQube com quality gate bloqueante. Releases são dirigidas por
tag (vX.Y.Z) e publicam no npm com provenance.
