cc2codex
CLI que sincroniza plugins do marketplace do CC para o Codex. Cada plugin de origem se torna
uma bridge cc-<nome>, o Markdown do agente CC é convertido para TOML do Codex, e cada
artefato recebe um marcador x-cc-bridge para que as operações de listar / atualizar / desinstalar
possam gerenciá-los em lote.
Instalação
O pacote está publicado no PyPI. Escolha um destes estilos de invocação — os
exemplos abaixo assumem que cc2codex está no $PATH:
-
uvxzero-install (recomendado, sempre a versão mais recente):uvx --from cc-plugin-to-codex cc2codex --help -
uv tool install(persistente):uv tool install cc-plugin-to-codex cc2codex --help -
pip simples:
pip install cc-plugin-to-codex cc2codex --help
5 comandos
| Comando | O que faz |
|---|---|
plugin-browse | Lista somente leitura dos plugins expostos por um marketplace de origem |
plugin-sync | Instala uma bridge: copia arquivos + converte agentes + atualiza o registro |
plugin-list | Mostra as bridges instaladas (identificadas pelo marcador x-cc-bridge) |
plugin-update | Re-sincroniza a partir da origem registrada no marcador |
plugin-uninstall | Remove uma bridge pelo marcador |
Conceitos principais
- Escopo:
global=~/.codex/ ~/.agents/;project=$PWD/.codex/ $PWD/.agents/.--scopeé obrigatório no modo estrito. - Origem: uma URL Git (
git@host:org/repo.git,https://…/repo.git,ssh://…,git://…, ougit@host:path) ou um caminho local de checkout que contenha.claude-plugin/marketplace.json. Origens Git são clonadas em/tmpe limpas depois.--refaceita um branch, tag ou SHA de commit. - Marcador
x-cc-bridge: campo de primeiro nível noplugin.jsonda bridge, mais um comentário na primeira linha de todo TOML de agente bridge. Arquivos sem o marcador são considerados de autoria do usuário e a ferramenta nunca os sobrescreverá a menos que--forceseja passado. - Nomeação: o nome da bridge é
cc-<plugin-origem>; o nome do arquivo TOML do agente écc_<plugin_snake>_<agente_snake>.toml(kebab-case → snake_case).
Fluxos típicos
Sincronizar um ou todos os plugins (recomendado para IA)
# Plugins específicos
cc2codex plugin-sync \
--source https://github.com/sua-org/cc-marketplace.git \
--plugin ios-dev --plugin base \
--scope global \
--non-interactive --yes
# Tudo
cc2codex plugin-sync \
--source /caminho/para/cc-marketplace \
--all-plugins --scope global \
--non-interactive --yes
Re-sincronizar a mesma origem é seguro: agentes que existiam no marcador antigo mas não estão mais presentes na origem são limpos automaticamente.
⚠️ Após
plugin-synco usuário deve instalar a bridge dentro do CodexO Codex não recarrega a quente
~/.agents/plugins/marketplace.json. Depois que o cc2codex terminar de escrever os arquivos, o usuário precisa reiniciar o Codex (ou iniciar uma nova sessão), executar/plugins, escolher a bridge recém-adicionada no marketplace "CC Bridged Plugins" e instalá-la. Até que essa etapa de instalação seja executada, o Codex não carregará as skills e agentes. Ao explicar uma sincronização bem-sucedida, sempre inclua esta instrução.
Verificar estado
cc2codex plugin-list # texto legível
cc2codex plugin-list --scope global --json # legível por máquina
Atualizar
cc2codex plugin-update cc-ios-dev --scope global --non-interactive --yes
cc2codex plugin-update --all --non-interactive --yes
Não é necessário passar --source novamente — a ferramenta lê do marcador.
Desinstalar
cc2codex plugin-uninstall cc-ios-dev --scope global --non-interactive --yes
cc2codex plugin-uninstall --all --scope all --non-interactive --yes
Remove o diretório do plugin + todo TOML de agente associado + a entrada no registro.
⚠️ O Codex tem seu próprio cache; desinstalar cobre apenas metade da história
O cc2codex remove apenas os arquivos que ele escreveu. O Codex tem dois locais de estado extras que o cc2codex não pode tocar:
~/.codex/plugins/cache/cc-bridged-plugins/<bridge>/<versao>/— o Codex copia as bridges aqui quando o usuário executa/plugins install, e carrega daqui em tempo de execução.~/.codex/config.toml, seção[plugins."<bridge>@cc-bridged-plugins"] enabled = true— o próprio estado de habilitação do Codex.Como resultado, uma bridge que foi previamente instalada dentro do Codex ainda será carregada do cache após uma desinstalação do cc2codex. Depois de explicar que a desinstalação foi bem-sucedida, também diga ao usuário para executar
/pluginsdentro do Codex e desinstalar a mesma bridge lá para que o Codex possa limpar seu próprio cache + configuração.Ou, manualmente:
rm -rf ~/.codex/plugins/cache/cc-bridged-plugins/<bridge>e edite~/.codex/config.tomlpara remover a seção[plugins."…"]correspondente.
Regras do modo estrito (importante)
Quando não há TTY ou qualquer um de --yes / --json / --non-interactive é
passado, o comando executa no modo estrito. No modo estrito, toda decisão
deve ser fornecida explicitamente:
| Ausente | Mensagem de erro |
|---|---|
--source | source não especificado; passe --source <git-url-ou-caminho> |
--plugin ou --all-plugins | nenhum plugin selecionado; passe --plugin <nome> (repetível) ou --all-plugins |
--scope | `scope não especificado; passe --scope global |
uninstall/update sem nome ou --all | deve especificar um nome de bridge ou --all para X (instalados: …) |
Ao chamar de uma IA ou script, passe todas as flags explicitamente — não confie em padrões.
Modo interativo
Em um TTY real, omitir uma flag abre um seletor questionary:
- Tipo de origem: URL Git / Caminho local / Escanear
~/.claude/plugins/marketplaces/ - Plugins: caixa de seleção múltipla
- Escopo: global / project
- Alvo de
uninstall/updatebridge: caixa de seleção múltipla
Armadilhas comuns
- Conflito não-bridge: um diretório de plugin já existe no caminho de destino
mas não tem o marcador
x-cc-bridge→ recusado (protege conteúdo de autoria do usuário). Passe--forcepara sobrescrever. - Conflito de troca de origem: uma bridge com o mesmo nome foi previamente
sincronizada da origem A e agora você está apontando para a origem B → recusado. Execute
plugin-uninstallprimeiro, ou passe--force. - Nome do plugin vs nome da bridge:
--pluginrecebe o nome da origem (ex.:ios-dev), não o nome da bridge (cc-ios-dev). O argumento posicional deplugin-uninstall/plugin-updaterecebe o nome da bridge. - Política de registro: cada entrada de registro é escrita com
installation: INSTALLED_BY_DEFAULT+authentication: ON_USE, então o Codex ativa a bridge automaticamente uma vez instalada. - Limpeza de agentes obsoletos é segura: apenas TOMLs que contêm o comentário
x-cc-bridgesão excluídos; TOMLs de autoria do usuário são deixados intactos.
Referência completa de flags
Flags compartilhadas
| Flag | Significado |
|---|---|
--source <url-ou-caminho> | URL Git (git@host:org/repo.git, https://…/repo.git) ou caminho local (diretório contendo .claude-plugin/marketplace.json). Omita para selecionar interativamente. |
| `--ref <branch | tag |
--scope {global,project} | Escopo de destino. global → ~/.codex/ ~/.agents/; project → $PWD/.codex/ $PWD/.agents/. Obrigatório no modo estrito para plugin-sync. |
--scope {global,project,all} | Filtro de escopo para plugin-list, plugin-update, plugin-uninstall. Padrão all. |
--plugin <nome> | Repetível. Recebe o nome do plugin do lado da origem (sem prefixo cc-). Mutuamente exclusivo com --all-plugins. |
--all-plugins | Sincroniza todos os plugins expostos pela origem. |
--all | Aplica plugin-update / plugin-uninstall a todas as bridges no escopo de destino. |
--yes | Pula prompts de confirmação (implica modo estrito). |
--non-interactive | Força modo estrito; ativado automaticamente quando stdin não é um TTY. |
--force | Ignora proteção de conflito (sobrescrita de não-bridge, origem diferente). |
--json | Emite JSON legível por máquina na stdout (implica modo estrito). |
plugin-browse
Listagem somente leitura de plugins em um marketplace de origem. Não escreve nada.
cc2codex plugin-browse --source <url-ou-caminho> [--ref <ref>] [--json]
Não interativo: --source é obrigatório.
plugin-sync
Comando principal de instalação. Pipeline:
- Resolver a origem (clonar Git em
/tmp, ou ler o caminho local). - Ler
<origem>/.claude-plugin/marketplace.jsonpara listar plugins disponíveis. - Filtrar com
--plugin/--all-plugins. - Para cada plugin selecionado:
- Pré-converter todos os
agents/*.md(falhar rapidamente). - Verificar conflitos de TOML de agente (autoria do usuário → recusar a menos que
--force). - Preparar um diretório irmão e copiar (lista negra exclui
.claude-plugin/,.codex-plugin/,hooks/,commands/,agents/, VCS/ruído de build). - Escrever
.codex-plugin/plugin.jsonincluindo o marcadorx-cc-bridgee a lista final de agentes. - Renomear atomicamente (POSIX) o diretório preparado sobre a bridge antiga.
- Escrever TOMLs de agente (comentário
# x-cc-bridge: {…}na linha 1). - Remover agentes obsoletos (no marcador antigo mas não na nova lista).
- Inserir ou atualizar a entrada no
marketplace.json(policy.installation = INSTALLED_BY_DEFAULT).
- Pré-converter todos os
cc2codex plugin-sync \
--source <url-ou-caminho> [--ref <ref>] \
--scope {global|project} \
{--plugin <nome> [--plugin <nome>] … | --all-plugins} \
[--force] [--yes] [--non-interactive] [--json]
Não interativo: --source, --scope e --plugin|--all-plugins são todos
obrigatórios.
plugin-list
Escaneia todo diretório de plugin no escopo de destino e lista aqueles que
contêm um marcador x-cc-bridge.
cc2codex plugin-list [--scope {global|project|all}] [--json]
Modo texto imprime caminhos de pluginsDir / agentsDir / registry para cada escopo
seguido pelo inventário de bridges com nomes de agentes. Modo JSON agrupa os mesmos
dados por escopo.
plugin-update
Usa o x-cc-bridge.source + .ref da bridge para re-resolver a origem e
executar o pipeline de sincronização. Argumentos de origem NÃO são necessários novamente.
cc2codex plugin-update [cc-<nome> | --all] \
[--scope {global|project|all}] \
[--force] [--yes] [--non-interactive] [--json]
- O argumento posicional é o nome da bridge (com prefixo
cc-). --allatualiza todas as bridges no escopo de destino.- No modo estrito, um nome ausente /
--allaciona um erro que lista as bridges instaladas.
plugin-uninstall
Limpeza orientada por x-cc-bridge.agents. Apenas arquivos com o marcador são
removidos; plugins e agentes de autoria do usuário estão sempre seguros.
cc2codex plugin-uninstall [cc-<nome> | --all] \
[--scope {global|project|all}] \
[--yes] [--non-interactive] [--json]
Ordem de exclusão:
- Cada TOML de agente listado em
x-cc-bridge.agents. - O próprio diretório
scope.plugins_dir/cc-<nome>/. - A entrada em
scope.registry(o arrayplugins[]demarketplace.json).
O arquivo marketplace.json em si nunca é removido, mesmo quando o array
fica vazio (plugins: []).
Esquemas JSON
plugin-browse --json
{
"marketplace": {
"name": "<string>",
"source": "<string>",
"sourceKind": "git|local",
"ref": "<string or null>",
"commit": "<string>"
},
"plugins": [
{
"name": "<string>",
"version": "<string>",
"description": "<string>",
"skillCount": 0,
"agentCount": 0,
"hasCodexManifest": true
}
]
}
plugin-sync --json
{
"scope": "global|project",
"synced": [
{
"bridgeName": "cc-<nome>",
"bridgeDir": "<caminho absoluto>",
"agents": ["cc_<plugin>_<agente>", "..."]
}
]
}
plugin-list --json
{
"scopes": {
"global": {
"pluginsDir": "<caminho>",
"agentsDir": "<caminho>",
"registry": "<caminho>",
"bridges": [
{
"name": "cc-<nome>",
"version": "<string>",
"sourcePlugin": "<nome origem>",
"source": "<url-ou-caminho>",
"sourceKind": "git|local",
"ref": "<string or null>",
"commit": "<sha or 'local'>",
"marketplace": "<nome do marketplace origem>",
"syncedAt": "<ISO-8601 UTC>",
"agents": ["cc_<plugin>_<agente>", "..."]
}
]
},
"project": { "...": "mesma estrutura" }
}
}
plugin-update --json
{
"updated": [
{"bridgeName": "cc-<nome>", "commit": "<sha>", "scope": "global|project"}
]
}
plugin-uninstall --json
{
"removed": [
{"bridge": "cc-<nome>", "agents": ["cc_<plugin>_<agente>", "..."], "scope": "global|project"}
]
}
Códigos de saída
| Código | Significado |
|---|---|
0 | Sucesso |
1 | Erro em tempo de execução (bridge não encontrada, conflito não resolvido, SyncConflictError, …) |
2 | Argumentos ausentes / inválidos (modo estrito, nome de plugin desconhecido, …) |
Formato do marcador x-cc-bridge
Escrito no primeiro nível de <scope.plugins_dir>/cc-<nome>/.codex-plugin/plugin.json:
{
"x-cc-bridge": {
"sourcePlugin": "<nome da origem sem prefixo cc->",
"source": "<url ou caminho absoluto>",
"sourceKind": "git|local",
"ref": "<branch/tag/sha or null>",
"commit": "<sha or 'local'>",
"marketplace": "<nome do marketplace.json origem>",
"syncedAt": "<ISO-8601 UTC>",
"tool": "cc-plugin-to-codex/<versao>",
"agents": ["cc_<plugin>_<agente>", "..."]
}
}
Comentário na primeira linha de cada TOML de agente bridge:
# x-cc-bridge: {"sourcePlugin":"<nome>","sourceAgent":"<nome-original>","bridgePlugin":"cc-<nome>","syncedAt":"..."}
name = "cc_<plugin>_<agente>"
description = "..."
developer_instructions = """..."""
Regras de detecção:
plugin.jsoné uma bridge se e somente se tiver um dicionáriox-cc-bridgeno primeiro nível.- Um TOML de agente é uma bridge se e somente se sua primeira linha corresponde à regex
^# x-cc-bridge: (\{.*\})$, o payload JSON analisa e as quatro chaves obrigatórias estão presentes.
Qualquer coisa sem correspondência é tratada como de autoria do usuário; a ferramenta não mexe.
--force é a única maneira de sobrescrever.