• Codex์—์„œ ์ƒŒ๋“œ๋ฐ•์Šค ์™ธ๋ถ€ ๋ช…๋ น ์‹คํ–‰์„ ์ œ์–ดํ•˜๋Š” ์„ ์–ธ์  ๊ทœ์น™ ์‹œ์Šคํ…œ (์‹คํ—˜์  ๊ธฐ๋Šฅ)
  • .rules ํŒŒ์ผ์— prefix_rule()์„ ์ •์˜ํ•˜๋ฉด, ๋ช…๋ น์–ด ํŒจํ„ด๋ณ„๋กœ allow / prompt / forbidden ๊ฒฐ์ •
  • Starlark(Python ์œ ์‚ฌ ์–ธ์–ด)๋กœ ์ž‘์„ฑ๋˜๋ฉฐ, ํŒŒ์ผ์‹œ์Šคํ…œ ์ ‘๊ทผ ์—†์ด ์•ˆ์ „ํ•˜๊ฒŒ ํ‰๊ฐ€
  • ์‚ฌ์šฉ์ž๊ฐ€ ํ„ฐ๋ฏธ๋„ UI์—์„œ ๋ช…๋ น์„ ์Šน์ธํ•˜๋ฉด, ํ•ด๋‹น ํŒจํ„ด์ด ์ž๋™์œผ๋กœ ๊ทœ์น™์— ๊ธฐ๋ก๋˜์–ด ์ดํ›„ ํ”„๋กฌํ”„ํŠธ ์ƒ๋žต

ํ•ด๋‹น ๊ฐœ๋…์ด ํ•„์š”ํ•œ ์ด์œ 

  • ๋ณด์•ˆ ๊ฒฝ๊ณ„ ์„ค์ •: ์–ด๋–ค ๋ช…๋ น์ด ์Šน์ธ ์—†์ด ์‹คํ–‰๋˜๊ณ , ์–ด๋–ค ๋ช…๋ น์ด ์ฐจ๋‹จ๋˜๋Š”์ง€ ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธ
  • ํŒ€ ํ‘œ์ค€ ๊ฐ•์ œ: ๊ด€๋ฆฌ์ž๊ฐ€ requirements.toml๋กœ ์ œํ•œ์  ๊ทœ์น™์„ ๋ฐฐํฌํ•˜์—ฌ ์กฐ์ง ์ „์ฒด์— ์ ์šฉ
  • ๋ฐ˜๋ณต ์Šน์ธ ์ œ๊ฑฐ: ํ•œ ๋ฒˆ ์Šน์ธํ•œ ๋ช…๋ น ํŒจํ„ด์„ ๊ทœ์น™์œผ๋กœ ์ €์žฅํ•˜์—ฌ ์ดํ›„ ์ž๋™ ํ—ˆ์šฉ
  • ๋ณต์žกํ•œ ์…ธ ์Šคํฌ๋ฆฝํŠธ ์•ˆ์ „ ์ฒ˜๋ฆฌ: &&, | ๋“ฑ์œผ๋กœ ์—ฐ๊ฒฐ๋œ ๋ช…๋ น์„ ๊ฐœ๋ณ„ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐ๊ฐ ๊ทœ์น™ ํ‰๊ฐ€

AS-IS

# ๋งค๋ฒˆ ๋™์ผํ•œ ๋ช…๋ น์— ์Šน์ธ ํ”„๋กฌํ”„ํŠธ ๋ฐ˜๋ณต
Codex: "gh pr view 7888 ์‹คํ–‰ํ•ด๋„ ๋ ๊นŒ์š”?" โ†’ ์Šน์ธ
Codex: "gh pr view 7889 ์‹คํ–‰ํ•ด๋„ ๋ ๊นŒ์š”?" โ†’ ๋˜ ์Šน์ธ
Codex: "gh pr list ์‹คํ–‰ํ•ด๋„ ๋ ๊นŒ์š”?" โ†’ ๋˜ ์Šน์ธ

TO-BE

