요약
cxc enable --help이 도움말을 출력하지 않고 enable을 그대로 실행한다. ~/.codex/config.toml을 수정하고 타임스탬프 백업까지 남긴다. 같은 경로를 타는 cxc disable --help / cxc uninstall --help는 반대로 플래그를 되돌리게 되므로 파급이 더 크다.
도움말을 보려던 호출이 상태를 바꾸는 건 놀람의 원칙 위반이고, 특히 에이전트가 CLI 표면을 탐색할 때 조용히 설정을 건드리게 된다.
환경
- Windows 11, Node v24.16.0, codex 0.135.0
- codexclaw 0.2.24+codex.20260908031619 (dev, 9cd5276)
- 플랫폼 무관한 argv 처리 문제로 보인다.
재현
$ cxc enable --help
codexclaw: enabled [default_mode_request_user_input]
config keys: memories.dedicated_tools
memories/{list,read,search,add_ad_hoc_note} 네 도구가 열립니다. ...
backup: C:\Users\super\.codex\config.toml.codexclaw-2026-09-10T12-04-54-836Z.bak
실제로 features.default_mode_request_user_input과 memories.dedicated_tools가 켜졌고 .bak 파일이 생성됐다. 도움말은 한 줄도 나오지 않는다.
disable 쪽은 파괴적이라 실행하지 않았고, 아래 코드 경로로만 확인했다.
원인
두 디스패처가 동일하게 나머지 argv를 버리고 서브커맨드만 하드코딩해서 넘긴다.
bin/codexclaw.mjs:462-471
case "enable":
process.exit(runConfigGuard(["enable"]));
break;
case "uninstall":
case "disable":
process.exit(runConfigGuard(["disable"]));
break;
case "status":
process.exit(runConfigGuard(["status"]));
break;
plugins/codexclaw/bin/cxc.mjs:165
process.exit(delegate(component, [cmd === "uninstall" ? "disable" : cmd]));
config만 예외적으로 process.argv.slice(2)를 통째로 넘기고, enable/disable/status는 단일 원소 배열로 고정된다. 그래서 --help는 config-guard에 도달조차 하지 못한다.
config-guard 쪽에도 갭이 있다. components/config-guard/src/cli.ts:41
if (action === undefined || action === "--help" || action === "-h" || action === "help") {
help 판정이 첫 인자에 대해서만 이뤄진다. 디스패처를 고쳐 ["enable","--help"]를 넘기더라도 action === "enable"이라 여전히 실행된다. 두 곳을 함께 고쳐야 한다.
영향
cxc enable --help: ~/.codex/config.toml 변경 + .bak 파일 생성. 반복 호출하면 백업이 계속 쌓인다.
cxc disable --help / cxc uninstall --help: 코드상 runConfigGuard(["disable"])로 직행하므로, 도움말 조회가 설치된 기능 플래그와 관리 키를 설치 이전 값으로 되돌린다.
cxc status --help는 읽기 전용이라 무해하지만 도움말이 안 나오는 건 마찬가지다.
- 최상위
cxc --help는 정상이라 사용자가 서브커맨드 도움말도 될 거라 기대하기 쉽다. 실제로 cxc orchestrate --help, cxc map --help는 동작한다.
제안
- 두 디스패처에서
enable/disable/uninstall/status도 process.argv.slice(2)를 그대로 전달한다.
- config-guard가 인자 위치와 무관하게
--help/-h를 먼저 검사하고, 해당 서브커맨드의 사용법과 부작용(어떤 키를 켜는지, 백업이 어디 생기는지)을 출력한 뒤 아무것도 하지 않고 종료하도록 한다.
- 상태 변경 커맨드 전반에 대해 "
--help가 있으면 부작용 없이 종료" 규칙을 회귀 테스트로 고정한다.
요약
cxc enable --help이 도움말을 출력하지 않고 enable을 그대로 실행한다.~/.codex/config.toml을 수정하고 타임스탬프 백업까지 남긴다. 같은 경로를 타는cxc disable --help/cxc uninstall --help는 반대로 플래그를 되돌리게 되므로 파급이 더 크다.도움말을 보려던 호출이 상태를 바꾸는 건 놀람의 원칙 위반이고, 특히 에이전트가 CLI 표면을 탐색할 때 조용히 설정을 건드리게 된다.
환경
재현
실제로
features.default_mode_request_user_input과memories.dedicated_tools가 켜졌고.bak파일이 생성됐다. 도움말은 한 줄도 나오지 않는다.disable쪽은 파괴적이라 실행하지 않았고, 아래 코드 경로로만 확인했다.원인
두 디스패처가 동일하게 나머지 argv를 버리고 서브커맨드만 하드코딩해서 넘긴다.
bin/codexclaw.mjs:462-471plugins/codexclaw/bin/cxc.mjs:165config만 예외적으로process.argv.slice(2)를 통째로 넘기고,enable/disable/status는 단일 원소 배열로 고정된다. 그래서--help는 config-guard에 도달조차 하지 못한다.config-guard 쪽에도 갭이 있다.
components/config-guard/src/cli.ts:41help 판정이 첫 인자에 대해서만 이뤄진다. 디스패처를 고쳐
["enable","--help"]를 넘기더라도action === "enable"이라 여전히 실행된다. 두 곳을 함께 고쳐야 한다.영향
cxc enable --help:~/.codex/config.toml변경 +.bak파일 생성. 반복 호출하면 백업이 계속 쌓인다.cxc disable --help/cxc uninstall --help: 코드상runConfigGuard(["disable"])로 직행하므로, 도움말 조회가 설치된 기능 플래그와 관리 키를 설치 이전 값으로 되돌린다.cxc status --help는 읽기 전용이라 무해하지만 도움말이 안 나오는 건 마찬가지다.cxc --help는 정상이라 사용자가 서브커맨드 도움말도 될 거라 기대하기 쉽다. 실제로cxc orchestrate --help,cxc map --help는 동작한다.제안
enable/disable/uninstall/status도process.argv.slice(2)를 그대로 전달한다.--help/-h를 먼저 검사하고, 해당 서브커맨드의 사용법과 부작용(어떤 키를 켜는지, 백업이 어디 생기는지)을 출력한 뒤 아무것도 하지 않고 종료하도록 한다.--help가 있으면 부작용 없이 종료" 규칙을 회귀 테스트로 고정한다.