• Codex Skill Discovery๋Š” codex ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์Šคํ‚ฌ ํŒŒ์ผ์„ ํƒ์ƒ‰ํ•˜๋Š” ๊ณ„์ธต์  ํŒŒ์ผ ์‹œ์Šคํ…œ ์Šค์บ” ๋ฉ”์ปค๋‹ˆ์ฆ˜
  • HOME(USER-level)๊ณผ cwd(PROJECT-level) ๋‘ ๊ฒฝ๋กœ๋ฅผ ๋™์‹œ์— ์Šค์บ”ํ•˜์—ฌ ์Šคํ‚ฌ ๋ชฉ๋ก์„ ๊ตฌ์„ฑํ•˜๋Š” ์ด์ค‘ ๋ ˆ๋ฒจ ๋””์Šค์ปค๋ฒ„๋ฆฌ ๊ตฌ์กฐ
  • app-server JSON-RPC ํ”„๋กœํ† ์ฝœ์˜ thread/start์™€ skills/list ๋‘ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ œ์–ด๋˜๋Š” ์„ธ์…˜ ๊ธฐ๋ฐ˜ ์Šคํ‚ฌ ๋ผ์šฐํŒ…

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

  • ์ž์ฒด ์„œ๋น„์Šค๊ฐ€ codex๋ฅผ spawnํ•˜์—ฌ ์‚ฌ์šฉํ•  ๋•Œ, ์„œ๋น„์Šค ์ „์šฉ ์Šคํ‚ฌ(์˜ˆ: ์‚ฌ๋‚ด DB ๊ฒ€์ƒ‰)์ด ์‚ฌ์šฉ์ž์˜ ๊ธ€๋กœ๋ฒŒ CLI์— ๋…ธ์ถœ๋˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค
  • ๋ฐ˜๋Œ€๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ๊ธ€๋กœ๋ฒŒํ•˜๊ฒŒ ์„ค์ •ํ•œ ์Šคํ‚ฌ์€ ์„œ๋น„์Šค์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค
  • codex ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฒ„์ „์ด ์‚ฌ์šฉ์ž๋งˆ๋‹ค ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ๋„ ์„œ๋น„์Šค๊ฐ€ ์ผ๊ด€๋˜๊ฒŒ ๋™์ž‘ํ•ด์•ผ ํ•œ๋‹ค

์ผ€์ด์Šค A: ์„œ๋น„์Šค๋Š” ์‚ฌ์šฉ์ž์˜ ๊ธ€๋กœ๋ฒŒ CLI๊ฐ€ ์•„๋‹Œ ์ž์ฒด ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค

๋ฐ”์ด๋„ˆ๋ฆฌ ํ•ด์„ ๊ฒฝ๋กœ

์‚ฌ์šฉ์ž๊ฐ€ npm install -g @openai/codex๋กœ ์„ค์น˜ํ•œ ๊ธ€๋กœ๋ฒŒ CLI๋Š” /opt/homebrew/bin/codex ๋“ฑ์— ์œ„์น˜ํ•œ๋‹ค. ์„œ๋น„์Šค๋Š” ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

์„œ๋น„์Šค ํ”„๋กœ์ ํŠธ์˜ package.json์— @openai/codex๋ฅผ ์˜์กด์„ฑ์œผ๋กœ ์„ ์–ธํ•˜๊ณ , ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ npm install์„ ์‹คํ–‰ํ•˜๋ฉด ํ”„๋กœ์ ํŠธ์˜ node_modules/ ์•ˆ์— codex ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์„ค์น˜๋œ๋‹ค. ์„œ๋น„์Šค๋Š” ์ด ๋กœ์ปฌ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ํ•ด์„ํ•˜์—ฌ spawnํ•œ๋‹ค:

my-service/
โ””โ”€โ”€ node_modules/
    โ””โ”€โ”€ @openai/codex-darwin-arm64/
        โ””โ”€โ”€ vendor/
            โ””โ”€โ”€ aarch64-apple-darwin/
                โ””โ”€โ”€ codex/
                    โ””โ”€โ”€ codex  โ† ์ด ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ spawn
// package.json โ€” ์บ๋Ÿฟ ์—†์ด ๊ณ ์ • ๋ฒ„์ „
{ "@openai/codex": "0.105.0" }

์‚ฌ์šฉ์ž๊ฐ€ ๊ธ€๋กœ๋ฒŒ์— 0.98.0์„ ์“ฐ๋“  0.116์„ ์“ฐ๋“ , ์„œ๋น„์Šค๋Š” ํ•ญ์ƒ ํ”„๋กœ์ ํŠธ node_modules/์— ์„ค์น˜๋œ 0.105.0 ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ spawnํ•œ๋‹ค. ๊ธ€๋กœ๋ฒŒ CLI์™€ ์„œ๋น„์Šค์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ์™„์ „ํžˆ ๋ณ„๊ฐœ์˜ ์„ค์น˜๋‹ค.

Q1. ์‚ฌ์šฉ์ž์˜ ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ X๋ฅผ ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€?

YES. ์‚ฌ์šฉ์ž๊ฐ€ ~/.agents/skills/X/ (๋˜๋Š” ๋ ˆ๊ฑฐ์‹œ ~/.codex/skills/X/)์— ์„ค์น˜ํ•œ ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ์€ ์„œ๋น„์Šค์—์„œ๋„ ๋ฐœ๊ฒฌ๋œ๋‹ค.

์ด์œ : spawn ์‹œ process.env๋ฅผ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•˜๋ฏ€๋กœ HOME ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์œ ์ง€๋œ๋‹ค. codex ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ํ•ญ์ƒ HOME ๊ธฐ๋ฐ˜์˜ USER-level ๊ฒฝ๋กœ(~/.agents/skills/ + ~/.codex/skills/)๋ฅผ ์Šค์บ”ํ•œ๋‹ค.