# ~/.codex/rules/default.rules (ํ•œ ๋ฒˆ๋งŒ ์ •์˜)
prefix_rule(
    pattern=["gh", "pr", ["view", "list"]],
    decision="allow",
    justification="gh pr ์กฐํšŒ ๋ช…๋ น์€ ์ฝ๊ธฐ ์ „์šฉ์ด๋ฏ€๋กœ ํ•ญ์ƒ ํ—ˆ์šฉ",
)
# ์ดํ›„์—๋Š” ํ”„๋กฌํ”„ํŠธ ์—†์ด ๋ฐ”๋กœ ์‹คํ–‰
Codex: gh pr view 7888 โ†’ โœ… ์ž๋™ ์‹คํ–‰
Codex: gh pr list โ†’ โœ… ์ž๋™ ์‹คํ–‰
Codex: gh pr merge โ†’ โš ๏ธ ๋งค์นญ ์•ˆ ๋จ โ†’ ์Šน์ธ ์š”์ฒญ

๊ทœ์น™ ํŒŒ์ผ ์œ„์น˜

.rules ํŒŒ์ผ์€ ~/.codex/rules/ ๋””๋ ‰ํ† ๋ฆฌ์— ์ €์žฅํ•˜๋ฉฐ, Codex๊ฐ€ ์‹œ์ž‘ ์‹œ Team Config ๊ณ„์ธต์˜ ๋ชจ๋“  ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์Šค์บ”ํ•œ๋‹ค.

์œ„์น˜๊ฒฝ๋กœ์šฉ๋„
User~/.codex/rules/default.rules๊ฐœ์ธ ๊ทœ์น™
Adminrequirements.toml (managed config)์กฐ์ง ์ „์ฒด ๊ฐ•์ œ ๊ทœ์น™

prefix_rule() ์ž‘์„ฑ๋ฒ•

ํ•„์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ

ํŒŒ๋ผ๋ฏธํ„ฐ์„ค๋ช…์˜ˆ์‹œ
pattern๋งค์นญํ•  ๋ช…๋ น์–ด ์ ‘๋‘์‚ฌ (๋น„์–ด์žˆ์ง€ ์•Š์€ ๋ฆฌ์ŠคํŠธ)["gh", "pr", "view"]

pattern ์š”์†Œ๋Š” ๋‘ ๊ฐ€์ง€ ํ˜•ํƒœ:

  • ๋ฆฌํ„ฐ๋Ÿด ๋ฌธ์ž์—ด: "pr" โ†’ ์ •ํ™•ํžˆ pr๋งŒ ๋งค์นญ
  • ๋Œ€์•ˆ ์œ ๋‹ˆ์–ธ: ["view", "list"] โ†’ view ๋˜๋Š” list ๋งค์นญ
# "gh pr view" ๋˜๋Š” "gh pr list"์— ๋งค์นญ
prefix_rule(
    pattern=["gh", "pr", ["view", "list"]],
    decision="allow",
)

์„ ํƒ ํŒŒ๋ผ๋ฏธํ„ฐ

ํŒŒ๋ผ๋ฏธํ„ฐ๊ธฐ๋ณธ๊ฐ’์„ค๋ช…
decision"allow""allow": ์ฆ‰์‹œ ์‹คํ–‰, "prompt": ๋งค๋ฒˆ ์Šน์ธ ์š”์ฒญ, "forbidden": ์ฐจ๋‹จ
justification-์‚ฌ๋žŒ์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์„ค๋ช…. ์Šน์ธ ํ”„๋กฌํ”„ํŠธ๋‚˜ ๊ฑฐ๋ถ€ ๋ฉ”์‹œ์ง€์— ํ‘œ์‹œ
match-์ด ๊ทœ์น™์ด ๋งค์นญํ•ด์•ผ ํ•˜๋Š” ์˜ˆ์‹œ ๋ฐฐ์—ด (๋กœ๋”ฉ ์‹œ ๊ฒ€์ฆ์šฉ)
not_match-์ด ๊ทœ์น™์ด ๋งค์นญํ•˜๋ฉด ์•ˆ ๋˜๋Š” ์˜ˆ์‹œ ๋ฐฐ์—ด (๋กœ๋”ฉ ์‹œ ๊ฒ€์ฆ์šฉ)

