μ리μ¦: oh-my-codex μν€ν μ² ν΄λΆ
μ΄ μ리μ¦λ OpenAI Codex CLI νμ₯ λ°νμμΈ oh-my-codex(OMX)μ λ΄λΆ ꡬ쑰λ₯Ό λ¨κ³λ³λ‘ ν΄λΆνλ κ³Όμ μ΄λ€.
| νΈ | λ΄μ© | ν΅μ¬ |
|---|---|---|
| 0νΈ | Overview | 3-Plane μν€ν μ², OMCμμ μ°¨μ΄, μ 체 νλ¦ |
| 1νΈ | Codex CLI Foundation | Codex CLI μ체μ ꡬ쑰μ νμ₯ ν¬μΈνΈ |
| 2νΈ | OMX Integration | OMXκ° Codexμ μ΄λ»κ² μ°κ²°λλ |
| 3νΈ | Skill System | μν¬νλ‘μ°λ₯Ό μ΄λ»κ² μ μνλ |
| 4νΈ | Prompt & Agent System | μμ΄μ νΈλ λκ³ μ΄λ»κ² μ νλλ |
| 5νΈ (λ³Έλ¬Έ) | MCP Servers | μ΄λ€ MCP λꡬλ₯Ό μΈ μ μλ |
| 6νΈ | State & Lifecycle | μνλ₯Ό μ΄λ»κ² μ μ§νλ |
| 7νΈ | Team Orchestration | Team λͺ¨λλ μ΄λ»κ² λμνλ |
| 8νΈ | Native & Spark | Rust λ€μ΄ν°λΈ λꡬλ λκ° |
- OMX MCP Serversλ μμ΄μ νΈμκ² μν μ μ₯Β·λ©λͺ¨λ¦¬Β·μ½λ μΈν 리μ μ€Β·μ€ν μΆμ Β·ν μ‘°μ¨ κΈ°λ₯μ μ 곡νλ 5κ° λΆλ¦¬λ MCP μλ² μΈνΈ
config.tomlμ[mcp_servers]μΉμ μΌλ‘ λ±λ‘λλ©°, μΈμ μμ μ stdio κΈ°λ°μΌλ‘ μλ μμλλ Node.js νλ‘μΈμ€- OMCμ 1κ° ν΅ν© μλ²(βtβ, 30+ λꡬ)μ λ¬λ¦¬, κ΄μ¬μ¬λ³λ‘ 5κ° μλ²λ₯Ό λΆλ¦¬νμ¬ λ 립μ μΌλ‘ νμ±ν/λΉνμ±νν μ μλ ꡬ쑰
ν΄λΉ κ°λ μ΄ νμν μ΄μ
- 4νΈμμ μμ΄μ νΈμ μ μμ λΌμ°ν μ μ΄ν΄νμ
- νμ§λ§ μμ΄μ νΈκ° μμ μ€μ μν μ μ₯, λ©λͺ¨λ¦¬ κ΄λ¦¬, μ½λ λΆμ, μ€ν μΆμ μ΄ νμνλ©°, Codex CLI κΈ°λ³Έ λꡬλ‘λ μ΄λ° μμ μ΄ λΉν¨μ¨μ μ΄κ±°λ λΆκ°λ₯
- OMXλ 5κ° MCP μλ²λ₯Ό μ 곡νμ¬ μ΄ κ°κ·Ήμ λ©μ β 3-Plane μν€ν μ²μ State Planeμ ν΄λΉ
AS-IS (OMC β 1κ° ν΅ν© MCP μλ²)
sequenceDiagram autonumber participant CC as Claude Code participant T as MCP μλ² "t" (ν΅ν©) participant FS as νμΌμμ€ν CC->>T: mcp__t__state_write(...) CC->>T: mcp__t__lsp_diagnostics(...) CC->>T: mcp__t__notepad_write(...) T->>FS: λͺ¨λ λκ΅¬κ° 1κ° νλ‘μΈμ€μμ μ²λ¦¬ Note over T: 30+ λꡬ, λ¨μΌ νλ‘μΈμ€<br/>esbuild β bridge/mcp-server.cjs
TO-BE (OMX β 5κ° λΆλ¦¬ MCP μλ²)
sequenceDiagram autonumber participant CX as Codex CLI (LLM) participant ST as omx_state participant MM as omx_memory participant CI as omx_code_intel participant TR as omx_trace participant TM as omx_team_run CX->>ST: state_write(mode: "ralph", ...) CX->>MM: project_memory_read(section: "techStack") CX->>CI: lsp_diagnostics(file: "src/main.ts") CX->>TR: trace_timeline(last: 10) CX->>TM: omx_run_team_start(...) Note over ST,TM: κ΄μ¬μ¬λ³ λΆλ¦¬, κ°λ³ λΉνμ±ν κ°λ₯<br/>tsc β dist/mcp/*.js (stdio)
MCP μλ² λ±λ‘κ³Ό λΆνΈμ€νΈλν
config.toml λ±λ‘ (μμ€: src/config/generator.ts)
omx setup μ buildMergedConfig()κ° 5κ° μλ²λ₯Ό config.tomlμ λ±λ‘νλ€.
[mcp_servers.omx_state]
command = "node"
args = ["/path/to/dist/mcp/state-server.js"]
enabled = true
startup_timeout_sec = 5
[mcp_servers.omx_code_intel]
command = "node"
args = ["/path/to/dist/mcp/code-intel-server.js"]
enabled = true
startup_timeout_sec = 10 # κ°μ₯ κΈ΄ timeout| μλ² | λ±λ‘ μ΄λ¦ | μμ€ | startup timeout |
|---|---|---|---|
| State | omx_state | dist/mcp/state-server.js | 5μ΄ |
| Memory | omx_memory | dist/mcp/memory-server.js | 5μ΄ |
| Code Intel | omx_code_intel | dist/mcp/code-intel-server.js | 10μ΄ |
| Trace | omx_trace | dist/mcp/trace-server.js | 5μ΄ |
| Team | omx_team_run | dist/mcp/team-server.js | 5μ΄ |
μλ μμκ³Ό λΉνμ±ν (μμ€: src/mcp/bootstrap.ts)
κ° μλ²λ autoStartStdioMcpServer()λ‘ stdio κΈ°λ° λΆνΈμ€νΈλνλλ€. νκ²½λ³μλ‘ κ°λ³ λλ μ 체 λΉνμ±ν κ°λ₯νλ€.
| νκ²½λ³μ | λμ |
|---|---|
OMX_MCP_SERVER_DISABLE_AUTO_START=1 | μ 체 5κ° μλ² λΉνμ±ν |
OMX_STATE_SERVER_DISABLE_AUTO_START=1 | state μλ²λ§ |
OMX_MEMORY_SERVER_DISABLE_AUTO_START=1 | memory μλ²λ§ |
OMX_CODE_INTEL_SERVER_DISABLE_AUTO_START=1 | code-intel μλ²λ§ |
OMX_TRACE_SERVER_DISABLE_AUTO_START=1 | trace μλ²λ§ |
OMX_TEAM_SERVER_DISABLE_AUTO_START=1 | team μλ²λ§ |
λΉλ νλ‘μΈμ€
src/mcp/*.ts β tsc (TypeScript μ»΄νμΌ) β dist/mcp/*.js
OMCλ esbuild β bridge/mcp-server.cjs λ¨μΌ λ²λ€μ΄μμ§λ§, OMXλ tscλ‘ κ° μλ²λ₯Ό κ°λ³ JS νμΌλ‘ μ»΄νμΌνλ€. μλ²λ³ λ
립 μ€νμ΄ κ°λ₯ν ꡬ쑰λ€.
omx_state β μν¬νλ‘μ° μν κ΄λ¦¬ (5κ° λꡬ)
λꡬ λͺ©λ‘
| λꡬ | μν | νμ νλΌλ―Έν° |
|---|---|---|
state_read | λͺ¨λλ³ μν μ½κΈ° | mode |
state_write | λͺ¨λλ³ μν μ°κΈ°/μ λ°μ΄νΈ | mode |
state_clear | λͺ¨λλ³ μν μμ | mode |
state_list_active | νμ¬ νμ± λͺ¨λ λͺ©λ‘ | (μμ) |
state_get_status | λͺ¨λλ³ μμΈ μν μ‘°ν | (μμ, modeλ μ ν) |
μ§μ λͺ¨λ (6κ°)
const SUPPORTED_MODES = [
"autopilot", "team", "ralph", "ultrawork", "ultraqa", "ralplan"
] as const;state_write μμΈ β ν΅μ¬ λꡬ
state_write({
mode: "ralph", // νμ: 6κ° λͺ¨λ μ€ νλ
active: true, // νμ± μν
iteration: 1, // νμ¬ λ°λ³΅ νμ
max_iterations: 10, // μ΅λ λ°λ³΅
current_phase: "executing", // νμ¬ λ¨κ³
task_description: "refactor API",
started_at: "2026-03-19T...",
state: { ... } // μΆκ° 컀μ€ν
νλ
})λμ λ°©μ:
- κΈ°μ‘΄ μνμ deep merge (κΈ°μ‘΄ νλ 보쑴)
- Atomic write: μμ νμΌ μμ± β rename (λ°μ΄ν° μμ€ λ°©μ§)
- Write-lock queue: λμΌ νμΌμ λν λμ μ°κΈ°λ₯Ό Promise 체μΈμΌλ‘ μ§λ ¬ν
- Ralph λͺ¨λλ
validateAndNormalizeRalphState()λ‘ phaseλ₯Ό μΆκ° κ²μ¦
μν νμΌ μ μ₯ ꡬ쑰
.omx/state/
βββ {mode}-state.json # Root scope (κΈλ‘λ²)
βββ session.json # νμ¬ μΈμ
λ§μ»€
βββ sessions/
βββ {sessionId1}/
β βββ {mode}-state.json # μΈμ
μ€μ½ν
βββ {sessionId2}/
βββ {mode}-state.json
μ€μ½ν μ°μ μμ (μμ€: src/mcp/state-paths.ts)
μ½κΈ° μ (state_read):
- λͺ
μμ
session_idμ 곡 β ν΄λΉ μΈμ κ²½λ‘λ§ - νμ¬ μΈμ
μ‘΄μ¬ (
session.json) β μΈμ μ°μ , root ν΄λ°± - μΈμ μμ β rootλ§
μ°κΈ° μ (state_write):
- νμ effective scopeμ κΈ°λ‘ (λͺ μ > νμ¬ μΈμ > root)
omx_memory β νλ‘μ νΈ λ©λͺ¨λ¦¬μ λ ΈνΈν¨λ (8κ° λꡬ)
Project Memory (4κ° λꡬ) β .omx/project-memory.json
| λꡬ | μν |
|---|---|
project_memory_read | μ 체 λλ μΉμ
λ³ μ½κΈ° (techStack, build, conventions, structure, notes, directives) |
project_memory_write | μ 체 κ΅μ²΄ λλ deep merge |
project_memory_add_note | νμμ€ν¬ν λ©λͺ¨ μΆκ° (μΉ΄ν
κ³ λ¦¬: build/test/deploy/env/architecture) |
project_memory_add_directive | μ°μ μμ μ§μ μΆκ° (high/normal) |
ν¬λ‘μ€ μΈμ λμ: νλ‘μ νΈλΉ 1κ° νμΌ, μΈμ μ€μ½ν μμ β λͺ¨λ μΈμ μ΄ κ°μ λ©λͺ¨λ¦¬λ₯Ό 곡μ νλ€.
interface ProjectMemory {
techStack?: string;
build?: string;
conventions?: string;
structure?: string;
notes?: Array<{ category: string; content: string; timestamp: string }>;
directives?: Array<{ directive: string; priority: string; timestamp: string }>;
}Notepad (4κ° λꡬ) β .omx/notepad.md
λ§ν¬λ€μ΄ κΈ°λ° μΈμ λ ΈνΈλ‘, 3κ° μΉμ μΌλ‘ ꡬλΆλλ€.
| λꡬ | λμ μΉμ | λμ |
|---|---|---|
notepad_read | μ 체 λλ μΉμ λ³ | μ½κΈ° |
notepad_write_priority | ## PRIORITY | κ΅μ²΄ (λ¨μΌ 컨ν μ€νΈ λΈλ‘, μ΅λ 500μ) |
notepad_write_working | ## WORKING MEMORY | μΆκ° (νμμ€ν¬ν μνΈλ¦¬, μλ μ 리 λμ) |
notepad_write_manual | ## MANUAL | μΆκ° (μꡬ 보쑴, μλ μ 리 μ λ¨) |
μΆκ° μ νΈλ¦¬ν°: notepad_prune (NμΌ μ΄μ WORKING MEMORY μ 리, κΈ°λ³Έ 7μΌ), notepad_stats (ν΅κ³)
## PRIORITY
νμ¬ μ΅μ°μ 컨ν
μ€νΈ (μΈμ
λ§λ€ κ΅μ²΄λ¨)
## WORKING MEMORY
[2026-03-19T10:00:00Z] API 리ν©ν° μ§ν μ€
[2026-03-19T11:30:00Z] ν
μ€νΈ ν΅κ³Ό νμΈ
## MANUAL
νλ‘μ νΈλ³ μꡬ λ©λͺ¨ (μλ μ 리 μ λ¨)omx_code_intel β μ½λ μΈν 리μ μ€ (9κ° λꡬ)
Codex CLIμλ Claude Code κ°μ λΉνΈμΈ LSP λκ΅¬κ° μλ€. OMXλ CLI λꡬ(tsc, ast-grep, grep)λ₯Ό λννμ¬ μ€μ©μ μ½λ μΈν 리μ μ€λ₯Ό μ 곡νλ€.
λꡬ λΆλ₯
| μΉ΄ν κ³ λ¦¬ | λꡬ | ꡬν λ°©μ |
|---|---|---|
| μ§λ¨ | lsp_diagnostics | tsc --noEmit μ€ν β νμΌλ³ νν°λ§ |
| μ§λ¨ | lsp_diagnostics_directory | νλ‘μ νΈ μ 체 νμ μ²΄ν¬ β νμΌλ³ κ·Έλ£Ήν |
| μ¬λ³Ό κ²μ | lsp_document_symbols | Regex κΈ°λ° μΆμΆ (15+ μΈμ΄ μ§μ) |
| μ¬λ³Ό κ²μ | lsp_workspace_symbols | μν¬μ€νμ΄μ€ μ 체 μ¬λ³Ό κ²μ (6λ¨κ³ κΉμ΄, μ΅λ 50κ°) |
| μ¬λ³Ό κ²μ | lsp_hover | μμΉ κΈ°λ° λ¨μ΄ μΆμΆ + λ‘컬 μ μ μ°ΎκΈ° |
| μ°Έμ‘° | lsp_find_references | grep -rn -wλ‘ μ¬λ³Ό μ°Έμ‘° μ°ΎκΈ° |
| μλ² μν | lsp_servers | tsc, ast-grep, grep κ°μ©μ± νμΈ |
| AST | ast_grep_search | ast-grep CLI ν¨ν΄ λ§€μΉ ($NAME, $$$ARGS λ©νλ³μ) |
| AST | ast_grep_replace | AST κΈ°λ° μ½λ μΉν (κΈ°λ³Έ dry-run) |
OMC LSP λꡬμμ λΉκ΅
| νλͺ© | OMC | OMX |
|---|---|---|
| ꡬν λ°©μ | Claude Code λΉνΈμΈ LSP λꡬ | CLI λꡬ λν (tsc, ast-grep, grep) |
| LSP νλ‘ν μ½ | μ§μ ν LSP νλ‘ν μ½ μ¬μ© | λ―Έμ¬μ© β CLI μΆλ ₯ νμ± |
| μ§λ¨ | lsp_diagnostics (λΉνΈμΈ) | tsc --noEmit β JSON νμ± |
| μ¬λ³Ό | lsp_document_symbols (LSP) | Regex κΈ°λ° μΆμΆ |
| hover | lsp_hover (LSP) | Regex κΈ°λ° κ·Όμ¬μΉ |
| AST | ast_grep_search/replace (λΉνΈμΈ) | ast-grep CLI λν |
| μΈμ΄ μ§μ | LSP μλ² μμ‘΄ | TS, Python, Go, Rust λ± 15+ (regex ν¨ν΄) |
omx_trace β μ€ν μΆμ (2κ° λꡬ)
λꡬ
| λꡬ | μν | μ£Όμ νλΌλ―Έν° |
|---|---|---|
trace_timeline | μκ°μ μμ΄μ νΈ νλ νμλΌμΈ | last (μ΅κ·Ό Nκ°), filter (all/turns/modes) |
trace_summary | μ§κ³ ν΅κ³ (ν΄ μ, λͺ¨λ μ¬μ©λ, ν ν° μλΉ) | (μμ) |
λ°μ΄ν° μμ€
graph LR subgraph νμ¬μΈμ ["νμ¬ μΈμ λ°μ΄ν°"] TL[".omx/logs/turns-*.jsonl"] MS[".omx/state/{mode}-state.json"] MT[".omx/metrics.json"] end subgraph νμ€ν 리["μΈμ νμ€ν 리 (λ³λ λͺ¨λ)"] RL[".codex/sessions/rollout-*.jsonl"] end TL --> TT["trace_timeline"] MS --> TT MT --> TS["trace_summary"] TL --> TS RL --> SH["session-history/search.ts<br/>(searchSessionHistory)"] style TT fill:#e8f0fe style TS fill:#e8f0fe style SH fill:#fef7e0
- trace_timeline/summary: νμ¬ μΈμ
μ
.omx/logs/λ‘κ·Έ + λͺ¨λ μν + λ©νΈλ¦μ€ - session-history: κ³Όκ±° μΈμ
μ
.codex/sessions/rollout-*.jsonlκ²μ (trace μλ²μ λ 립)
omx_team_run β Team μ‘°μ¨ (4κ° λꡬ + deprecated)
νμ‘΄ λꡬ (4κ°)
| λꡬ | μν |
|---|---|
omx_run_team_start | tmux worker μ€ν° (codex/claude/gemini), jobId μ¦μ λ°ν |
omx_run_team_status | λ ΌλΈλ‘νΉ μν νμΈ |
omx_run_team_wait | λΈλ‘νΉ ν΄λ§ + μλ nudge + μ΄λ²€νΈ λͺ¨λ |
omx_run_team_cleanup | worker pane μ 리 (leader/HUD 보쑴) |
Deprecated λꡬ β CLI μ νΈ μ΄μ
20+ ν μ‘°μ λꡬ(team_send_message, team_broadcast, team_create_task λ±)κ° hard-deprecated λμλ€. νΈμΆ μ code: "deprecated_cli_only" μλ¬μ ν¨κ» CLI λμ ννΈλ₯Ό λ°ννλ€.
Deprecation μ΄μ :
- MCP νλ‘ν μ½μ μνλΉμ μ₯ νΉμ± β teamμ tmux μΈμ /λ°νμ μλͺ μ£ΌκΈ°μ νΈν λΆκ°
- CLI μΈν°μ΅ νμ β tmux μΈμ κ΄λ¦¬, λ°νμ μν μ λ°μ΄νΈμ CLI 컨ν μ€νΈ νμ
- λμ:
omx team api ...CLI λͺ λ ΉμΌλ‘ λμΌ κΈ°λ₯ μν
MCP workingDirectory Hardening β 보μ
κ²½λ‘ κ²μ¦ λ€κ³μΈ΅ (μμ€: src/mcp/state-paths.ts)
| κ³μΈ΅ | κ²μ¦ λ΄μ© |
|---|---|
| NUL λ°μ΄νΈ | \0 ν¬ν¨ μ κ±°λΆ |
| Path Traversal | .. μνμ€ μ°¨λ¨ |
| Mode Segment | ^[A-Za-z0-9_-]{1,64}$ ν¨ν΄ κ°μ (κ²½λ‘ κ΅¬λΆμ λΆν) |
| Session ID | ^[A-Za-z0-9_-]{1,64}$ ν¨ν΄ κ°μ |
| Allowlist | OMX_MCP_WORKDIR_ROOTS μ€μ μ νμ© λ£¨νΈ μΈ κ±°λΆ |
OMX_MCP_WORKDIR_ROOTS β λλ ν 리 μλλ°μ±
# Unix: μ½λ‘ ꡬλΆ
export OMX_MCP_WORKDIR_ROOTS="/home/user/projects:/tmp/sandbox"
# Windows: μΈλ―Έμ½λ‘ ꡬλΆ
set OMX_MCP_WORKDIR_ROOTS="C:\projects;D:\sandbox"μ€μ μ MCP μλ²κ° νμ©λ λ£¨νΈ νμ λλ ν 리μμλ§ λμνλ€. isWithinRoot() ν¨μκ° μλ κ²½λ‘ κ³μ°μΌλ‘ νμΆ μ¬λΆλ₯Ό κ²μ¦νλ€.
OMC MCPμμ μ 체 λΉκ΅
| νλͺ© | OMC | OMX |
|---|---|---|
| μλ² μ | 1κ° βtβ (ν΅ν©) | 5κ° (κ΄μ¬μ¬ λΆλ¦¬) |
| λ±λ‘ λ°©μ | .mcp.json | config.toml |
| λΉλ λ°©μ | esbuild β λ¨μΌ .cjs | tsc β κ°λ³ .js |
| μ΄ λꡬ μ | 30+ | 28κ° (state 5 + memory 8 + code-intel 9 + trace 2 + team 4) |
| λΉνμ±ν | λΆκ° (μλ² ν΅ν©) | κ°λ³/μ 체 νκ²½λ³μ |
| LSP ꡬν | Claude Code λΉνΈμΈ | CLI λν (tsc, ast-grep, grep) |
| μν μ€μ½ν | λ¨μΌ scope | μΈμ μ€μ½ν (session.json κΈ°λ°) |
| ν¬λ‘μ€ μΈμ | notepad + project-memory | project-memory.json + notepad.md (ꡬ쑰 λμΌ) |
| 보μ | μμ | workdir allowlist + path validation |