sequenceDiagram
    autonumber
    participant User as ์‚ฌ์šฉ์ž ํ™˜๊ฒฝ
    participant App as Service Backend
    participant Codex as codex (๋ฒˆ๋“ค ๋ฐ”์ด๋„ˆ๋ฆฌ)
    participant GS as ~/.agents/skills/
    participant PS as {appDataDir}/.agents/skills/

    User->>GS: ์Šคํ‚ฌ X ์„ค์น˜ (๊ธ€๋กœ๋ฒŒ CLI๋กœ)
    App->>Codex: spawn(codexBinaryPath, env: { HOME=~ })
    App->>Codex: thread/start(cwd=appDataDir)
    Codex->>GS: HOME ๊ธฐ์ค€ ์Šค์บ” โ†’ ์Šคํ‚ฌ X ๋ฐœ๊ฒฌ โœ…
    Codex->>PS: cwd ๊ธฐ์ค€ ์Šค์บ” โ†’ ์‚ฌ๋‚ด DB ๊ฒ€์ƒ‰ ์Šคํ‚ฌ ๋ฐœ๊ฒฌ โœ…
    Codex-->>App: ์Šคํ‚ฌ X + ์‚ฌ๋‚ด DB ๊ฒ€์ƒ‰ ์Šคํ‚ฌ ๋ชจ๋‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

์‹ค์ œ ์˜ˆ์‹œ

Q. ๊ธ€๋กœ๋ฒŒ์— study-guard ์Šคํ‚ฌ์„, ํ”„๋กœ์ ํŠธ์— ๋‚ด๋ถ€ DB ์ ‘๊ทผ ์Šคํ‚ฌ์„ ์„ค์ •ํ–ˆ๋‹ค. ์„œ๋น„์Šค์—์„œ ๋‘˜ ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€?

A. ๋‘˜ ๋‹ค ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ (USER-level):
  ~/.agents/skills/study-guard/

ํ”„๋กœ์ ํŠธ ์Šคํ‚ฌ (PROJECT-level):
  {appDataDir}/.agents/skills/access-db/

์„œ๋น„์Šค๊ฐ€ codex๋ฅผ spawnํ•˜๋ฉด:

  1. spawn ์‹œ process.env๊ฐ€ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ โ†’ HOME=~ โ†’ ~/.agents/skills/study-guard/ ๋ฐœ๊ฒฌ โœ…
  2. thread/start์—์„œ cwd๋ฅผ ์„œ๋น„์Šค ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์„ค์ • โ†’ {appDataDir}/.agents/skills/access-db/ ๋ฐœ๊ฒฌ โœ…

๋‘ ๋ ˆ๋ฒจ์˜ ํ•ฉ์ง‘ํ•ฉ์œผ๋กœ ๋™์ž‘ํ•˜๋ฏ€๋กœ, ์„ธ์…˜์—์„œ study-guard์™€ access-db ์Šคํ‚ฌ ๋ชจ๋‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

sequenceDiagram
    autonumber
    participant App as Service Backend
    participant Codex as codex (๋ฒˆ๋“ค ๋ฐ”์ด๋„ˆ๋ฆฌ)
    participant GS as ~/.agents/skills/study-guard/
    participant PS as {appDataDir}/.agents/skills/access-db/

    App->>Codex: spawn(codexBinaryPath, env: { HOME=~ })
    App->>Codex: thread/start(cwd=appDataDir)
    Codex->>GS: HOME ๊ธฐ์ค€ ์Šค์บ” โ†’ study-guard ๋ฐœ๊ฒฌ โœ…
    Codex->>PS: cwd ๊ธฐ์ค€ ์Šค์บ” โ†’ access-db ์Šคํ‚ฌ ๋ฐœ๊ฒฌ โœ…
    Codex-->>App: study-guard + access-db ๋ชจ๋‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

ํ•ต์‹ฌ์€ ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ๋ฒˆ๋“ค๋œ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ, HOME์€ ์‚ฌ์šฉ์ž ๊ฒƒ์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฒ„์ „๊ณผ ์Šคํ‚ฌ ๋””์Šค์ปค๋ฒ„๋ฆฌ ๊ฒฝ๋กœ๋Š” ๋ณ„๊ฐœ์˜ ๋ฌธ์ œ๋‹ค.

์ผ€์ด์Šค B: ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฒ„์ „ ํ•€๋‹๊ณผ ์‚ฌ์šฉ์ž ๊ฐ„ ๋…๋ฆฝ์„ฑ

์‹œ๋‚˜๋ฆฌ์˜ค: ํ˜„์žฌ ์†Œ์Šค์ฝ”๋“œ ๊ธฐ์ค€ โ€” ์–‘์ชฝ ๊ฒฝ๋กœ ๋ชจ๋‘ ์Šค์บ”

์†Œ์Šค์ฝ”๋“œ ๋ถ„์„ ๊ฒฐ๊ณผ, ํ˜„์žฌ codex๋Š” .codex/skills/์™€ .agents/skills/๋ฅผ ๋™์‹œ์— ์Šค์บ”ํ•œ๋‹ค. User scope์—์„œ ~/.codex/skills/๋Š” deprecated์ด์ง€๋งŒ ํ•˜์œ„ ํ˜ธํ™˜์„ ์œ„ํ•ด ์œ ์ง€๋œ๋‹ค.

๊ตฌ๋ถ„์‚ฌ์šฉ์ž A (๋ ˆ๊ฑฐ์‹œ ๊ฒฝ๋กœ ์‚ฌ์šฉ)์‚ฌ์šฉ์ž B (ํ˜„์žฌ ๊ถŒ์žฅ ๊ฒฝ๋กœ ์‚ฌ์šฉ)
๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ ์œ„์น˜~/.codex/skills/~/.agents/skills/
์„œ๋น„์Šค ๋ฐ”์ด๋„ˆ๋ฆฌ0.105.0 (๋™์ผ)0.105.0 (๋™์ผ)
์„œ๋น„์Šค์—์„œ ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ ๋ฐœ๊ฒฌโœ… (deprecated ๊ฒฝ๋กœ๋„ ์Šค์บ”)โœ… (ํ˜„์žฌ ๊ถŒ์žฅ ๊ฒฝ๋กœ ์Šค์บ”)