decision ์šฐ์„ ์ˆœ์œ„

์—ฌ๋Ÿฌ ๊ทœ์น™์ด ๋™์‹œ์— ๋งค์นญ๋˜๋ฉด, ๊ฐ€์žฅ ์ œํ•œ์ ์ธ ๊ฒฐ์ •์ด ์šฐ์„ ํ•œ๋‹ค:

forbidden > prompt > allow

์…ธ ๋ช…๋ น ์ฒ˜๋ฆฌ

์•ˆ์ „ํ•œ ์ฒด์ธ ๋ช…๋ น ๋ถ„๋ฆฌ

bash/zsh์˜ -c ๋˜๋Š” -lc ํ”Œ๋ž˜๊ทธ๋กœ ์‹คํ–‰๋˜๋Š” ์…ธ ๋ช…๋ น์ด ์•ˆ์ „ํ•œ ์—ฐ์‚ฐ์ž(&&, ||, ;, |)๋กœ ์—ฐ๊ฒฐ๋˜๊ณ  ๋‹จ์ˆœ ๋‹จ์–ด๋งŒ ํฌํ•จํ•˜๋ฉด, Codex๊ฐ€ ๊ฐœ๋ณ„ ๋ช…๋ น์œผ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐ๊ฐ ๊ทœ์น™์„ ํ‰๊ฐ€ํ•œ๋‹ค:

# ์ด ๋ช…๋ น์€ "git status"์™€ "git diff"๋กœ ๋ถ„๋ฆฌ๋˜์–ด ๊ฐ๊ฐ ๊ทœ์น™ ํ‰๊ฐ€
bash -c "git status && git diff"

๋ณต์žกํ•œ ์Šคํฌ๋ฆฝํŠธ ์ฒ˜๋ฆฌ

๋ฆฌ๋‹ค์ด๋ ‰์…˜, ์น˜ํ™˜, ํ™˜๊ฒฝ๋ณ€์ˆ˜, ์™€์ผ๋“œ์นด๋“œ, ์ œ์–ด ํ๋ฆ„ ๋“ฑ ๊ณ ๊ธ‰ ์…ธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋Š” ๋‹จ์ผ ํ˜ธ์ถœ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค:

# ์ „์ฒด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํ•˜๋‚˜์˜ ํŒจํ„ด์œผ๋กœ ํ‰๊ฐ€๋จ
["bash", "-lc", "<์ „์ฒด ์Šคํฌ๋ฆฝํŠธ>"]

์ด ๋ณด์ˆ˜์  ์ ‘๊ทผ์€ ๋ณต์žกํ•œ ์Šคํฌ๋ฆฝํŠธ ์•ˆ์— ์œ„ํ—˜ํ•œ ๋ช…๋ น์ด ์ˆจ๊ฒจ์ง€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค.

๊ทœ์น™ ํ…Œ์ŠคํŠธ

CLI๋กœ ๊ทœ์น™์˜ ๋งค์นญ ๋™์ž‘์„ ์‚ฌ์ „ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค:

codex execpolicy check --pretty \
  --rules ~/.codex/rules/default.rules \
  -- gh pr view 7888 --json title,body,comments

์—ฌ๋Ÿฌ ๊ทœ์น™ ํŒŒ์ผ์„ ์กฐํ•ฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ.

์‚ฌ์šฉ์ž ์Šน์ธ ์ž๋™ ๊ธฐ๋ก

ํ„ฐ๋ฏธ๋„ UI์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ช…๋ น์„ ์Šน์ธํ•˜๋ฉด, Codex๊ฐ€ prefix_rule ํ•ญ๋ชฉ์„ ์ž๋™์œผ๋กœ ~/.codex/rules/default.rules์— ๊ธฐ๋กํ•œ๋‹ค. ์ดํ›„ ๋™์ผํ•œ ํŒจํ„ด์˜ ๋ช…๋ น์€ ํ”„๋กฌํ”„ํŠธ ์—†์ด ์‹คํ–‰๋œ๋‹ค.

