Codex · 확장점: Skills (SKILL.md + progressive disclosure)
Codex · 확장점: Skills (SKILL.md + progressive disclosure)
한 줄 요약
Skill은 “이런 작업은 이렇게 처리하라”를 적어둔 폴더 하나이고, Codex는 평소엔 그 목차만 보다가 필요할 때만 본문을 펼쳐 읽는다. 왜 배우나: 새 작업 절차를 코드 수정 없이 AI에게 안전하게 가르치는 가장 표준적인 방법이고, 컨텍스트를 아끼는 “점진 공개” 원리를 그대로 보여주기 때문이다.
그림
flowchart TD A["스킬 루트들<br/>Repo · User · Admin · System 캐시"] --> B["로더: 폴더 스캔<br/>SKILL.md + agents/openai.yaml 파싱"] B --> C["스킬 목록<br/>(이름·설명·경로)"] C --> D["예산 적용<br/>강등/alias 정리"] D --> E["초기 카탈로그(목차)<br/>모델에게 한 줄씩 보여줌"] E --> F["모델: 요청 vs 설명 매칭<br/>또는 사용자가 $이름 명시"] F --> G["고른 스킬의 SKILL.md 전체 읽기"] G --> H["본문 절차대로 실행<br/>scripts 실행 / references 읽기"]
쉽게 풀기
스킬을 요리 레시피 카드라고 생각하면 쉽다.
-
레시피 카드 = 폴더 하나. 폴더 안에는 반드시
SKILL.md라는 설명서 한 장이 있다. 여기에 “언제 쓰는 요리인지”와 “어떻게 만드는지”가 적혀 있다. 옆에 도구(scripts/= 실행 코드), 참고서(references/), 사진·아이콘(assets/)을 곁들일 수도 있다. -
요리사(Codex)는 처음엔 메뉴판만 본다. 대화를 시작할 때 Codex는 설치된 모든 레시피의 이름 · 한 줄 설명 · 어디 있는지만 쭉 훑는다. 카드 전체를 다 읽지는 않는다. 책장에 책이 100권 있어도 책등 제목만 먼저 보는 것과 같다.
-
주문이 들어오면 그때 해당 카드를 펼친다. 사용자의 요청이 어떤 레시피의 “한 줄 설명”과 맞아떨어지면, 그제야 그
SKILL.md를 통째로 열어 읽고 적힌 순서대로 일한다. 이렇게 “처음엔 목차만, 필요할 때 본문”으로 컨텍스트를 아끼는 방식을 **progressive disclosure(점진 공개)**라고 부른다. -
메뉴판이 너무 길면 글씨를 줄인다. 스킬이 너무 많아 목차조차 자리를 많이 차지하면, Codex는 정해진 예산(컨텍스트의 약 2%, 또는 8,000자)까지만 채운다. 그 안에 안 들어가면 설명을 짧게 줄이고, 그래도 안 되면 일부 스킬은 빼고 “몇 개 빠졌다”고 경고한다.
[!note] 두 번 “주입”된다는 게 핵심 스킬은 모델에게 두 단계로 들어간다. ① 목차 단계(모든 스킬의 한 줄 요약) → ② 본문 단계(고른 스킬의 SKILL.md 전체). 목차는 항상 보이지만, 무거운 본문은 선택된 것만 들어간다. 그래서 스킬이 많아도 평소 컨텍스트가 터지지 않는다.
핵심 정리
스킬 폴더 구성 요소:
| 항목 | 필수? | 역할 |
|---|---|---|
SKILL.md | 필수 | frontmatter(이름+설명) + 본문 지시문 |
agents/openai.yaml | 선택 | UI 표시·정책·의존성 메타데이터 |
scripts/ | 선택 | 결정적 동작이 필요할 때 쓰는 코드 |
references/ · assets/ | 선택 | 추가 참고문서 · 아이콘/템플릿 |
SKILL.md frontmatter 필드:
| 필드 | 필수? | 핵심 제약 |
|---|---|---|
name | 사실상 필수 | 최대 64자. 비면 폴더명으로 대체 |
description | 필수 | 최대 1024자. 비면 로드 실패. 암묵 호출 매칭의 핵심 |
metadata.short-description | 선택 | 최대 1024자. 비거나 길면 무시 |
[!note] 점진 공개 예산과 3단 강등 (render.rs)
- 예산: 컨텍스트 창을 알면
창 크기 × 2 / 100토큰(예: 200,000 → 4,000). 모르면 8,000자.- 1단계: 모든 설명을 전부 넣어도 예산 이내면 → 전부 포함.
- 2단계: 안 되면 → 설명을 한 글자씩 공평 분배해 균등 축약. 평균 100자 넘게 잘리면 “설명이 줄었다” 경고.
- 3단계: 그래도 안 되면 → 설명 전부 제거, 우선순위 높은 스킬부터 채우고 나머지는 빼며 “N개 누락” 경고.
- 우선순위: System(0) > Admin(1) > Repo(2) > User(3), 동순위는 이름순.
- alias 최적화: 경로가 길어 예산을 까먹으면
r0 = /절대/경로별칭 테이블로 바꿔, 더 많은 스킬이 들어가는 쪽을 택한다.
[!note] 스캐너 동작 상수 (loader.rs) 파일명
SKILL.md· 메타데이터agents/openai.yaml· 탐색 깊이 최대 6 · 루트당 디렉토리 한도 2,000 ·.으로 시작하는 항목은 스킵 · 심볼릭 링크는 Repo/User/Admin에서만 추적(System은 미추적). 메타데이터는 fail-open:openai.yaml이 없거나 깨져도 SKILL.md 로딩은 막지 않고 기본값으로 넘어간다.
실제 예시
A. 디렉토리 레이아웃 (실제 시스템 스킬 구조와 동일)
my-skill/
├── SKILL.md # 필수. YAML frontmatter(name+description) + 본문 지시
├── agents/
│ └── openai.yaml # 선택. interface/policy/dependencies 메타데이터
├── scripts/ # 선택. 결정적 동작이 필요할 때 실행/패치할 코드
├── references/ # 선택. SKILL.md가 가리키는 추가 참고문서
└── assets/ # 선택. 아이콘·템플릿 등 (아이콘은 반드시 이 아래)
B. 시스템 내장 스킬 frontmatter (실제 소스 인용)
// codex-rs/skills/src/assets/samples/skill-creator/SKILL.md
---
name: skill-creator
description: Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Codex's capabilities with specialized knowledge, workflows, or tool integrations.
metadata:
short-description: Create or update a skill
---
# Skill Creator
This skill provides guidance for creating effective skills.
C. agents/openai.yaml — 의존성·인터페이스 선언 (실제 소스 인용)
# codex-rs/skills/src/assets/samples/openai-docs/agents/openai.yaml
interface:
display_name: "OpenAI Docs"
short_description: "Reference OpenAI docs, Codex self-knowledge, and model migration guidance"
icon_small: "./assets/openai-small.svg"
icon_large: "./assets/openai.png"
default_prompt: "Use OpenAI Docs for official docs lookup, questions about Codex itself or Codex surfaces, model selection, model migration, and prompt-upgrade work."
dependencies:
tools:
- type: "mcp"
value: "openaiDeveloperDocs"
description: "OpenAI Developer Docs MCP server"
transport: "streamable_http"
url: "https://developers.openai.com/mcp"
agents/openai.yaml의 주요 옵션(loader.rs SkillMetadataFile):
interface.icon_small/icon_large— 반드시assets/하위 상대경로. 절대경로/..금지(플러그인 공유 assets만 예외).interface.brand_color—#RRGGBB정확히 7자만 허용, 아니면 무시.policy.allow_implicit_invocation— 기본true.false면$skill명시 호출만 가능(자동 매칭 제외).policy.products—Chatgpt/Codex/Atlas제품 게이팅. 비면 전제품 허용.dependencies.tools[].type/value— 항목별 필수(예:"mcp"+ MCP 서버 식별자).
D. 컨텍스트에 실제로 들어가는 두 형태 (render.rs · skill_instructions.rs)
# 초기 카탈로그(목차) 한 줄 형식
- {name}: {description} (file: {path})
# 설명이 잘리면: - {name}: {앞부분} (file: {path})
# 전부 제거되면: - {name}: (file: {path})
# 스킬 선택 후 본문 주입 형식 (<skill> 마커)
<skill>
<name>{name}</name>
<path>{path}</path>
{SKILL.md 전체 내용}
</skill>
[!note] 모델에 들어가는 두 프래그먼트의 정체 ① 초기 카탈로그 =
AvailableSkillsInstructions, 역할developer, 마커<skills_instructions>.## Skills인트로 +### Available skills(한 줄들) +### How to use skills(점진 공개 규칙: “SKILL.md를 EOF까지 완전히 읽어라, 서브에이전트에 위임 금지” 등)로 조립. 대상은 활성화 +allow_implicit_invocation인 스킬만. ② 선택된 스킬 본문 =SkillInstructions, 역할user, 마커<skill>.build_skill_injections가 명시($이름/링크) 또는 암묵 매칭으로 고른 스킬의 SKILL.md를 파일에서 읽어 주입하고codex.skill.injected메트릭을 낸다.
E. 직접 만들 때 — 최소 스킬 템플릿
// my-skill/SKILL.md (지시문만 있는 최소 스킬)
---
name: my-skill
description: Explain exactly when this skill should and should not trigger. Front-load the key use case and trigger words.
metadata:
short-description: One-line UI label
---
# My Skill
1. 첫 단계 (명령형, 입력/출력 명시)
2. 둘째 단계
- 결정적 동작이 필요하면 scripts/foo.py 를 실행/패치하라.
저장 위치(스코프별): Repo = $CWD/.agents/skills/, User = $HOME/.agents/skills/, Admin = /etc/codex/skills/. 명시 호출은 $my-skill. 비활성화는 ~/.codex/config.toml의 [[skills.config]] + path + enabled = false.
만들 때 체크리스트:
-
SKILL.md첫 줄---, 닫는---있는가 (없으면 로드 실패) -
name(≤64자) +description(≤1024자, 비면 실패) 채웠는가 - description에 트리거 조건·범위·경계를 앞쪽에 배치했는가 (축약돼도 매칭되게)
- 폴더를
.agents/skills/같은 스코프 루트 아래(깊이 6 이내)에 뒀는가, 폴더명이.으로 시작하지 않는가 - (선택)
agents/openai.yaml로 interface/policy/dependencies 선언 — 아이콘은assets/하위 상대경로, brand_color는#RRGGBB - 자동 매칭을 막으려면
policy.allow_implicit_invocation: false - scripts/references는 SKILL.md에서 명시적으로 라우팅 (모델이 직접 읽도록)
F. 시스템 내장 스킬 설치 (skills 크레이트 lib.rs)
내장 스킬은 바이너리에 include_dir!로 임베드되어 install_system_skills가 $CODEX_HOME/skills/.system/에 풀어쓴다. 매 시작마다 다시 쓰지 않도록 임베드 디렉토리 핑거프린트(해시, salt v1)를 .codex-system-skills.marker에 기록하고, 마커가 일치하면 설치를 건너뛴다. 불일치면 기존 디렉토리를 지우고 다시 쓴다. 로더는 이 .system 경로를 SkillScope::System 루트로 스캔하며, System 스코프 파싱 오류는 사용자 에러 목록에 올리지 않는다.
요약 & 셀프체크
3줄 요약:
- 스킬은
SKILL.md한 장(이름+설명+본문)을 가진 폴더로, AI에게 작업 절차를 코드 수정 없이 가르친다. - 평소엔 “한 줄 설명 목차”만 모델에 들어가고(점진 공개), 요청과 맞아떨어질 때만 본문 전체가 주입된다.
- 목차가 예산(2% 또는 8,000자)을 넘으면 설명 축약 → 일부 제거 순으로 강등하고, 우선순위는 System > Admin > Repo > User다.
스스로 답해보기:
- 사용자가 스킬을 명시하지 않았는데도 Codex가 그 스킬을 골라 쓰게 만드는 필드는 무엇이고, 자동 매칭을 막으려면 어디를 어떻게 바꾸는가?
- 설치된 스킬이 너무 많아 목차 예산을 초과하면 어떤 순서로 어떤 일이 일어나는가?
- 모델에 들어가는 “목차 프래그먼트”와 “본문 프래그먼트”는 각각 역할(role)과 마커가 어떻게 다른가?
연결
근거 파일
- /home/seunghyeong/harness-work/codex/codex-rs/core-skills/src/model.rs (SkillMetadata, SkillPolicy, SkillInterface, SkillDependencies/SkillToolDependency, allows_implicit_invocation, 제품 제한)
- /home/seunghyeong/harness-work/codex/codex-rs/core-skills/src/loader.rs (SKILL.md/openai.yaml 파싱, frontmatter 추출, 스캔 상수, 스코프별 루트, 길이 제한)
- /home/seunghyeong/harness-work/codex/codex-rs/core-skills/src/render.rs (예산 8000자/2%, 3단 강등, alias 테이블, 카탈로그 한 줄 형식, How-to-use 지시)
- /home/seunghyeong/harness-work/codex/codex-rs/core-skills/src/skill_instructions.rs (
<skill>마커, name/path/contents 본문 주입) - /home/seunghyeong/harness-work/codex/codex-rs/core-skills/src/injection.rs (build_skill_injections, 명시/암묵 멘션 수집, $토큰·링크 파싱)
- /home/seunghyeong/harness-work/codex/codex-rs/core/src/context/available_skills_instructions.rs (developer role,
<skills_instructions>프래그먼트) - /home/seunghyeong/harness-work/codex/codex-rs/skills/src/lib.rs (시스템 내장 스킬 .system 캐시 설치, marker 핑거프린트)
- /home/seunghyeong/harness-work/codex/codex-rs/skills/src/assets/samples/skill-creator/SKILL.md, …/openai-docs/agents/openai.yaml (실제 예시 인용)
- /home/seunghyeong/harness-work/codex/codex-rs/protocol/src/protocol.rs (SkillScope, Product, SKILLS_INSTRUCTIONS_OPEN/CLOSE_TAG)
- /mnt/d/6study/10_프레임워크분석/_원문아카이브/codex/83_agent-skills.md (공식문서: progressive disclosure, 2%/8000자, 스코프 표, 메타데이터)
[!tip] Codex 교차검증 메모 (원본 분석 보존) 본 노트의 모든 형식·상수·스키마는 codex-rs 실제 소스에서 확인된 값이다. 핵심 근거: 스캔 상수(
MAX_SCAN_DEPTH=6,MAX_SKILLS_DIRS_PER_ROOT=2000,SKILLS_FILENAME=SKILL.md,SKILLS_METADATA_DIR/FILENAME=agents/openai.yaml)와 길이 제한(MAX_NAME_LEN=64, qualified 128,MAX_DESCRIPTION_LEN=1024)은 loader.rs, 예산(default_skill_metadata_budget= window×2/100, 미지 시DEFAULT_SKILL_METADATA_CHAR_BUDGET=8000)·3단 강등(render_skill_lines_from_lines)·경고 임계(WARNING_THRESHOLD_CHARS=100)·alias 비교(aliased_render_is_better)·우선순위(prompt_scope_rank)는 render.rs, 본문 주입<skill>마커는 skill_instructions.rs, 목차 developer 프래그먼트·<skills_instructions>태그는 available_skills_instructions.rs와 protocol.rs에서 확인됨. 메타데이터 fail-open과 System 스코프 오류 비노출 동작도 소스 기준으로 보존.