OpenAI Codex · Code Mode

새 기능은 먼저 crate를 찾아요. core는 마지막 칸.

저장소를 열면 첫 반응은 core에 넣는 거예요. 저장소는 그걸 금지로 적어 둡니다. 기존 non-core crate를 먼저 보고, 없으면 새로 만드세요. 의존 방향이 리프 타입을 핵심 밖으로 막습니다.

강의 목표읽고 나면 세 가지를 말할 수 있어요. 새 기능이 왜 기본으로 codex-core에 들어가면 안 되는지. 의존 방향이 어떻게 한 층 밖으로 막는지, 막힌 뒤 올바른 착지점은 어디인지. 이 금지에는 기계 빨간불이 없는데, 무엇으로 아직 돌아가고 있는지.
먼저 해보세요 · 새 기능이 앉을 crate 고르기
같은 새 기능: 먼저 핵심에 부딪히고, 규칙이 어느 층으로 미는지 보세요
새 기능
재생을 눌러 규칙이 어떻게 가는지 보세요. 왼쪽 crate를 직접 눌러 막히는지 봐도 돼요.
컴파일 그래프 위의 착지점0개 재컴파일
리프 · core 비의존
핵심 · 33만 줄, 86개 mod
core를 직접 의존하는 25개
간접 · client가 끌고 옴
이 단계의 판정대기
손에 든 기능브랜치 이름을 컨텍스트에
탐색 착지점아직 안 놓음
막는 규칙아직 안 켜짐
올바른 착지점규칙을 먼저 한 바퀴
시작을 기다려요.
논리 궤적 · 애니메이션 각 단계가 소스의 어느 구간인지
  1. workspace members는 명시 배열, 지금은 135개Cargo.toml L3
  2. 디렉터리는 core, crate 이름은 codex-coreAGENTS.md L4
  3. 금지: resist adding code to codex-coreAGENTS.md L76
  4. 기존 non-core crate에 살 수 있는지 먼저 묻기AGENTS.md L80
  5. 아니면 workspace crate를 새로 만들고 옛 코드 리팩터를 허용AGENTS.md L81
  6. 리뷰는 불필요하게 core로 가는 PR을 적극 막음AGENTS.md L83
  7. core는 이미 빼낸 context-fragments를 의존함core/Cargo.toml L35
  8. 비기계적 변경은 한 번에 800줄 이하AGENTS.md L127
새 기능을 고르고 재생을 누르세요. 어느 층에서 먼저 막히는지, 올바른 착지점은 어디인지 보세요.
막는 것은 기본 착지점core에 넣는 순간 직접 하류 25개와 core 자신이 다시 컴파일돼요. tui도 client를 타고 끌려옵니다. 리프 타입을 핵심에 용접하면, 재사용하려면 샌드박스와 Guardian까지 같이 끌어와야 해요.
올바른 착지점은 리프기존 non-core crate에 살 수 있으면 거기 사세요. 안 되면 crate를 새로 만들고 옛 코드를 리팩터하세요. core는 이미 그 리프들을 의존하니, 호출 쪽이 될 수 있어요.
마지막 칸도 설명은 필요해요session 내부 상태를 꼭 만져야 하면 core에 들어가도 돼요. 리뷰는 그래도 왜 못 빼내는지 묻습니다. 금지는 습관을 막고, 이유 있는 예외는 못 막아요.
수업용 스케치: 재컴파일 수는 core 자신과 직접 하류 25개로 어림잡아, 의존 변이 어디까지 번지는지 보여 줍니다. tui는 간접으로 표시. 궤적 오른쪽 행 번호는 openai/codex 저장소 commit 4f39251a01에 대응해요.
아이디어 1 · 새 개념은 먼저 착지점을 찾고, core는 마지막 칸
어떤 문제를 푸는가

이 agent에 작은 기능을 넣고 싶어요. 매 턴 시작에 현재 git 브랜치 이름을 모델 컨텍스트에 쓰는 것. 저장소를 열면 첫 반응은 codex-core에 넣는 겁니다. session, context, guardian, tools가 다 거기 있어요. 새 파일을 넣는 게 제일 싸죠. 의존 표도 안 고치고, 호출 사슬도 crate를 넘지 않아요.

일주일이 지나면 같은 이유로 세 개가 더 들어와요. 도구 출력을 자르는 helper, 모델 공급자 어댑터, 세션 복구의 구석. core/src/lib.rs 꼭대기에 mod가 또 셋. 하류는 use codex_core만 쓰면 되고, 컴파일 그래프는 넓어집니다. 누군가 컨텍스트 조각 타입만 재사용하려다 core에 용접된 걸 봐요. 재사용하려면 core 전부, 샌드박스·MCP·Guardian까지 끌어와야 해요.