A์™€ B ๋ชจ๋‘ ์„œ๋น„์Šค์—์„œ ์ •์ƒ ๋™์ž‘ํ•œ๋‹ค. codex ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์–‘์ชฝ ๊ฒฝ๋กœ๋ฅผ ๋ชจ๋‘ ์Šค์บ”ํ•˜๋ฏ€๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ์–ด๋А ๊ฒฝ๋กœ์— ์Šคํ‚ฌ์„ ์„ค์น˜ํ–ˆ๋“  ๋ฐœ๊ฒฌ๋œ๋‹ค.

์‚ฌ์šฉ์ž A (๋ ˆ๊ฑฐ์‹œ ๊ฒฝ๋กœ):
  ์„œ๋น„์Šค: {cwd}/.codex/skills/ โœ… + ~/.codex/skills/ โœ… (deprecated but scanned)
                                  + ~/.agents/skills/ โœ… (current)

์‚ฌ์šฉ์ž B (ํ˜„์žฌ ๊ถŒ์žฅ ๊ฒฝ๋กœ):
  ์„œ๋น„์Šค: {cwd}/.codex/skills/ โœ… + ~/.codex/skills/ โœ… (deprecated but scanned)
                                  + ~/.agents/skills/ โœ… (current)

๊ฒฐ๋ก : ์„œ๋น„์Šค์˜ ํ•ต์‹ฌ ๋™์ž‘์€ ์‚ฌ์šฉ์ž์˜ ๊ธ€๋กœ๋ฒŒ CLI ๋ฒ„์ „๊ณผ ์™„์ „ํžˆ ๋…๋ฆฝ์ ์ด๋‹ค. package.json์— ๋ฒ„์ „์„ ํ•€๋‹ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋˜ํ•œ ์–‘์ชฝ ๊ฒฝ๋กœ๋ฅผ ๋ชจ๋‘ ์Šค์บ”ํ•˜๋ฏ€๋กœ ๊ฒฝ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ณผ๋„๊ธฐ์—๋„ ๋ฌธ์ œ์—†๋‹ค.

์„œ๋น„์Šค ์ธก ์Šคํ‚ฌ ๋ฐฐํฌ ์ „๋žต

์†Œ์Šค์ฝ”๋“œ ๋ถ„์„ ๊ฒฐ๊ณผ codex๋Š” .codex/skills/์™€ .agents/skills/๋ฅผ ๋™์‹œ์— ์Šค์บ”ํ•˜๋ฏ€๋กœ, ์–ด๋А ํ•œ ๊ฒฝ๋กœ์—๋งŒ ๋ฐฐํฌํ•˜๋ฉด ์ถฉ๋ถ„ํ•˜๋‹ค. ์„œ๋น„์Šค๋Š” ํ˜„์žฌ ๊ถŒ์žฅ ๊ฒฝ๋กœ์ธ .agents/skills/์— ๋ฐฐํฌํ•œ๋‹ค.

1. ๋‹จ์ผ ๊ฒฝ๋กœ ๋ฐฐํฌ (ํ˜„์žฌ ์„œ๋น„์Šค ๊ตฌํ˜„)

skill-deployer.service.ts์—์„œ {appDataDir}/.agents/skills/์— ๋ฐฐํฌ:

function getCodexSkillsTarget(): string {
  return path.join(getAppDataDir(), ".agents", "skills");
}

codex ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ repo_agents_skill_roots() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด cwd ๊ฒฝ๋กœ ์ƒ์˜ .agents/skills/๋ฅผ ์Šค์บ”ํ•˜๋ฏ€๋กœ, thread/start์—์„œ cwd=appDataDir๋กœ ์„ค์ •ํ•˜๋ฉด ์ž๋™ ๋ฐœ๊ฒฌ๋œ๋‹ค.

2. ๋ฏธ๋ž˜ deprecated ์ œ๊ฑฐ์— ๋Œ€ํ•œ ๋ฐฉ์–ด

ํ˜„์žฌ .codex/skills/(Project scope)๋Š” deprecated๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ, ํ–ฅํ›„ ์ œ๊ฑฐ๋  ๊ฐ€๋Šฅ์„ฑ์— ๋Œ€๋น„ํ•˜์—ฌ .agents/skills/๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•˜๋‹ค. ๋งŒ์•ฝ ๋ฏธ๋ž˜์— .agents/skills/๋„ ๊ฒฝ๋กœ๊ฐ€ ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด, symlink ๋ฐฐํฌ๋กœ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋‹ค:

๊ณต์‹ ๋ฌธ์„œ: โ€œCodex supports symlinked skill folders and follows symlink targets when scanning these locations.โ€

3. skills/list ๊ฒ€์ฆ (์„ ํƒ)

๋ฐ”์ด๋„ˆ๋ฆฌ ์—…๊ทธ๋ ˆ์ด๋“œ ์‹œ ์Šคํ‚ฌ ๋ฐœ๊ฒฌ ์ƒํƒœ๋ฅผ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค:

const skillsResult = await peer.request("skills/list", {
  cwds: [APP_DATA_DIR],
});
 
const expectedSkills = ["access-db", "internal-search"];
const foundSkills = skillsResult.skills.map(s => s.name);
const missing = expectedSkills.filter(s => !foundSkills.includes(s));
 
