다 끝나면 Codex CLI는 osFoundry의 GitNest 저장소에서 두 가지 일을 할 수 있다. 터미널 세션에서 만든 파일을 브랜치에 넣는 것, 그리고 다 만들어진 체인지셋을 PR로 내보내는 것이다. PR은 GitNest 안에서 열 수도 있고 GitHub나 GitLab에 드래프트로 열 수도 있다. Codex가 직접 커밋하거나 push하는 건 없다. 일은 하나하나 Codex CLI 연결의 "Needs your approval" 아래 카드로 올라오고, 카드에는 파일, 브랜치, 정확한 커밋이 찍혀 있다. 저장소 오너가 누르기 전까지는 아무 일도 안 일어난다.
누가 뭘 하나
| Codex CLI | osFoundry | |
|---|---|---|
| 로그인 | 내 Codex 로그인. osfoundry:read, osfoundry:write가 든 osFoundry OAuth 토큰을 Codex가 들고 있다 | 오너가 Connected 탭에서 연결을 한 번 승인했다 |
| 보낼 수 있는 것 | 브랜치 하나에 UTF-8 파일 최대 20개, 합계 200 KB. 또는 버전과 합성 커밋에 고정된 체인지셋 ID | 요청마다 만료 시각이 붙은 제안으로 저장 |
| 승인하는 사람 | 쓰기 호출 전마다 Codex가 나한테 묻는다(default_tools_approval_mode = "writes") | 저장소 권한을 아직 가진 연결 오너가 Approve and create나 Approve and publish를 누른다 |
| 실제로 쓰는 쪽 | Codex 쪽에선 아무도 안 쓴다 | 승인 뒤에 osFoundry가 커밋하거나 PR을 연다 |
| 프로바이더 토큰 | 절대 안 넘어간다 | 승인할 때 오너가 연결해 둔 GitHub/GitLab 계정을 쓰고, 체인지셋 전용 브랜치에만 쓴다 |
| 머지 | 손이 안 닿는다 | GitNest든 프로바이더든 사람 몫으로 남는다 |
세팅
1. Codex가 쓰는 툴을 GitNest 쪽으로 좁히기
연결은 평소대로 만든다. 헤더의 열쇠 아이콘, Connected 탭, Other MCP client를 고르고 표시 이름에 Codex CLI 같은 걸 넣는다. 카드나 알림마다 이 이름이 나오니까 오너가 바로 알아볼 이름이 좋다.
Codex 쪽 설정은 이렇다.
codex mcp add osfoundry --url https://api.osfoundry.io/api/v1/external-mcp # ~/.codex/config.toml [mcp_servers.osfoundry] url = "https://api.osfoundry.io/api/v1/external-mcp" scopes = ["osfoundry:read", "osfoundry:write"] default_tools_approval_mode = "writes" enabled_tools = [ "list_granted_resources", "read_gitnest_repository", "list_gitnest_work", "list_gitnest_checks", "propose_gitnest_file_import", "propose_gitnest_native_publication", "propose_gitnest_provider_publication", ] codex mcp login osfoundry 서버에는 툴이 59개 있는데, 이 글에서 쓰는 건 위의 7개다. propose_로 시작하는 3개만 읽기 전용 표시가 없어서, "writes"로 두면 Codex는 읽기 툴 4개는 알아서 돌리고 제안을 낼 때마다 멈춰서 나한테 묻는다. 그러니까 승인이 두 번 이어진다. 터미널에서 내가 한 번, osFoundry에서 오너가 한 번. 내가 오너라면 첫 번째는 Codex가 내가 생각한 걸 요청하려는지 확인하는 정도로 보면 된다.
2. 연결이 들어 있는 프로젝트에 저장소 넣기
연결은 프로젝트를 통해서만 GitNest 저장소를 볼 수 있다. GitNest에서 저장소를 열고 Project 항목을 찾는다. 선택 상자는 저장소 오너한테만 보인다. 프로젝트를 고르면 "Repository project updated" 토스트가 뜬다. 그다음 Connected 탭에서 Codex CLI를 고르고, Projects 아래 Add to project로 같은 프로젝트를 추가한다.
파일 가져오기는 네이티브 GitNest 저장소, 즉 Git 데이터를 osFoundry 쪽에 둔 저장소여야 한다. 툴 설명에도 "Repository GitNest must be enabled."라고 대놓고 적혀 있다. GitHub를 미러링만 하는 저장소라면 체인지셋을 거쳐 프로바이더로 공개하는 길을 쓴다.
3. GitHub나 GitLab이면 프로바이더 계정 연결해 두기
propose_gitnest_provider_publication은 오너가 승인하는 순간, 오너가 연결해 둔 Git 프로바이더 계정으로 push한다. 연결된 계정이 없으면 승인해도 push할 수단이 없다. 이 과정 어디에서도 Codex한테 GitHub 토큰은 필요 없다.
실제로 돌려 보면
이 글을 쓴 머신에는 Codex가 설치돼 있지 않아서, 아래 세션은 시뮬레이션한 예시다. 툴 이름과 인자 이름은 라이브 서버의 tools/list에서 가져왔고, Codex가 붙이는 mcp__osfoundry__ 접두사도 그대로 뒀다. 저장소, 파일, ID, 답변은 데모용 내용이다.
Example (simulated) > shop-api has no CI. In osFoundry, put a GitHub Actions workflow that runs `make test` on pull requests, plus the Makefile target, on a branch codex/ci-workflow. • mcp__osfoundry__list_granted_resources {} ← project "Checkout" · GitNest repository "shop-api" • mcp__osfoundry__read_gitnest_repository {"repository_id": "…"} ← native, GitNest enabled, default branch main • mcp__osfoundry__propose_gitnest_file_import { "repository_id": "…", "branch": "codex/ci-workflow", "message": "Add CI workflow and make test target", "files": [ {"path": ".github/workflows/ci.yml", "content": "name: ci\non: [pull_request]\n…"}, {"path": "Makefile", "content": "test:\n\tpython -m pytest -q\n"}], "idempotency_key": "codex-shop-api-ci-0001"} [Codex asks: allow this tool call? → yes] ← proposal waiting for the owner I prepared one commit for shop-api on codex/ci-workflow with two files. Nothing is committed yet. The owner approves it in osFoundry. osFoundry에서는 벨에 "Codex CLI proposes GitNest file changes"가 뜬다. 연결 패널의 카드 제목은 "Commit GitNest files in shop-api"이고, 그 밑에 "Commit to branch: codex/ci-workflow"와 커밋 메시지가 나온다. "Review all proposed files (2)"를 펼치면 diff 요약이 아니라 파일마다 전체 텍스트가 보인다. Approve and create를 누르면 커밋되고, Decline을 누르면 버려진다.
예시: shop-api의 Commit GitNest files 카드에서 제안된 파일 두 개를 펼친 화면
같은 날 조금 뒤, GitNest에서 체인지셋이 이미 합성된 상태에서:
Example (simulated) > Is the "Add CI workflow" change set green? If so, open it on GitHub as a draft PR. • mcp__osfoundry__list_gitnest_work {"repository_id": "…", "kind": "changes"} ← "Add CI workflow" · version 3 • mcp__osfoundry__list_gitnest_checks {"repository_id": "…", "change_set_id": "…"} ← composed commit 73e59f27bc4f…: unit passed · lint passed • mcp__osfoundry__propose_gitnest_provider_publication { "repository_id": "…", "change_set_id": "…", "expected_change_set_version": 3, "expected_composition_oid": "73e59f27bc4f…", "idempotency_key": "codex-shop-api-ci-pr-0001"} [Codex asks: allow this tool call? → yes] ← proposal waiting for the owner Both checks passed on the composed commit. I asked for a draft GitHub PR of version 3; it opens when the owner approves it in osFoundry. Codex는 PR의 브랜치도, 제목도, 대상도 정하지 않는다. 스키마가 받는 건 체인지셋, Codex가 읽은 버전, Codex가 읽은 합성 커밋뿐이다. draft: false나 다른 target_branch를 넣으면 누구한테 닿기도 전에 걸러진다.
카드 제목은 "Open a draft GitHub or GitLab pull request in shop-api"다. "Change set: … · expected version 3", "Reviewed commit: 73e59f27bc4f…", "Review change set before approving" 링크, 그리고 승인하면 뭐가 일어나는지 한 줄이 나온다. 그 한 줄은 "uses your linked Git provider account to push this change-set branch and open a draft pull request"다. 버튼은 Approve and publish. GitNest 안에 있는 저장소라면 propose_gitnest_native_publication이 짝이 되는 카드 "Publish GitNest pull request"를 만들고, 이쪽은 "creates a publication branch and opens a pull request in this native repository"라고 적혀 있다.
예시: Needs your approval 아래의 프로바이더 PR 카드와 네이티브 공개 카드
카드의 링크를 누르면 GitNest에서 체인지셋이 열린다. 합성 커밋의 체크 결과가 리뷰 탭 위쪽 맨 위에 있어서, 오너는 결정하기 전에 Codex가 본 걸 똑같이 볼 수 있다.
어디까지가 Codex 몫인가
파일 가져오기는 텍스트만 실어 나른다. 엔트리 하나는 경로와 전체 내용, 그게 전부다. 파일 모드도, 삭제도, 바이너리도 없고, 커밋 전체가 20파일, 200 KB 안에 들어간다. 그래서 카드에서 모든 바이트를 읽을 수 있다. GitNest에서 오너가 브라우저로 직접 올리는 건 훨씬 넉넉하다(2,000파일, 파일당 8 MB, 합계 32 MB). 그건 사람이 자기 파일을 커밋하는 거라서다.
공개는 Codex가 이름 붙인 브랜치가 아니라 합성된 체인지셋에서 나간다. 카드에는 Codex가 본 버전과 커밋이 고정돼 있다. 누르기 전에 체인지셋이 다시 합성되면, osFoundry의 재확인이 아무도 안 본 걸 공개하는 대신 제안을 거절한다. 승인 시점에는 지금 권한, 저장소의 리스크 등급과 필수 체크, 대상도 같이 확인한다. 이 규칙들은 사람이 GitNest의 Risk tiers와 Required checks에서 정하고, Codex는 건드릴 수 없다.
GitHub나 GitLab에서 움직이는 건 체인지셋 전용 브랜치 하나뿐이다. PR은 드래프트로 열리고, push에는 승인 시점에 오너가 연결해 둔 계정을 쓴다. Codex는 그 토큰을 볼 일이 없고, 다른 브랜치는 push에 끼지 않는다.
머지는 목록에 없다. 이 제안들이 갈 수 있는 끝은 열린 PR까지다. 누가 머지할지, 머지 뒤에 뭐가 돌아갈지는 저장소에 있는 사람들 몫이다.
tools/list에서 공개 툴 둘에는 openWorldHint: true가 붙어 있고, 파일 가져오기에는 없다. PR은 대화 밖의 사람한테도 보이니까, 제대로 만든 클라이언트라면 이걸 먼저 물어볼 이유로 받아들인다. 여기서 Codex가 하는 것처럼.
다음엔 아직 아무도 안 쓰는 브랜치에 가져오기를 한 번 해 보자. Codex한테 새 파일 하나, CONTRIBUTING.md나 CI 워크플로 같은 걸 제안하게 하고, 카드에서 "Review all proposed files"를 펼쳐 본 다음 승인하면 된다. 저장소 쪽에서 체인지셋, 체크, 공개가 어떻게 맞물리는지는 GitNest 페이지에 정리돼 있다.