아이디어는 무엇인가

저장소는 이걸 금지로 적어요. AGENTS.md는 굵은 영어로 resist adding code to codex-core라고 씁니다. 새 개념은 기존 non-core crate에 살 수 있는지 먼저 물어요. 그다음 workspace crate를 새로 만들지, 그리고 그걸 위해 옛 코드를 리팩터해도 되는지. core는 마지막 칸. 리뷰는 core에 기능을 쌓는 PR을 적극 되돌리라고 요구받아요.

출처: AGENTS.md 72–83행

새 개념 crate가 필요해요 기존 non-core crate 여기 살 수 있나 그 crate에 넣기 되면 거기 살기 새 crate 경계가 분명하면 만들고 리팩터 안 됨 마지막 칸 core 리뷰는 계속 물어요
교육용 구조도: 입력은 새 개념, 출력은 착지점. core는 두 길이 다 막힐 때만 나타나요.

금지가 파일에 적힌 날은 2026-03-26. 그때 이미 core가 가장 큰 crate였어요. 세운 뒤 workspace 멤버는 75에서 135로 늘었고, core 생산 코드도 여전히 늘었습니다. 막는 것은 기본으로 핵심에 던지는 습관이지, 핵심이 계속 크는 것은 못 막아요.

명단은 명시 배열이에요. codex-rs/Cargo.tomlmembers를 세면 135. 디렉터리 이름과 crate 이름은 따로 보세요. 디렉터리는 core, 패키지 이름은 codex-core, use할 때는 codex_core.

출처: codex-rs/Cargo.toml 1–20행; AGENTS.md 1–5행; codex-rs/core/Cargo.toml 1–9행

.rs 줄 수로 보면 소수 crate가 부피 대부분을 먹어요. core 33만, tui 27만, app-server 14.8만. 1만 줄 이상이 24개, 2천 미만이 77개. 테스트를 빼면 core는 약 10.3만 줄. workspace 멤버 25개가 직접 의존합니다. tui의 Cargo.toml에는 그 줄이 없어요. codex-app-server-client를 의존하고, client가 core를 끌어옵니다. core에 한 줄 넣으면 직접 하류 25개가 재컴파일되고, tui도 끌려와요.

출처: codex-rs/cli/Cargo.toml 41–42행; codex-rs/tui/Cargo.toml 30–31행

왜 오래 성립하는가

신 패키지의 실패 모드는 “이번엔 작으니까 핵심에 먼저”예요. 기본 착지점을 평범한 글로 적어 리뷰가 막을 권한을 갖게 하세요. 언어에 기대지 않습니다. 다른 언어로 다시 써도 최소 형태는 이 세 질문이에요. 기존 패키지에 살 수 있나, 새 패키지를 만들어야 하나, 핵심에 들어간다면 왜 못 빼내나.

아이디어 2 · 리프 타입은 리프 crate에 남아요
어떤 문제를 푸는가

의존 방향이 뒤집히면 컴파일 그래프가 양쪽에서 부풀어요. core는 이미 codex-* crate 61개를 의존하고, 빼낸 context-fragmentsfeatures도 포함됩니다. 새 컨텍스트 타입을 다시 core에 쓰면, 재사용하려는 사람은 샌드박스와 Guardian까지 같이 끌어와야 해요. 리프가 핵심을 의존하고 핵심이 다시 리프를 의존하면, 경계는 사라집니다.

아이디어는 무엇인가

빼낸 crate는 자기에게 필요한 것만 가져요. context-fragments 패키지 목록에는 비즈니스 의존이 거의 없고, protocol과 문자열 유틸만 만지며, 조각 타입 둘과 trait 하나를 re-export합니다. core는 그걸 의존할 수 있고, 그건 core를 의존하지 않아요. git 브랜치 이름 같은 조각은 이 길로 갑니다. 타입은 fragments에 두고, core는 호출 쪽. 모델 공급자 어댑터는 이미 codex-model-provider로 빠졌어요. session 내부를 꼭 만져야 하는 것만 마지막 칸으로 가고, 리뷰는 그래도 왜 못 빼내는지 묻습니다.

출처: codex-rs/context-fragments/src/lib.rs 1–6행; codex-rs/core/Cargo.toml 26–42행