if (missing.length > 0) {
  logger.error(`์Šคํ‚ฌ ๋ฏธ๋ฐœ๊ฒฌ: ${missing.join(", ")} โ€” ๊ฒฝ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•„์š”`);
}

skills/list๋Š” ์ฝ๊ธฐ ์ „์šฉ ์กฐํšŒ์ด๋ฏ€๋กœ, ์„ธ์…˜ ๋™์ž‘์— ์˜ํ–ฅ ์—†์ด ์Šคํ‚ฌ ๋ฐœ๊ฒฌ ์ƒํƒœ๋ฅผ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.

์Šคํ‚ฌ ๋””์Šค์ปค๋ฒ„๋ฆฌ์˜ ๋‘ ๋ ˆ๋ฒจ

Level๊ฒฝ๋กœ์ƒํƒœ๊ฒฐ์ • ์š”์†Œ์„ค๋ช…
USER (๊ธ€๋กœ๋ฒŒ)~/.agents/skills/ํ˜„์žฌ ๊ถŒ์žฅspawn ์‹œ HOME ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ชจ๋“  codex ์„ธ์…˜์—์„œ ํ•ญ์ƒ ์Šค์บ”
USER (๊ธ€๋กœ๋ฒŒ)~/.codex/skills/deprecated (ํ•˜์œ„ ํ˜ธํ™˜)spawn ์‹œ CODEX_HOMEํ•˜์œ„ ํ˜ธํ™˜์šฉ์œผ๋กœ ์—ฌ์ „ํžˆ ์Šค์บ”
PROJECT (ํ”„๋กœ์ ํŠธ){cwd}/.codex/skills/activethread/start์˜ cwd ํŒŒ๋ผ๋ฏธํ„ฐํ”„๋กœ์ ํŠธ config layer ๊ธฐ์ค€
PROJECT (ํ”„๋กœ์ ํŠธ){root~cwd}/.agents/skills/ํ˜„์žฌ ๊ถŒ์žฅthread/start์˜ cwd ํŒŒ๋ผ๋ฏธํ„ฐํ”„๋กœ์ ํŠธ ๋ฃจํŠธ~cwd ์‚ฌ์ด ๋ชจ๋‘ ์Šค์บ”

๋‘ ๋ ˆ๋ฒจ์€ ํ•ฉ์ง‘ํ•ฉ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. USER ๊ฒฝ๋กœ์™€ PROJECT ๊ฒฝ๋กœ๋ฅผ ๋ชจ๋‘ ์Šค์บ”ํ•œ ํ›„, dedupe_skill_roots_by_path()๋กœ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๊ณ  ๋ฐœ๊ฒฌ๋œ ๋ชจ๋“  ์Šคํ‚ฌ์„ ํ•ด๋‹น ์„ธ์…˜์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.

HOME๊ณผ cwd๋Š” ์Šคํ‚ฌ๋งŒ์„ ์œ„ํ•œ ์„ค์ •์ด ์•„๋‹ˆ๋‹ค

HOME๊ณผ cwd๋Š” codex ์ „๋ฐ˜์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ์„ค์ •์ด๋ฉฐ, ์Šคํ‚ฌ ๋””์Šค์ปค๋ฒ„๋ฆฌ๋Š” ๊ทธ ์ค‘ ํ•˜๋‚˜์˜ ๋ถ€๊ฐ€ ํšจ๊ณผ์ผ ๋ฟ์ด๋‹ค.

HOME (spawn ํ™˜๊ฒฝ๋ณ€์ˆ˜) โ€” ~/.codex/ ์ „์ฒด + ~/.agents/ ๋ฅผ ๊ฒฐ์ •:

๊ฒฝ๋กœ์šฉ๋„
~/.codex/config.tomlcodex ์„ค์ • (๋ชจ๋ธ, API ํ‚ค ๊ฒฝ๋กœ ๋“ฑ)
~/.codex/auth/์ธ์ฆ ์ •๋ณด
~/.codex/db/codex ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ
~/.codex/certs/TLS ์ธ์ฆ์„œ
~/.codex/skills/USER-level ์Šคํ‚ฌ (deprecated, ํ•˜์œ„ ํ˜ธํ™˜)
~/.agents/skills/USER-level ์Šคํ‚ฌ (ํ˜„์žฌ ๊ถŒ์žฅ)

process.env๋กœ HOME์„ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•˜๋Š” ์ด์œ ๋Š” ์‚ฌ์šฉ์ž์˜ codex ์„ค์ •, ์ธ์ฆ ์ •๋ณด ๋“ฑ์„ ๋ชจ๋‘ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋‹ค.

cwd (thread/start ํŒŒ๋ผ๋ฏธํ„ฐ) โ€” ์„ธ์…˜์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ ์ „๋ฐ˜์„ ๊ฒฐ์ •:

์˜ํ–ฅ์„ค๋ช…
๋ช…๋ น ์‹คํ–‰codex๊ฐ€ ์…ธ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ๋•Œ์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ
ํŒŒ์ผ ์ ‘๊ทผ์ƒ๋Œ€ ๊ฒฝ๋กœ ๊ธฐ์ค€์  (ํŒŒ์ผ ์ฝ๊ธฐ/์“ฐ๊ธฐ)
์ƒŒ๋“œ๋ฐ•์Šค ๊ฒฝ๊ณ„sandbox_workspace_write ๋ชจ๋“œ์˜ workspace ๋ฃจํŠธ
ํ”„๋กœ์ ํŠธ ์„ค์ •{cwd}/.codex/ ํ”„๋กœ์ ํŠธ ๋ ˆ๋ฒจ ์„ค์ •
ํ”„๋กœ์ ํŠธ ์Šคํ‚ฌ{cwd}/.codex/skills/ + {cwd}/.agents/skills/ PROJECT-level ์Šคํ‚ฌ