sequenceDiagram
    autonumber
    actor User
    participant Codex
    participant Rules as default.rules

    Codex->>User: "gh pr view ์‹คํ–‰ํ•ด๋„ ๋ ๊นŒ์š”?"
    User->>Codex: ์Šน์ธ
    Codex->>Rules: prefix_rule(pattern=["gh","pr","view"],<br/>decision="allow") ์ž๋™ ๊ธฐ๋ก
    Note over Codex: ๋‹ค์Œ ๋ฒˆ "gh pr view" โ†’ ํ”„๋กฌํ”„ํŠธ ์—†์ด ์‹คํ–‰

Smart Approvals (๊ด€๋ฆฌ์ž ๊ธฐ๋Šฅ)

๊ด€๋ฆฌ์ž๊ฐ€ managed config์˜ requirements.toml๋กœ ์ œํ•œ์  ๊ทœ์น™์„ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋‹ค. Smart approvals๊ฐ€ ํ™œ์„ฑํ™”๋˜๋ฉด(๊ธฐ๋ณธ๊ฐ’), ์‚ฌ์šฉ์ž๊ฐ€ ๊ถŒํ•œ ์ƒ์Šน์„ ์š”์ฒญํ•  ๋•Œ Codex๊ฐ€ prefix_rule ํ•ญ๋ชฉ์„ ์ œ์•ˆํ•˜์—ฌ ๊ด€๋ฆฌ์ž ๋ฆฌ๋ทฐ๋ฅผ ๊ฑฐ์นœ๋‹ค.

๊ทœ์น™ ์–ธ์–ด: Starlark

.rules ํŒŒ์ผ์€ Starlark๋กœ ์ž‘์„ฑํ•œ๋‹ค. Starlark๋Š” Python๊ณผ ์œ ์‚ฌํ•œ ๋ฌธ๋ฒ•์ด์ง€๋งŒ, ๋ถ€์ž‘์šฉ(side effect)์ด ์—†๋„๋ก ์„ค๊ณ„๋˜์–ด ํŒŒ์ผ์‹œ์Šคํ…œ ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด ๋•๋ถ„์— ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ํ™˜๊ฒฝ์—์„œ๋„ ์•ˆ์ „ํ•˜๊ฒŒ ๊ทœ์น™์„ ํ‰๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

Claude Code Permissions์™€ ๋น„๊ต

ํ•ญ๋ชฉCodex RulesClaude Code Permissions
์ •์˜ ํ˜•์‹.rules ํŒŒ์ผ (Starlark)settings.json (JSON)
๊ทœ์น™ ๋‹จ์œ„๋ช…๋ น์–ด ์ ‘๋‘์‚ฌ ํŒจํ„ด (prefix_rule)๋„๊ตฌ ์ด๋ฆ„ + glob ํŒจํ„ด
๊ฒฐ์ • ์˜ต์…˜allow / prompt / forbiddenallow / deny
์ถฉ๋Œ ํ•ด๊ฒฐ๊ฐ€์žฅ ์ œํ•œ์ ์ธ ๊ฒฐ์ • ์šฐ์„ deny๊ฐ€ allow๋ณด๋‹ค ์šฐ์„ 
์ž๋™ ๊ธฐ๋ก์Šน์ธ ์‹œ ๊ทœ์น™ ์ž๋™ ์ƒ์„ฑ์Šน์ธ ์‹œ allowlist์— ์ž๋™ ์ถ”๊ฐ€
์…ธ ๋ช…๋ น ๋ถ„๋ฆฌ์ฒด์ธ ๋ช…๋ น์„ ๊ฐœ๋ณ„ ํ‰๊ฐ€ํ•ด๋‹น ์—†์Œ (๋„๊ตฌ ๋‹จ์œ„ ์ œ์–ด)
ํ…Œ์ŠคํŠธ ๋„๊ตฌcodex execpolicy check CLIํ•ด๋‹น ์—†์Œ
๊ทœ์น™ ์–ธ์–ดStarlark (Python-like)JSON
๊ด€๋ฆฌ์ž ๊ฐ•์ œrequirements.tomlEnterprise managed settings

์ฐธ๊ณ  ๋ฌธ์„œ