cc2codex
CC 마켓플레이스 플러그인을 Codex와 동기화하는 CLI 도구입니다. 각 소스 플러그인은 cc-<이름> 브릿지가 되고, CC 에이전트 마크다운은 Codex TOML로 변환되며, 모든 아티팩트에는 x-cc-bridge 마커가 기록되어 목록 / 업데이트 / 제거 명령어로 일괄 관리할 수 있습니다.
설치
이 패키지는 PyPI에 게시되어 있습니다. 다음 중 하나의 호출 방식을 선택하세요 — 아래 예제는 cc2codex가 $PATH에 있다고 가정합니다.
-
uvx제로 설치 (권장, 항상 최신):uvx --from cc-plugin-to-codex cc2codex --help -
uv tool install(영구 설치):uv tool install cc-plugin-to-codex cc2codex --help -
일반 pip:
pip install cc-plugin-to-codex cc2codex --help
5가지 명령어
| 명령어 | 설명 |
|---|---|
plugin-browse | 소스 마켓플레이스가 제공하는 플러그인을 읽기 전용으로 나열 |
plugin-sync | 브릿지 설치: 파일 복사 + 에이전트 변환 + 레지스트리 업데이트 |
plugin-list | 설치된 브릿지 표시 (x-cc-bridge 마커로 식별) |
plugin-update | 마커에 기록된 소스에서 다시 동기화 |
plugin-uninstall | 마커로 브릿지 제거 |
핵심 개념
- 범위(Scope):
global=~/.codex/ ~/.agents/;project=$PWD/.codex/ $PWD/.agents/. 엄격 모드에서는--scope가 필수입니다. - 소스(Source):
.claude-plugin/marketplace.json이 포함된 Git URL (git@host:org/repo.git,https://…/repo.git,ssh://…,git://…, 또는git@host:path) 또는 로컬 체크아웃 경로입니다. Git 소스는/tmp에 클론된 후 정리됩니다.--ref는 브랜치, 태그 또는 커밋 SHA를 받습니다. x-cc-bridge마커: 브릿지plugin.json의 최상위 필드이며 모든 브릿지 에이전트 TOML의 첫 줄 주석입니다. 마커가 없는 파일은 사용자가 작성한 것으로 간주되며--force가 전달되지 않는 한 도구가 절대 덮어쓰지 않습니다.- 이름 규칙: 브릿지 이름은
cc-<소스-플러그인>; 에이전트 TOML 파일명은cc_<플러그인-스네이크>_<에이전트-스네이크>.toml입니다 (케밥-케이스 → 스네이크_케이스).
일반적인 워크플로우
하나 또는 모든 플러그인 동기화 (AI 친화적)
# 특정 플러그인
cc2codex plugin-sync \
--source https://github.com/your-org/cc-marketplace.git \
--plugin ios-dev --plugin base \
--scope global \
--non-interactive --yes
# 전체
cc2codex plugin-sync \
--source /path/to/cc-marketplace \
--all-plugins --scope global \
--non-interactive --yes
동일한 소스를 다시 동기화하는 것은 안전합니다. 이전 마커에 존재하지만 소스에 더 이상 없는 에이전트는 자동으로 정리됩니다.
⚠️
plugin-sync후 사용자는 Codex 내에서 브릿지를 설치해야 합니다.Codex는
~/.agents/plugins/marketplace.json을 핫 리로드하지 않습니다. cc2codex가 파일 쓰기를 완료한 후, 사용자는 Codex를 재시작하고 (또는 새 세션을 시작하고),/plugins를 실행한 뒤 새로 추가된 브릿지를 "CC Bridged Plugins" 마켓플레이스에서 선택하여 설치해야 합니다. 이 설치 단계가 실행될 때까지 Codex는 스킬과 에이전트를 로드하지 않습니다. 성공적인 동기화를 설명할 때는 항상 이 지침을 함께 제공해야 합니다.
상태 확인
cc2codex plugin-list # 사람이 읽기 쉬운 텍스트
cc2codex plugin-list --scope global --json # 기계가 읽기 쉬운 JSON
업데이트
cc2codex plugin-update cc-ios-dev --scope global --non-interactive --yes
cc2codex plugin-update --all --non-interactive --yes
--source를 다시 전달할 필요가 없습니다. 도구가 마커에서 읽어옵니다.
제거
cc2codex plugin-uninstall cc-ios-dev --scope global --non-interactive --yes
cc2codex plugin-uninstall --all --scope all --non-interactive --yes
플러그인 디렉토리 + 관련된 모든 에이전트 TOML + 레지스트리 항목을 제거합니다.
⚠️ Codex에는 자체 캐시가 있습니다. 제거는 절반만 완료합니다.
cc2codex는 자신이 작성한 파일만 제거합니다. Codex에는 cc2codex가 건드릴 수 없는 두 가지 추가 상태 위치가 있습니다:
~/.codex/plugins/cache/cc-bridged-plugins/<브릿지>/<버전>/— 사용자가/plugins install을 실행할 때 Codex가 브릿지를 여기에 복사하며, 런타임에 여기서 로드합니다.~/.codex/config.toml, 섹션[plugins."<브릿지>@cc-bridged-plugins"] enabled = true— Codex 자체의 활성화 상태입니다.결과적으로 cc2codex로 제거한 후에도 이전에 Codex 내부에 설치된 브릿지는 캐시에서 계속 로드됩니다. 제거가 성공했다고 설명한 후, 사용자에게 Codex 내에서
/plugins를 실행하고 동일한 브릿지를 제거하도록 지시하여 Codex가 자체 캐시와 구성을 정리하게 하세요.또는 수동으로:
rm -rf ~/.codex/plugins/cache/cc-bridged-plugins/<브릿지>를 실행하고~/.codex/config.toml에서 해당[plugins."…"]섹션을 삭제합니다.
엄격 모드 규칙 (중요)
TTY가 없거나 --yes / --json / --non-interactive 중 하나라도 전달되면 명령어는 엄격 모드로 실행됩니다. 엄격 모드에서는 모든 결정을 명시적으로 제공해야 합니다:
| 누락된 항목 | 오류 메시지 |
|---|---|
--source | source not specified; pass --source <git-url-or-path> |
--plugin 또는 --all-plugins | no plugins selected; pass --plugin <name> (repeatable) or --all-plugins |
--scope | `scope not specified; pass --scope global |
이름이나 --all 없이 uninstall/update | must specify a bridge name or --all to X (installed: …) |
AI나 스크립트에서 호출할 때는 모든 플래그를 미리 전달하세요. 기본값에 의존하지 마십시오.
대화형 모드
실제 TTY에서 플래그를 생략하면 questionary 선택기가 나타납니다:
- 소스 유형: Git URL / 로컬 경로 /
~/.claude/plugins/marketplaces/스캔 - 플러그인: 다중 선택 체크박스
- 범위: global / project
uninstall/update브릿지 대상: 다중 선택 체크박스
일반적인 함정
- 비브릿지 충돌: 대상 경로에 플러그인 디렉토리가 이미 존재하지만
x-cc-bridge마커가 없는 경우 → 거부됨 (사용자 작성 콘텐츠 보호).--force를 전달하여 재정의합니다. - 소스 전환 충돌: 동일한 이름의 브릿지가 이전에 소스 A에서 동기화되었고 지금 소스 B를 가리키는 경우 → 거부됨. 먼저
plugin-uninstall을 실행하거나--force를 전달합니다. - 플러그인 이름 vs 브릿지 이름:
--plugin은 소스 이름을 받습니다 (예:ios-dev), 브릿지 이름(cc-ios-dev)이 아닙니다.plugin-uninstall/plugin-update의 위치 인수는 브릿지 이름을 받습니다. - 레지스트리 정책: 각 레지스트리 항목은
installation: INSTALLED_BY_DEFAULT+authentication: ON_USE로 기록되므로 Codex는 설치 시 브릿지를 자동으로 활성화합니다. - 오래된 에이전트 정리는 안전함:
x-cc-bridge주석이 있는 TOML만 삭제되며, 직접 작성한 TOML은 그대로 유지됩니다.
전체 플래그 참조
공통 플래그
| 플래그 | 의미 |
|---|---|
--source <url-or-path> | Git URL (git@host:org/repo.git, https://…/repo.git) 또는 로컬 경로 (.claude-plugin/marketplace.json이 포함된 디렉토리). 대화형 선택을 위해 생략 가능. |
| `--ref <branch | tag |
--scope {global,project} | 대상 범위. global → ~/.codex/ ~/.agents/; project → $PWD/.codex/ $PWD/.agents/. plugin-sync의 엄격 모드에서 필수. |
--scope {global,project,all} | plugin-list, plugin-update, plugin-uninstall의 범위 필터. 기본값 all. |
--plugin <name> | 반복 가능. 소스 측 플러그인 이름을 받습니다 (cc- 접두사 없음). --all-plugins와 상호 배타적. |
--all-plugins | 소스가 제공하는 모든 플러그인 동기화. |
--all | 대상 범위의 모든 브릿지에 plugin-update / plugin-uninstall 적용. |
--yes | 확인 프롬프트 건너뛰기 (엄격 모드 암시). |
--non-interactive | 엄격 모드 강제 실행; stdin이 TTY가 아닐 때 자동 활성화. |
--force | 충돌 보호 우회 (비브릿지 덮어쓰기, 다른 소스). |
--json | stdout에 기계 판독 가능 JSON 출력 (엄격 모드 암시). |
plugin-browse
소스 마켓플레이스의 플러그인을 읽기 전용으로 나열합니다. 아무것도 쓰지 않습니다.
cc2codex plugin-browse --source <url-or-path> [--ref <ref>] [--json]
비대화형: --source 필수.
plugin-sync
핵심 설치 명령어. 파이프라인:
- 소스 확인 (Git은
/tmp에 클론, 또는 로컬 경로 읽기). <source>/.claude-plugin/marketplace.json을 읽어 사용 가능한 플러그인 목록 확인.--plugin/--all-plugins로 필터링.- 선택된 각 플러그인에 대해:
- 모든
agents/*.md사전 변환 (빠른 실패). - 에이전트 TOML 충돌 확인 (사용자 작성 →
--force없으면 거부). - 형제 디렉토리 스테이징 및 복사 (블랙리스트:
.claude-plugin/,.codex-plugin/,hooks/,commands/,agents/, VCS/빌드 노이즈 제외). x-cc-bridge마커와 최종 에이전트 목록이 포함된.codex-plugin/plugin.json작성.- POSIX 원자적 이름 변경으로 스테이징된 디렉토리를 기존 브릿지로 교체.
- 에이전트 TOML 작성 (1번 줄에
# x-cc-bridge: {…}주석). - 오래된 에이전트 제거 (이전 마커에는 있지만 새 목록에는 없는 것).
marketplace.json항목 업데이트 (policy.installation = INSTALLED_BY_DEFAULT).
- 모든
cc2codex plugin-sync \
--source <url-or-path> [--ref <ref>] \
--scope {global|project} \
{--plugin <name> [--plugin <name>] … | --all-plugins} \
[--force] [--yes] [--non-interactive] [--json]
비대화형: --source, --scope, --plugin|--all-plugins 모두 필수.
plugin-list
대상 범위의 모든 플러그인 디렉토리를 스캔하고 x-cc-bridge 마커가 있는 항목을 나열합니다.
cc2codex plugin-list [--scope {global|project|all}] [--json]
텍스트 모드는 각 범위의 pluginsDir / agentsDir / registry 경로와 에이전트 이름이 포함된 브릿지 목록을 출력합니다. JSON 모드는 동일한 데이터를 범위별로 그룹화합니다.
plugin-update
브릿지의 x-cc-bridge.source + .ref를 사용하여 소스를 다시 확인하고 동기화 파이프라인을 실행합니다. 소스 인수는 다시 필요하지 않습니다.
cc2codex plugin-update [cc-<name> | --all] \
[--scope {global|project|all}] \
[--force] [--yes] [--non-interactive] [--json]
- 위치 인수는 브릿지 이름입니다 (
cc-접두사 포함). --all은 대상 범위의 모든 브릿지를 업데이트합니다.- 엄격 모드에서 이름 /
--all이 없으면 설치된 브릿지를 나열하는 오류가 발생합니다.
plugin-uninstall
x-cc-bridge.agents에 의해 구동되는 정리. 마커가 있는 파일만 제거됩니다; 사용자가 작성한 플러그인과 에이전트는 항상 안전합니다.
cc2codex plugin-uninstall [cc-<name> | --all] \
[--scope {global|project|all}] \
[--yes] [--non-interactive] [--json]
삭제 순서:
x-cc-bridge.agents아래에 나열된 모든 에이전트 TOML.scope.plugins_dir/cc-<name>/디렉토리 자체.scope.registry의 항목 (marketplace.json의plugins[]배열).
marketplace.json 파일 자체는 절대 제거되지 않습니다, 배열이 비어 있더라도 (plugins: []) 마찬가지입니다.
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-<name>",
"bridgeDir": "<absolute path>",
"agents": ["cc_<plugin>_<agent>", "..."]
}
]
}
plugin-list --json
{
"scopes": {
"global": {
"pluginsDir": "<path>",
"agentsDir": "<path>",
"registry": "<path>",
"bridges": [
{
"name": "cc-<name>",
"version": "<string>",
"sourcePlugin": "<source name>",
"source": "<url-or-path>",
"sourceKind": "git|local",
"ref": "<string or null>",
"commit": "<sha or 'local'>",
"marketplace": "<source market name>",
"syncedAt": "<ISO-8601 UTC>",
"agents": ["cc_<plugin>_<agent>", "..."]
}
]
},
"project": { "...": "same shape" }
}
}
plugin-update --json
{
"updated": [
{"bridgeName": "cc-<name>", "commit": "<sha>", "scope": "global|project"}
]
}
plugin-uninstall --json
{
"removed": [
{"bridge": "cc-<name>", "agents": ["cc_<plugin>_<agent>", "..."], "scope": "global|project"}
]
}
종료 코드
| 코드 | 의미 |
|---|---|
0 | 성공 |
1 | 런타임 오류 (브릿지를 찾을 수 없음, 해결되지 않은 충돌, SyncConflictError 등) |
2 | 누락되거나 유효하지 않은 인수 (엄격 모드, 알 수 없는 플러그인 이름 등) |
x-cc-bridge 마커 형식
<scope.plugins_dir>/cc-<name>/.codex-plugin/plugin.json의 최상위에 기록됩니다:
{
"x-cc-bridge": {
"sourcePlugin": "<source name without cc- prefix>",
"source": "<url or absolute path>",
"sourceKind": "git|local",
"ref": "<branch/tag/sha or null>",
"commit": "<sha or 'local'>",
"marketplace": "<name from source marketplace.json>",
"syncedAt": "<ISO-8601 UTC>",
"tool": "cc-plugin-to-codex/<version>",
"agents": ["cc_<plugin>_<agent>", "..."]
}
}
각 브릿지 에이전트 TOML의 첫 줄 주석:
# x-cc-bridge: {"sourcePlugin":"<name>","sourceAgent":"<original-name>","bridgePlugin":"cc-<name>","syncedAt":"..."}
name = "cc_<plugin>_<agent>"
description = "..."
developer_instructions = """..."""
감지 규칙:
plugin.json은 최상위x-cc-bridge딕셔너리가 있는 경우 브릿지입니다.- 에이전트 TOML은 첫 번째 줄이 정규식
^# x-cc-bridge: (\{.*\})$과 일치하고, JSON 페이로드가 파싱되며, 네 가지 필수 키가 모두 있는 경우 브릿지입니다.
일치하지 않는 것은 사용자 작성으로 간주되며 도구는 건드리지 않습니다. --force만이 이를 재정의할 수 있는 유일한 방법입니다.