cwd๋ฅผ ์„œ๋น„์Šค ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์„ค์ •ํ•˜๋Š” ๋ณธ๋ž˜ ๋ชฉ์ ์€ codex์˜ ํŒŒ์ผ ์ž‘์—…๊ณผ ๋ช…๋ น ์‹คํ–‰์„ ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์—์„œ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๊ณ , PROJECT-level ์Šคํ‚ฌ ๋””์Šค์ปค๋ฒ„๋ฆฌ๋Š” ๊ทธ์— ๋”ฐ๋ผ์˜ค๋Š” ๋ถ€๊ฐ€ ํšจ๊ณผ๋‹ค.

์ฝ”๋“œ์—์„œ ๋‘ ๋ ˆ๋ฒจ์ด ์„ค์ •๋˜๋Š” ์œ„์น˜

// 1๋‹จ๊ณ„: spawn โ€” ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ
const spawnEnv = {
  ...process.env,                                      // HOME ํฌํ•จ โ†’ USER-level ๋””์Šค์ปค๋ฒ„๋ฆฌ ๊ทผ๊ฑฐ
  TOOL_CLI: "/path/to/skill/script/tool-cli",          // ์Šคํ‚ฌ์ด ์‚ฌ์šฉํ•  CLI ๊ฒฝ๋กœ
  TOOL_BASE_URL: `http://localhost:${backendPort}`,    // ์Šคํ‚ฌ โ†’ ์„œ๋น„์Šค API ํ†ต์‹  ์ฃผ์†Œ
  TOOL_USER_ID: userId,                                // ์š”์ฒญ ์‚ฌ์šฉ์ž ์‹๋ณ„
};
const child = spawn(codexBinaryPath, ["app-server", ...flags], {
  stdio: ["pipe", "pipe", "pipe"],
  env: spawnEnv,
});
 
// 2๋‹จ๊ณ„: thread/start โ€” ์„ธ์…˜ ์ƒ์„ฑ
await peer.request("thread/start", {
  model: "o4-mini",
  cwd: APP_DATA_DIR,   // โ†’ PROJECT-level ๋””์Šค์ปค๋ฒ„๋ฆฌ ๊ทผ๊ฑฐ
  approvalPolicy: "never",
});
์„ค์ • ์œ„์น˜๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ X์‚ฌ๋‚ด DB ๊ฒ€์ƒ‰ ์Šคํ‚ฌ
spawn env (...process.env)HOME โ†’ ~/.agents/skills/ + ~/.codex/skills/์—ฌ๊ธฐ์„œ ๋ฐœ๊ฒฌ-
thread/start (cwd)cwd โ†’ {appDataDir}/.agents/skills/ + {appDataDir}/.codex/skills/-์—ฌ๊ธฐ์„œ ๋ฐœ๊ฒฌ

์‚ฌ์šฉ์ž์˜ ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ X๋Š” thread/start๊ฐ€ ์•„๋‹ˆ๋ผ spawn ์‹œ ์ „๋‹ฌ๋œ HOME ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์ธํ•ด ๋ฐœ๊ฒฌ๋œ๋‹ค. spawnEnv์—์„œ HOME์„ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ๋ฎ์–ด์“ฐ๋ฉด ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ X๋Š” ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š๋Š”๋‹ค.

cwd๊ฐ€ ์Šคํ‚ฌ ๋””์Šค์ปค๋ฒ„๋ฆฌ์—์„œ ํ•˜๋Š” ์—ญํ• 

HOME(spawn ํ™˜๊ฒฝ๋ณ€์ˆ˜)์ด ์ด๋ฏธ ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ ์ ‘๊ทผ์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, cwd(thread/start ํŒŒ๋ผ๋ฏธํ„ฐ)๋Š” ์ถ”๊ฐ€์ ์ธ ํ”„๋กœ์ ํŠธ ์Šค์ฝ”ํ”„ ๊ฒฝ๋กœ๋ฅผ ์ œ๊ณตํ•œ๋‹ค:

์‚ฌ์šฉ์ž๊ฐ€ codex CLI ์ง์ ‘ ์‚ฌ์šฉ:
  spawn HOME=~                         โ†’ ~/.agents/skills/                    (๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ X โœ…)
  thread/start cwd=~/projects/myapp    โ†’ ~/projects/myapp/.agents/skills/     (์‚ฌ๋‚ด DB ๊ฒ€์ƒ‰ ์Šคํ‚ฌ โŒ)

์„œ๋น„์Šค๊ฐ€ spawn:
  spawn HOME=~                         โ†’ ~/.agents/skills/                    (๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ X โœ…)
  thread/start cwd=appDataDir          โ†’ {appDataDir}/.agents/skills/         (์‚ฌ๋‚ด DB ๊ฒ€์ƒ‰ ์Šคํ‚ฌ โœ…)

cwd๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•œ HOME์„ ๊ณต์œ ํ•˜๋ฉด์„œ๋„ ์„œ๋น„์Šค ์ „์šฉ ์Šคํ‚ฌ์„ ๊ฒฉ๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

JSON-RPC ๋ฉ”์„œ๋“œ: skills/list vs thread/start

codex app-server๋Š” JSON-RPC 2.0 ํ”„๋กœํ† ์ฝœ๋กœ ํ†ต์‹ ํ•œ๋‹ค. ์Šคํ‚ฌ ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋Š” ๋‘ ๊ฐ€์ง€๋‹ค.

thread/start

์„ธ์…˜์„ ์ƒ์„ฑํ•˜๊ณ  ์Šคํ‚ฌ ๋””์Šค์ปค๋ฒ„๋ฆฌ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๋ฉ”์„œ๋“œ.

{
  "method": "thread/start",
  "params": {
    "model": "o4-mini",
    "cwd": "/path/to/service/data",
    "approvalPolicy": "never"
  }
}

