Codex CLI 설정
Codex CLI 호환 레이어와 프로젝트 스킬 발견 문제를 다룹니다.
작성 기준
- 확인 날짜: 2026-09-05
- 확인 버전: codex-cli 0.153.4 (codex-pin.json/runtime 일치 — 값의 SoT는 codex-pin.json; nix overlay — OpenAI 공식 릴리스 직핀; #890에서 mise npm backend → nix 이관)
- 재검증:
jq -r .version modules/shared/programs/codex/codex-pin.json && codex --version && codex --help
목적과 범위
~/.codex/config.toml실행 정책(approval_policy,sandbox_mode) 및 모델 설정AGENTS.md/.agents/skills투영 구조.agents/skills/*디렉토리 심링크 검증nrs(또는 동등 activation) 이후 결과 검증- Claude Code / Codex CLI 등 AI 에이전트별 동작 차이 정리
빠른 진단 체크리스트
.agents/skills/*이 디렉토리 심링크인지 확인 (ls -la .agents/skills/)- 프로젝트 루트
AGENTS.md -> CLAUDE.md심링크 확인 (git-tracked) ./scripts/ai/verify-ai-compat.sh실행- 문서화된 runtime recognition 검사로
codex exec에서 스킬 이름이 보이는지 확인 - 권한 프롬프트 이슈는
approval_policy,sandbox_mode설정으로 분리 진단
런타임 라우팅과 노출 경계
| 세션 | 기본 실행 경로 |
|------|----------------|
| Direct Codex | native subagent. using-codex-exec은 자기 참조 방지를 위해 의도적으로 노출하지 않으며 직접 호출 대상이 아니다. |
| Claude Code | codex exec subprocess. using-codex-exec은 이 경로를 위한 adapter 문서다. |
| headless | codex exec subprocess를 foreground serial로 실행한다. |
위임 권한과 실행 경계는 프로젝트의 AGENTS.override.md를 따른다. 현재 세션이 제공하는 도구와 동시 실행 상한을 확인한다.
Shared skill 노출 정책의 SoT는
default.nix의 exposedCodexSkills와
intentionallyNotExposed다. verify-ai-compat.sh는
그 목록과 project directory projection을 독립적으로 감사하는 oracle이다.
request_user_input Default Mode 활성화
codex 0.106+에서 default (code) collaboration mode에서도 request_user_input 도구 사용 가능 (openai/codex#10384, PR openai/codex#12735). 본 nixos-config는 자기 환경 한정으로 활성화 가정.
활성화 절차:
modules/shared/programs/codex/files/config.toml및config.darwin.toml의[features]섹션에default_mode_request_user_input = true확인 (commit b94fd06에서 추가됨).codex --version이 0.106+ 인지 확인.nrs후~/.codex/config.toml에 flag가 반영되었는지 확인.
검증:
- codex 세션 default mode에서
use request_user_input to ask me ...로 invoke 시 tool call이 실제 발생하는지 (plain-text 응답이 아닌지) 관찰. - 0.106 release 댓글에 따르면 default mode 모델은 "make assumptions and only stop if blocked" 정책으로 자동 호출하지 않으므로, 인터뷰 기반 스킬 본문에 명시적 사용 지시가 있어야 한다.
- 옵션 개수/Recommended 라벨은 schema/server enforcement가 아니라 codex tool description의 LLM convention이다 (codex 0.128 main fact-check 기준 —
tools/src/request_user_input_tool.rs의 JSON Schema description 문자열에 "2-3 choices", "recommended option first" 가이드 존재). PR openai/codex#12735는 mode 가용성만 확장하고 schema는 미변경. prompt template 차원에서는 mode별 차이 있음 (plan.md만 "2-4 options + recommended default" 명시).
핵심 파일
modules/shared/programs/codex/default.nix— 설정, shared skill 노출 정책 SoT, project 스킬 투영 activation 배선modules/shared/programs/codex/files/project-codex-skills.sh— project 스킬 투영과 고아 링크 정리 본체modules/shared/programs/codex/files/config.toml— 실행 정책/모델 설정 (NixOS)modules/shared/programs/codex/files/config.darwin.toml— macOS 전용 설정 (user-scope MCP 포함)modules/shared/programs/codex/files/retired-config-keys.txt— 배포본에서 회수할 퇴역 키 목록 SoT (activation·nrs 복구·verify가 공유)scripts/ai/verify-ai-compat.sh— 노출 정책 및 directory projection 독립 감사 oraclemodules/shared/programs/claude/files/CLAUDE.md— 글로벌 라우팅/지침.claude/skills/*(원본).agents/skills/*(Codex 발견용 투영)
설치/업데이트 경로
Codex CLI 바이너리는 declarative nix overlay로 설치한다 (modules/shared/programs/codex/package.nix,
libraries/packages.nix의 shared 경유; macOS+NixOS 공통; #890에서 mise npm backend → nix 이관).
overlay는 OpenAI 공식 GitHub 릴리스의 prebuilt를 직접 핀한다 — nixpkgs lag(수 주)이나
제3자 flake 신뢰 없이 최신 codex를 추적하기 위함이다. 설치 소스는 upstream이 조립·검증해
발행하는 codex-package 통합 tarball 하나다 (#1219 — codex + code-mode host 사이드카
codex-code-mode-host + 번들 rg/zsh 동봉; linux=musl, darwin=signed macho라 소스 컴파일·patchelf
없음). overlay는 tarball 전체를 $out/libexec/codex/에 풀고 $out/bin/codex symlink만
노출한다 — codex가 canonical 실행 경로 옆 codex-package.json으로 package layout을 인식해
사이드카·번들 도구를 libexec 실경로에서 찾는다. 구성 요소 열거는 upstream 소관이라, 릴리스가
구성 요소를 추가/분리해도 저장소가 추적할 필요 없다(#1220 반쪽 설치 장애 클래스의 구조적 해소;
mise shim의 비대화형 PATH fragility 회피가 이관 동기 — #815/#821/#823/#845/#858).
- 버전 SoT:
modules/shared/programs/codex/codex-pin.json(version/tag + flake systems 2개 (aarch64-darwin·x86_64-linux)의 codex-package asset/hash 각 1쌍). version/tag/hash는update-codex로 bump하고, platforms/asset 키는 정적 설정이라 손으로 관리한다. - 설치/정리 코드 SoT:
default.nix의 정리 activation 3종(cleanupLegacyCodexCli,cleanupMiseCodexShim,cleanupManualNodeCodex). 이들은 codex를 설치하지 않고, 과거 설치 방식 (GitHub ELF/brew cask, mise npm backend shim, 수동 npm 글로벌) 잔재가 PATH에서 codex(nix profile)를 shadow하지 못하게 정리만 한다. - NixOS MiniPC의 Codex App mobile remote-control은 예외적으로 별도 standalone package를
~/.codex/packages/standalone/current/아래에 둔다. 이 standalone은 app-server payload 전용이며, 일반command -v codex를 shadow하면 안 된다. 특히~/.local/bin/codex -> ~/.codex/packages/standalone/...symlink는 회귀로 취급하고codex-remote-control-ensure.service/verify-ai-compat.sh가 제거 또는 실패 처리한다.
업데이트(한 줄로 최신 stable):
update-codex # 최신 stable로 codex-pin.json bump + nrs
update-codex --pre # alpha/prerelease 포함 최신
update-codex --no-build # 핀만 갱신(nrs 생략)
update-codex는 OpenAI 릴리스에서 최신 rust-vX.Y.Z를 찾아 핀된 플랫폼 해시를 prefetch해
codex-pin.json을 갱신하고 nrs로 적용한다(mise 미호출). 갱신 후 codex-pin.json 변경을 커밋한다.
nix는 lock 기반이라 "자동 최신"은 없고 — update-codex 한 줄이 그 역할을 한다.
왜 nixpkgs가 아니라 직접 overlay인가
nixpkgs codex는 cache.nixos.org prebuilt가 있어 편하지만 upstream 대비 수 주 lag이 있고, codex는
릴리스가 매우 잦아 lag이 실사용에 거슬린다. 그래서 OpenAI 공식 릴리스를 직접 핀해 lag 0 + 제3자
flake 신뢰 0 + 컴파일 0(prebuilt fetch)으로 간다. 대안(nixpkgs lag / 커뮤니티 flake codex-cli-nix의
단일 메인테이너 신뢰)은 트레이드오프가 있어 채택하지 않았다. config가 요구하는 feature floor(현재
0.124+ stable hooks, #585/#584)는 항상 직핀 최신이 충족한다.
npm install -g @openai/codex 금지:
node는 mise에 남으므로(codex만 부분 폐기, #890) 수동 글로벌이 ~/.local/share/mise/installs/node/<ver>/bin에
깔리면 PATH상 nix profile보다 앞서 codex를 가린다. 다음 nrs의 cleanupManualNodeCodex가
각 node 버전 prefix의 npm으로 env PATH="$node_prefix/bin:${pkgs.mise}/bin:$PATH" "$npm_bin" uninstall -g @openai/codex를
반복 호출해 수동 글로벌을 제거하므로, codex가 사라지거나 꼬인 것처럼 보인다.
(lts/24/latest 같은 symlink 별칭 디렉토리는 [ ! -L ] 가드로 제외해 중복 uninstall을 막는다.)
진단 — codex shadow가 의심되면 PATH 첫 매치를 확인한다:
whence -p codex # PATH 첫 매치 (nix profile/store여야 정상; mise shims 경로면 잔존 shim 회귀)
type -a codex # 모든 후보 (node/<ver>/bin이 앞이면 수동 글로벌 잔재)
readlink -f ~/.codex/packages/standalone/current/bin/codex # remote-control standalone 예외 경로
검증: codex --version, ./scripts/ai/verify-ai-compat.sh(codex PATH resolve 가드 포함).
잔존 mise codex shim이 PATH 앞에서 codex(nix profile)를 가리는 회귀는 managing-mise의 셸 활성화 구조를 참조한다.
진단 우선순위 (중요)
Skills 누락 이슈의 1차 원인은 trust보다 투영 방식이다.
Codex CLI는 디렉토리 심링크를 따라가지만 파일 심링크는 무시한다 (PR #8801).
.agents/skills/<name>은 반드시 디렉토리 심링크여야 하며, SKILL.md 파일 자체를 심링크하면 안 된다.
실행 정책 / Trust 메모
codex-cli 0.153.4 기준으로 codex --help에 codex trust 독립 서브커맨드는 확인되지 않았다
(재검증: command codex --help | grep -cE '^\s+trust' → 0).
권한 프롬프트 동작은 전역 실행 정책으로 제어한다.
approval_policy = "never"
sandbox_mode = "danger-full-access"
프로젝트 trust의 SoT는 사용자 승인에 의한 디렉토리별 runtime mutation이다. Nix template은
trust를 하드코딩하지 않고 runtime-owned config.toml의 [projects.*] 엔트리를 보존한다.
선언 소유 vs 앱 소유 (config.toml)
~/.codex/config.toml은 nix 템플릿과 Codex 앱이 함께 쓰는 파일이다. sync는 템플릿이 선언한 leaf만
덮어쓰고(template-owned) 나머지는 보존한다(user-owned). 앱 UI가 쓰는 키를 템플릿에 두면 nrs마다
되돌아가 UI 선택이 무효가 되므로, 경계는 다음과 같이 둔다 (2026-09-05 결정).
| 소유 | 키 | 근거 |
|------|----|------|
| 템플릿(선언) | approval_policy, sandbox_mode, [features], [agents], [[hooks.*]], [notice] | 정책·안전 경계. 사용자가 UI로 바꾸는 값이 아니다 |
| 앱(UI persist) | model, model_reasoning_effort, service_tier | Desktop/TUI 선택이 최상위 키로 기록됨. 템플릿에서 제거 |
| 앱(런타임 상태) | [projects.*], tui, desktop, memories, plugins, skills, marketplaces, notify, mcp_servers | 앱이 생성·갱신. 템플릿은 선언하지 않는다 |
템플릿에서 키를 지워도 배포본에는 user-owned로 남는다. 배포본에서까지 영구 회수해야 하는 정책 키는
retired-config-keys.txt에
등록한다 — 그러면 nrs가 activation과 NO_CHANGES 복구 양쪽에서 제거하고, verify-ai-compat.sh가
잔존을 retired_key_present drift로 잡는다. 등록한 키를 템플릿이 다시 선언하면 스크립트가
EXIT_ERROR로 막는다(선언과 회수가 겹치면 sync가 매번 썼다 지우고 check가 영원히 drift를 내
수렴하지 않으므로). 목록은 두 플랫폼 템플릿 공용이라 양쪽 모두 선언하지 않는 키만 넣는다.
앱 소유 키(model, model_reasoning_effort, service_tier)는 이 목록에 넣지 않는다 — 영구 회수는
매 nrs마다 사용자의 UI 선택까지 지운다. 이 키들의 옛 템플릿 pin 잔재는 "1회만 지우고 그 뒤로는
보존"이라 회수 메커니즘으로 표현할 수 없으므로 호스트별 1회 수동 삭제로 처리한다(절차는 config
템플릿 헤더 주석).
트러블슈팅 / FAQ
- 스킬이 안 보임:
.agents/skills/*가 파일 심링크인지 확인하고 디렉토리 심링크로 교정한다.nrs출력에Warning: keeping .agents/skills/<name>이 있으면 그 자리의 실디렉토리·파일이 투영을 막고 있다 — 처리 규칙은 아래 "투영 아키텍처"를 따른다. MiniPC(NixOS)에서는 activation이home-manager-<primaryUser>서비스로 돌아 이 경고가nrs출력이 아니라 journal로 가므로,journalctl -u home-manager-<primaryUser>에서 확인하거나 메인 체크아웃의verify-ai-compat.sh로 확인한다. - 권한 프롬프트 반복:
~/.codex/config.toml의approval_policy,sandbox_mode를 확인한다. - AGENTS 불일치:
AGENTS.md자리가 일반 파일이나 실디렉토리면nrs가 보존하고Warning: keeping AGENTS.md를 stderr로 남긴다. 내용을 확인해 필요한 수정은CLAUDE.md에 반영하고 해당 파일·디렉토리를 옮기거나 지운 뒤nrs로 심링크를 복구한다. 검증기도 보존된 자료와 링크 누락을 구분해 안내한다. 정상 링크·다른 대상의 링크·링크 부재는 자동으로 수렴한다. - 활성화 누락:
nrs실행 후./scripts/ai/verify-ai-compat.sh로 재검증한다. - codex 업데이트가 안 됨: codex는 nix overlay라 버전이
codex-pin.json에 핀된다 — 최신화는update-codex한 줄(자동 추적 아님).npm install -g @openai/codex는cleanupManualNodeCodex가 제거하므로 사용하지 않는다 (whence -p codex로 PATH 잔재 확인 — nix profile/store 경로여야 정상).
투영 아키텍처
.claude/skills/<name>/ # 단일 원본 (SKILL.md, references/ 등)
-> directory symlink
.agents/skills/<name>/ # ../../.claude/skills/<name> 심링크
Codex CLI는 디렉토리 심링크를 follow_links(true)로 순회한다 (PR #8801).
파일 심링크는 무시되므로 반드시 디렉토리 단위로 심링크해야 한다.
투영은 원본마다 .agents/skills/<name> 자리를 본다. 올바른 관리 링크면 그대로 두고, 없으면 만들고,
다른 대상을 가리키는 심링크면 링크만 관리 링크로 바꾼다(링크 대상은 건드리지 않는다). 그 자리의
실디렉토리와 파일은 git 추적 여부와 관계없이 지우지 않는다.
SKILL.md가 git 추적인 실디렉토리:Skipping ... (run 'git pull' first)를 출력한다. 심링크 전환 커밋을 받기 전에nrs가 먼저 돈 경우이므로git pull뒤nrs를 다시 실행한다.- 그 밖의 실디렉토리(전부 미추적,
SKILL.md만 미추적,SKILL.md없음)와 파일: 원인과 조치 (review its contents, move or delete it, then rerun nrs)를 담은Warning: keeping .agents/skills/<name>경고를 stderr로 남기고 rc는 0이다. 사용자 자료일 수 있으므로 내용을 확인해 옮기거나 지운 뒤nrs를 다시 실행한다. 정리 전까지 그 스킬은 Codex에 투영되지 않고verify-ai-compat.sh가 실패로 보고한다. - 추적 판정 명령 자체가 실패한 실디렉토리: 미추적으로 보지 않고 보존한다. 경고의 원인은
cannot tell whether it is git-tracked (git ls-files exit <rc>)이고 조치는 위와 같다.
고아 정리는 activation이 만든 관리 링크(../../.claude/skills/<name> 상대 심링크) 중
원본이 사라진 것만 지운다. 원본 없는 실디렉토리와 다른 대상을 가리키는 링크는 지우지 않고
Warning: keeping .agents/skills/<name> 경고만 남긴다 — verify-ai-compat.sh가 이를 계속
고아 투영으로 보고하므로, 옮기거나 지우는 판단은 사람이 한다. 절대경로 target이면서
SKILL.md에 접근 가능한 플러그인 스킬 링크는 검증기와 같은 기준으로 경고 없이 보존한다.
활성화
원칙은 nrs 실행이다.
환경 제약으로 nrs를 실행하지 못하면, Codex 모듈 activation과 동등한 절차로 재생성해도 된다.
그 절차는 저장소 루트에서 DRY_RUN_CMD='' bash modules/shared/programs/codex/files/project-codex-skills.sh "$PWD"다.
DRY_RUN_CMD=echo면 변경 명령만 출력하고, DRY_RUN_CMD를 생략하거나 git을 찾지 못하면 아무것도 바꾸지 않고 실패한다.
검증 명령
# 구조 검증
./scripts/ai/verify-ai-compat.sh
# 디렉토리 심링크 검증 (모두 심링크여야 함)
for d in .agents/skills/*; do
[ -L "$d" ] && echo "OK: $(basename $d) -> $(readlink $d)" || echo "FAIL: $(basename $d)"
done
# 런타임 인식 검증
codex -a never exec "Answer YES or NO only: Is a skill named 'configuring-codex' available in this workspace?"
관련 계약
- Direct Codex 위임 권한과 실행 경계: AGENTS.override.md
레퍼런스
- 상세 장애 기록 및 회귀 체크:
references/runbook-codex-compat.md
문서와 CLI 동작이 다를 때는 CLAUDE.md의 "스킬 문서 불일치 시 행동 원칙"을 따른다.