리프 crate fragments / features core가 리프를 의존 codex-core 호출은 돼요. 도로 삼키면 안 돼요. 직접 하류 25개 cli / app-server / ext 타입을 core에 용접하면 재사용 비용이 중심 전부 끌어오기가 돼요 타입을 리프에 두면, 필요한 사람만 그 작은 패키지를 의존해요
교육용 구조도: 화살표는 중심에서 리프를 향할 수만 있어요. 리프는 core를 되돌아 의존하면 안 됩니다.

옆에 자가 두 개 더 있어요. 파일 목표는 500줄, 대략 800을 넘으면 새 모듈. 비기계적 변경은 한 번에 800줄 이하, 복잡한 로직은 500까지. 세 층을 같이 보면 같은 일을 겨냥해요. 사람과 AI 모두 이미 큰 파일에 변경을 크게 쓰려 합니다.

출처: AGENTS.md 49–61행; AGENTS.md 125–131행

이 금지 자체에는 lint도 CI job도 없어요. 저장소에서 resist adding code to codex-core를 찾으면 AGENTS.md 한곳뿐입니다. 실제로 막는 것은 옆의 조항들이에요. Bazel lock을 안 갱신하면 CI가 빨개지고, include_str!인데 BUILD.bazel을 안 고치면 Bazel이 빨개집니다. core 금지는 습관을 막고, 이유 있는 예외와 놓친 눈은 못 막아요.

출처: AGENTS.md 37–43행

core는 마지막 칸이지, 기본 칸이 아니에요.
왜 오래 성립하는가

컴파일 그래프의 방향은 물리 제약이에요. 리프는 혼자 컴파일되고 여러 중심이 재사용할 수 있습니다. 중심이 리프 타입을 삼키면, 재사용 비용이 중심 전부 끌어오기가 돼요. 이 모양은 언어를 바꿔도 성립합니다.

가로 비교 · 같은 문제의 다른 답

DSH: 능력은 전부 플러그인, 특권 커널은 없어요

DSH 루트 AGENTS.md는 원칙을 굵은 영어로 적어요. everything is a plugin. Cordis는 서비스·타입화된 이벤트·되돌릴 수 있는 부작용만 받습니다. 모델 어댑터, 도구 레지스트리, 세션 로그, agent loop가 전부 플러그인이에요. 패치해야 하는 특권 커널은 없습니다. 새 패키지가 기존 그룹에 들어가면 루트 package.json은 안 고치고, glob이 찾아요.

Codex는 그 착탈기를 컴파일기 crate로 바꿨어요. 새 능력은 members 배열을 고치고 BUILD.bazel을 쓰고 다시 컴파일해야 합니다. 손댈 자리는 리뷰와 CI뿐이에요. 리뷰는 core에 들어가도 되는지, CI는 잠금 두 개를 같이 고쳤는지 봅니다.

양쪽 모두 소스 대조 완료 · 2026-08-22 · DSH · 플러그인 패키지

Grok Build: 명단은 자동 생성, 계층은 디렉터리

Grok 루트 Cargo.toml 첫 줄은 이 workspace가 생성된 것이라고 밝히고, 사람은 각 crate 자기 명단을 고치라고 해요. 같은 기준으로 members를 세면 79. 조직은 루트 README에 있습니다. pager는 TUI, shell은 런타임, tools와 workspace는 도메인 능력, common / build는 리프.

리뷰가 읽으라고 쓴 core 금지는 없어요. 분할 자체가 지도입니다. 팽창은 조합 입구와 crate 추출로 소화해요. Codex가 더 내는 것은 리뷰 텍스트와 이중 빌드 잠금이에요.

양쪽 모두 소스 대조 완료 · 2026-08-22 · Grok · workspace 멤버 79개
수업 실습
01

도구 출력을 자른다면, 어디에 둘까요

작은 기능이 또 와요. 도구 반환이 너무 길면 먼저 자르고 모델에 넘기는 것. helper처럼 보이니 core의 tools 옆에 두는 게 제일 싸죠. 방금 세 질문으로 밀어 보세요. 기존 non-core crate에 더 맞는 집이 있는지, 문자열 유틸만 담는 작은 패키지를 만들어야 하는지, core에 넣으면 어느 의존 변이 막히는지.

어느 변을 막을지, 막은 뒤 올바른 착지점을 적으세요. 마지막 칸을 고르면 리뷰가 무엇을 물을지 한 줄 보태세요.

Takeaway: 새 개념은 기존 non-core crate를 먼저 찾고, 없으면 crate를 만들며 리팩터하세요. core는 마지막 칸. 리뷰는 핵심으로 가는 PR에 왜 못 빼내는지 꼭 물어야 해요. 리프 타입을 리프 crate에 둬야 컴파일 그래프가 양쪽에서 부풀지 않습니다.