cwd๊ฐ€ PROJECT-level ์Šคํ‚ฌ ํƒ์ƒ‰ ๊ฒฝ๋กœ๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด codex๋Š” USER-level(HOME ๊ธฐ๋ฐ˜)๊ณผ PROJECT-level(cwd ๊ธฐ๋ฐ˜)์„ ๋ชจ๋‘ ์Šค์บ”ํ•˜์—ฌ ์„ธ์…˜์˜ ์Šคํ‚ฌ ๋ชฉ๋ก์„ ๊ตฌ์„ฑํ•œ๋‹ค.

skills/list

ํ˜„์žฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šคํ‚ฌ ๋ชฉ๋ก์„ ์กฐํšŒํ•˜๋Š” ์ฝ๊ธฐ ์ „์šฉ ๋ฉ”์„œ๋“œ.

{
  "method": "skills/list",
  "params": {
    "perCwdExtraUserRoots": ["/additional/path"]
  }
}

perCwdExtraUserRoots ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ถ”๊ฐ€ ํƒ์ƒ‰ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด๊ฒƒ์€ ์กฐํšŒ ์ „์šฉ์ด๋‹ค. ํ•ด๋‹น ๊ฒฝ๋กœ์˜ ์Šคํ‚ฌ ๋ชฉ๋ก์„ ๋ณผ ์ˆ˜ ์žˆ์„ ๋ฟ, ์„ธ์…˜์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. thread/start์—๋Š” ์ด ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, API๋ฅผ ํ†ตํ•œ ์ถ”๊ฐ€ ๊ฒฝ๋กœ ์ฃผ์ž…์œผ๋กœ๋Š” ์„ธ์…˜์˜ ์Šคํ‚ฌ ๋””์Šค์ปค๋ฒ„๋ฆฌ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์—†๋‹ค. ์ด๊ฒƒ์ด ๋ฌผ๋ฆฌ์  ํŒŒ์ผ ๋ฐฐํฌ ๋ฐฉ์‹์ด ๊ฐ€์žฅ ์•ˆ์ •์ ์ธ ์ด์œ ๋‹ค.

thread/start์˜ cwd vs spawn์˜ cwd ์˜ต์…˜

๋‘ ๊ฐ€์ง€ cwd๋Š” ๋‹ค๋ฅธ ๋ ˆ์ด์–ด์—์„œ ๋™์ž‘ํ•œ๋‹ค:

์„ค์ • ๋ฐฉ๋ฒ•๋ ˆ์ด์–ด์—ญํ• 
spawn(binary, args, { cwd: path })OS-levelcodex ํ”„๋กœ์„ธ์Šค์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ
thread/start { cwd: path }JSON-RPC ํŒŒ๋ผ๋ฏธํ„ฐ์Šคํ‚ฌ ๋””์Šค์ปค๋ฒ„๋ฆฌ + ๋ช…๋ น ์‹คํ–‰ ๊ฒฝ๋กœ

spawn ์˜ต์…˜์˜ cwd๋ฅผ ์„ค์ •ํ•˜๋ฉด codex ํ”„๋กœ์„ธ์Šค์˜ OS-level ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ๋ณ€๊ฒฝ๋œ๋‹ค. thread/start์—์„œ cwd๋ฅผ ์ƒ๋žตํ•˜๋ฉด ํ”„๋กœ์„ธ์Šค์˜ OS-level cwd๋ฅผ fallback์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์ง€๋งŒ, ์ด๋Š” ๋ฌธ์„œํ™”๋œ ๋™์ž‘์ด ์•„๋‹Œ ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์— ์˜์กดํ•˜๋Š” ๊ฒƒ์ด๋‹ค. thread/start์— cwd๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ •์ ์ด๋‹ค.

.codex/skills/ vs .agents/skills/ โ€” ์†Œ์Šค์ฝ”๋“œ ๊ธฐ๋ฐ˜ ๋ถ„์„

์‹ค์ œ ์†Œ์Šค์ฝ”๋“œ (codex-rs/core/src/skills/loader.rs)

๋‘˜ ๋‹ค ์Šค์บ”๋œ๋‹ค. ๋‹จ, scope๋ณ„๋กœ ์—ญํ• ์ด ๋‹ค๋ฅด๋‹ค.

// ์ƒ์ˆ˜ ์ •์˜
const AGENTS_DIR_NAME: &str = ".agents";
const SKILLS_DIR_NAME: &str = "skills";

User scope โ€” ~/.codex/skills/ (deprecated) + ~/.agents/skills/ (current)

ConfigLayerSource::User { .. } => {
    // Deprecated user skills location (`$CODEX_HOME/skills`), kept for backward
    // compatibility.
    roots.push(SkillRoot {
        path: config_folder.as_path().join(SKILLS_DIR_NAME),  // ~/.codex/skills
        scope: SkillScope::User,
    });
 
    // `$HOME/.agents/skills` (user-installed skills).
    if let Some(home_dir) = home_dir {
        roots.push(SkillRoot {
            path: home_dir.join(AGENTS_DIR_NAME).join(SKILLS_DIR_NAME),  // ~/.agents/skills
            scope: SkillScope::User,
        });
    }
}

Project scope โ€” {cwd}/.codex/skills/ (active) + {cwd~root}/.agents/skills/ (active)

ConfigLayerSource::Project { .. } => {
    // deprecated ์ฃผ์„ ์—†์Œ โ€” ์ •์ƒ ๊ฒฝ๋กœ
    roots.push(SkillRoot {
        path: config_folder.as_path().join(SKILLS_DIR_NAME),  // {project}/.codex/skills
        scope: SkillScope::Repo,
    });
}

์ถ”๊ฐ€๋กœ repo_agents_skill_roots() ํ•จ์ˆ˜๊ฐ€ ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ๋ถ€ํ„ฐ cwd๊นŒ์ง€ ๋ชจ๋“  ๋””๋ ‰ํ† ๋ฆฌ์—์„œ .agents/skills/๋ฅผ ์Šค์บ”ํ•œ๋‹ค:

fn repo_agents_skill_roots(config_layer_stack: &ConfigLayerStack, cwd: &Path) -> Vec<SkillRoot> {
    let project_root = find_project_root(cwd, &project_root_markers);
    let dirs = dirs_between_project_root_and_cwd(cwd, &project_root);
    for dir in dirs {
        let agents_skills = dir.join(AGENTS_DIR_NAME).join(SKILLS_DIR_NAME);
        if agents_skills.is_dir() {
            roots.push(SkillRoot { path: agents_skills, scope: SkillScope::Repo });
        }
    }
}

์ „์ฒด ์Šค์บ” ๊ฒฝ๋กœ (์šฐ์„ ์ˆœ์œ„์ˆœ)

Scope๊ฒฝ๋กœ์ƒํƒœ์ฝ”๋“œ ๊ทผ๊ฑฐ
Repo{project}/.codex/skills/Active (deprecated ์•„๋‹˜)ConfigLayerSource::Project
Repo{root~cwd}/.agents/skills/Active (ํ˜„์žฌ ๊ถŒ์žฅ)repo_agents_skill_roots()
User~/.codex/skills/Deprecated (ํ•˜์œ„ ํ˜ธํ™˜)ConfigLayerSource::User + ์ฃผ์„
User~/.agents/skills/Active (ํ˜„์žฌ ๊ถŒ์žฅ)ConfigLayerSource::User + AGENTS_DIR_NAME
System~/.codex/skills/.system/Active (๋ฒˆ๋“ค)system_cache_root_dir()
Admin/etc/codex/skills/ActiveConfigLayerSource::System

ํ•ต์‹ฌ: deprecated๋Š” User scope์˜ ~/.codex/skills/๋งŒ ํ•ด๋‹น

์†Œ์Šค์ฝ”๋“œ์˜ // Deprecated user skills location ($CODEX_HOME/skills) ์ฃผ์„์€ User scope์˜ ~/.codex/skills/์—๋งŒ ์ ์šฉ๋œ๋‹ค. Project scope์˜ {project}/.codex/skills/๋Š” deprecated๊ฐ€ ์•„๋‹ˆ๋ฉฐ ์ •์ƒ์ ์ธ ํ”„๋กœ์ ํŠธ ์„ค์ • ๊ฒฝ๋กœ๋‹ค.

CODEX_HOME์€ ์™œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๊ฐ€

CODEX_HOME์€ ~/.codex ์ „์ฒด๋ฅผ ๋Œ€์ฒดํ•œ๋‹ค. ์Šคํ‚ฌ๋ฟ ์•„๋‹ˆ๋ผ config, auth, DB, certs๊นŒ์ง€ ๋ชจ๋‘ ์˜ํ–ฅ๋ฐ›๋Š”๋‹ค.

ํ™˜๊ฒฝ๋ณ€์ˆ˜์˜ํ–ฅ ๋ฒ”์œ„์Šคํ‚ฌ ๊ฒฉ๋ฆฌ ์ ํ•ฉ์„ฑ
HOMEOS ์ „์ฒด ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌโŒ ๊ณผ๋„ํ•จ
CODEX_HOMEcodex ์ „์ฒด ์ƒํƒœ (config, auth, DB, certs, skills)โŒ ๊ณผ๋„ํ•จ
cwd (thread/start)PROJECT-level ์Šคํ‚ฌ ๊ฒฝ๋กœ๋งŒโœ… ์ •ํ™•ํžˆ ์ ํ•ฉ

์˜ˆ์‹œ๋กœ ๋ณด๋Š” HOME vs CODEX_HOME์˜ ์ฐจ์ด

์‚ฌ์šฉ์ž์˜ ์‹ค์ œ ํ™˜๊ฒฝ์ด ์•„๋ž˜์™€ ๊ฐ™๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค:

~/.codex/
โ”œโ”€โ”€ config.toml          โ† ์‚ฌ์šฉ์ž ์„ค์ • (๋ชจ๋ธ: o4-mini, sandbox: off ๋“ฑ)
โ”œโ”€โ”€ auth/
โ”‚   โ””โ”€โ”€ credentials.json โ† ์‚ฌ์šฉ์ž์˜ OpenAI API ํ‚ค
โ”œโ”€โ”€ db/
โ”‚   โ””โ”€โ”€ history.sqlite   โ† ๋Œ€ํ™” ํžˆ์Šคํ† ๋ฆฌ
โ”œโ”€โ”€ log/
โ”‚   โ””โ”€โ”€ codex.log
โ””โ”€โ”€ skills/
    โ””โ”€โ”€ study-guard/     โ† ์‚ฌ์šฉ์ž์˜ ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ

๋ฐฉ๋ฒ• 1: HOME์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ

const child = spawn(codexBinaryPath, ["app-server"], {
  env: { ...process.env, HOME: "/opt/service" },  // โ† HOME ๋ณ€๊ฒฝ
});

๊ฒฐ๊ณผ:

ํ•ญ๋ชฉ๊ฒฝ๋กœ์ƒํƒœ
config.toml/opt/service/.codex/config.tomlโŒ ์—†์Œ โ€” ์‚ฌ์šฉ์ž ์„ค์ • ์œ ์‹ค
auth/opt/service/.codex/auth/โŒ ์—†์Œ โ€” API ํ‚ค ์œ ์‹ค, ์ธ์ฆ ์‹คํŒจ
DB/opt/service/.codex/db/โŒ ์—†์Œ โ€” ํžˆ์Šคํ† ๋ฆฌ ์œ ์‹ค
๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ/opt/service/.codex/skills/โŒ ์—†์Œ โ€” study-guard ์œ ์‹ค
SSH/GPG ๋“ฑ/opt/service/.ssh/, .gnupg/โŒ OS ์ „์ฒด์— ์˜ํ–ฅ

HOME์€ codex๋ฟ ์•„๋‹ˆ๋ผ OS ์ „์ฒด์˜ ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋ฐ”๊พธ๋ฏ€๋กœ, ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰ํ•˜๋Š” ๋ชจ๋“  ์…ธ ๋ช…๋ น(git, ssh ๋“ฑ)์—๋„ ์˜ํ–ฅ์„ ์ค€๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ๊นจ์ง„๋‹ค.

๋ฐฉ๋ฒ• 2: CODEX_HOME์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ

const child = spawn(codexBinaryPath, ["app-server"], {
  env: { ...process.env, CODEX_HOME: "/opt/service/codex-state" },  // โ† CODEX_HOME ๋ณ€๊ฒฝ
});

๊ฒฐ๊ณผ:

ํ•ญ๋ชฉ๊ฒฝ๋กœ์ƒํƒœ
config.toml/opt/service/codex-state/config.tomlโŒ ์—†์Œ โ€” ์‚ฌ์šฉ์ž ์„ค์ • ์œ ์‹ค
auth/opt/service/codex-state/auth/โŒ ์—†์Œ โ€” API ํ‚ค ์œ ์‹ค, ์ธ์ฆ ์‹คํŒจ
DB/opt/service/codex-state/db/โŒ ์—†์Œ โ€” ํžˆ์Šคํ† ๋ฆฌ ์œ ์‹ค
๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ (CODEX_HOME ๊ธฐ๋ฐ˜)/opt/service/codex-state/skills/โŒ ์—†์Œ โ€” study-guard ์œ ์‹ค
SSH/GPG ๋“ฑ~/.ssh/, ~/.gnupg/โœ… ์˜ํ–ฅ ์—†์Œ

HOME๋ณด๋‹ค๋Š” ๋ฒ”์œ„๊ฐ€ ์ข์ง€๋งŒ(OS์—๋Š” ์˜ํ–ฅ ์—†์Œ), codex์˜ ๋ชจ๋“  ์ƒํƒœ๋ฅผ ํ†ต์งธ๋กœ ๊ฒฉ๋ฆฌํ•œ๋‹ค. ์Šคํ‚ฌ๋งŒ ๋ถ„๋ฆฌํ•˜๋ ค ํ–ˆ๋Š”๋ฐ config, auth, DB๊นŒ์ง€ ๋ชจ๋‘ ์žƒ๋Š”๋‹ค. ์†Œ์Šค ์ฝ”๋“œ์—์„œ๋„ CODEX_HOME์€ config.toml, auth/, db/, log/, skills/ ๋“ฑ codex ์ „์ฒด ์ƒํƒœ ๋””๋ ‰ํ† ๋ฆฌ์˜ ๋ฃจํŠธ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

๋ฐฉ๋ฒ• 3: cwd๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ (๊ถŒ์žฅ)

const child = spawn(codexBinaryPath, ["app-server"], {
  env: { ...process.env },  // โ† HOME ๊ทธ๋Œ€๋กœ ์œ ์ง€
});
 
await peer.request("thread/start", {
  cwd: "/opt/service/app-data",  // โ† cwd๋งŒ ์„œ๋น„์Šค ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์„ค์ •
});

๊ฒฐ๊ณผ:

ํ•ญ๋ชฉ๊ฒฝ๋กœ์ƒํƒœ
config.toml~/.codex/config.tomlโœ… ์‚ฌ์šฉ์ž ์„ค์ • ์œ ์ง€
auth~/.codex/auth/โœ… API ํ‚ค ์œ ์ง€
DB~/.codex/db/โœ… ํžˆ์Šคํ† ๋ฆฌ ์œ ์ง€
๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ~/.agents/skills/study-guard/โœ… ์œ ์ง€
์„œ๋น„์Šค ์ „์šฉ ์Šคํ‚ฌ/opt/service/app-data/.agents/skills/access-db/โœ… ์ถ”๊ฐ€ ๋ฐœ๊ฒฌ
SSH/GPG ๋“ฑ~/.ssh/, ~/.gnupg/โœ… ์˜ํ–ฅ ์—†์Œ

๊ธฐ์กด ๋ชจ๋“  ๊ฒƒ์„ ์œ ์ง€ํ•˜๋ฉด์„œ, ์„œ๋น„์Šค ์ „์šฉ ์Šคํ‚ฌ๋งŒ ์ถ”๊ฐ€๋œ๋‹ค. cwd๋Š” PROJECT-level ๊ฒฝ๋กœ๋งŒ ๋ณ€๊ฒฝํ•˜๋ฏ€๋กœ USER-level ์ƒํƒœ(config, auth, DB, ๊ธ€๋กœ๋ฒŒ ์Šคํ‚ฌ)์— ์ „ํ˜€ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

ํ•œ ๋ˆˆ์— ๋น„๊ต

HOME ๋ณ€๊ฒฝ:        โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ  ๋ชจ๋“  ๊ฒƒ์ด ๋ฐ”๋€œ (OS + codex ์ „์ฒด)
CODEX_HOME ๋ณ€๊ฒฝ:  โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ  codex ์ „์ฒด ์ƒํƒœ๊ฐ€ ๋ฐ”๋€œ (config + auth + DB + skills)
cwd ๋ณ€๊ฒฝ:         โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆโ–ˆโ–ˆ  PROJECT-level ์Šคํ‚ฌ ๊ฒฝ๋กœ๋งŒ ๋ฐ”๋€œ
                  โ”œโ”€โ”€ OS โ”€โ”€โ”คโ”œโ”€โ”€ codex ์ƒํƒœ โ”€โ”€โ”คโ”œโ”€ ์Šคํ‚ฌ โ”€โ”ค

์ฐธ๊ณ  ๋ฌธ์„œ