Version: 0.13.1 | License: MIT | Repository: Yeachan-Heo/oh-my-codex
Table of Contents
- Architecture Overview
- System Requirements
- Configuration Reference
- Deployment & Scaling
- Operations
- Performance
- Security
- Developer Internals
- Integration Points
1. Architecture Overview
oh-my-codex (OMX) is a multi-agent orchestration layer that sits on top of OpenAI Codex CLI. It transforms single-agent Codex sessions into coordinated multi-agent teams operating inside tmux sessions, with a Rust-backed native runtime for state management and an extensible hook and plugin system for deep Codex integration.
1.1 Component Inventory
oh-my-codex
├── TypeScript Layer (src/)
│ ├── cli/ — CLI entry + all subcommand handlers (28 files, ~490K chars)
│ ├── team/ — Multi-agent team orchestration (27 files, ~600K chars)
│ ├── notifications/ — Discord / Telegram / Slack (18 files, ~180K chars)
│ ├── mcp/ — 5 MCP servers (8 files, ~97K chars)
│ ├── hooks/ — Codex hook integration (8 files, ~95K chars)
│ │ ├── extensibility/ — Plugin system (9 files, ~27K chars)
│ │ └── code-simplifier/ — Code simplification hook
│ ├── hud/ — Heads-up display (9 files, ~52K chars)
│ ├── autoresearch/ — Experiment loops (2 files, ~53K chars)
│ ├── config/ — Config generators (4 files, ~52K chars)
│ ├── adapt/ — Adapter framework (6 files, ~47K chars)
│ ├── state/ — Mode state management (6 files, ~41K chars)
│ ├── openclaw/ — OpenClaw integration (4 files, ~35K chars)
│ ├── utils/ — Shared utilities (9 files, ~33K chars)
│ ├── agents/ — Agent definitions (2 files, ~21K chars)
│ ├── catalog/ — Skill/agent catalog (3 files, ~16K chars)
│ ├── pipeline/ — Pipeline orchestrator (3 files, ~15K chars)
│ ├── ralph/ — Verification loop (2 files, ~14K chars)
│ ├── session-history/ — Session history search (1 file, ~12K chars)
│ ├── runtime/ — Runtime bridge to Rust (1 file, ~10K chars)
│ ├── modes/ — Base mode lifecycle (1 file, ~9K chars)
│ ├── ralplan/ — RALPLAN mode runtime (1 file, ~9K chars)
│ ├── subagents/ — Subagent tracker (1 file, ~8K chars)
│ ├── planning/ — Planning artifacts (1 file, ~5K chars)
│ ├── verification/ — Verifier (1 file, ~3.5K chars)
│ └── visual/ — Visual verdict validation (2 files, ~3K chars)
│
├── Rust Layer (crates/)
│ ├── omx-explore-harness — Sandboxed exploration binary
│ ├── omx-mux — tmux multiplexer abstractions
│ ├── omx-runtime-core — Core runtime engine
│ ├── omx-runtime — Runtime binary wrapper
│ └── omx-sparkshell — Shell command runner with AI summary
│
├── prompts/ — 30+ agent prompt files
├── skills/ — 35+ skill definitions (SKILL.md)
├── missions/ — Experiment mission definitions
├── templates/ — AGENTS.md template, catalog-manifest.json
└── playground/ — Demo scripts
1.2 High-Level Architecture Diagram
┌─────────────────────────────────────────────────────────────────────┐
│ User / CI / Script │
└────────────────────────────┬────────────────────────────────────────┘
│ omx <command>
▼
┌─────────────────────────────────────────────────────────────────────┐
│ CLI Layer (src/cli/) │
│ team | run | skill | plan | research | history | config | ... │
└───────────┬─────────────────────────────────────────────────────────┘
│
┌──────┴──────────────────────────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌────────────────────────┐
│ Pipeline │ │ Direct Skill / Mode │
│ (RALPLAN → │ │ Execution │
│ Team Exec → │ └────────────────────────┘
│ Ralph Verify) │
└────────┬────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Team Orchestration (src/team/) │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ Leader │ │ Workers │ │ Mailbox │ │ Phase Control │ │
│ │ (tmux) │◄─┤ (tmux panes)│ │ (MCP) │ │ (lifecycle) │ │
│ └──────────┘ └──────────────┘ └──────────┘ └───────────────┘ │
└───────────┬──────────────────────┬──────────────────────────────────┘
│ │
▼ ▼
┌────────────────────┐ ┌──────────────────────────────────────────┐
│ Rust Runtime │ │ MCP Servers (stdio processes) │
│ (omx-runtime) │ │ state | memory | code_intel | trace │
│ omx-runtime-core │ │ | wiki │
│ omx-mux │ └──────────────────────────────────────────┘
│ omx-sparkshell │
│ omx-explore- │
│ harness │
└────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Codex CLI (external) │
│ hooks: SessionStart, PreToolUse, PostToolUse, │
│ UserPromptSubmit, Stop │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Notifications (src/notifications/) │
│ Discord webhook/bot | Telegram | Slack │
└─────────────────────────────────────────────────────────────────────┘
1.3 Technology Stack
| Layer | Technology | Version / Notes |
|---|---|---|
| CLI runtime | Node.js | >= 20 required |
| Language (TS) | TypeScript | Compiled to JS |
| Language (native) | Rust | Edition 2021 |
| Agent protocol | OpenAI Codex CLI | External dependency |
| Terminal multiplexer | tmux | Required for team mode |
| MCP protocol | Model Context Protocol | stdio transport |
| Distribution | cargo-dist | Cross-platform native binaries |
| Test runner | Node.js --test |
Built-in test runner |
| Coverage | c8 | V8 coverage |
| Cargo tests | cargo test | Per-crate + compat tests |
1.4 Key Design Decisions
File-based state machine. All mode state lives in .omx/state/ as JSON files. No database, no message broker. This makes state inspectable with any text tool and resilient to process crashes — the last-written file wins.
Atomic tmux pane operations. The Rust omx-mux crate wraps tmux pane I/O through capture, input injection, and delivery confirmation primitives. Injection is confirmed before the caller proceeds, preventing race conditions in multi-pane environments.
Authority lease system. omx-runtime-core's AuthorityLease model ensures only one runtime process holds authority over a session at a time. Replays reconstruct state from a DispatchLog on restart, making the runtime crash-safe.
Dual-model architecture. SparkShell selects between a "spark" (lighter, faster) model and a "frontier" (more capable) model based on output line count. This caps cost for routine shell summaries while preserving quality for large outputs.
POSIX-only explore harness. omx-explore-harness runs only on POSIX systems. The sandboxed PATH allowlist ensures the Codex subprocess cannot access host tools outside the approved set.
2. System Requirements
2.1 Runtime Prerequisites
| Requirement | Minimum | Notes |
|---|---|---|
| Node.js | 20.0.0 | LTS or current; ESM support required |
| tmux | Any recent | Required for team mode; must be in PATH |
| OpenAI Codex CLI | Latest | Installed separately; codex must be in PATH |
| Git | 2.x+ | Used for worktree management and branch operations |
| Rust toolchain | 1.70+ (approx.) | Only needed for building from source |
| OS | Linux / macOS | POSIX required for omx-explore-harness; Windows supported for other features via x86_64-pc-windows-msvc binary |
2.2 Optional Prerequisites
| Dependency | Purpose | Required When |
|---|---|---|
| Discord bot token / webhook | Discord notifications | OMX_DISCORD_* configured |
| Telegram bot | Telegram notifications | OMX_TELEGRAM_* configured |
| Slack webhook | Slack notifications | OMX_SLACK_WEBHOOK_URL configured |
| OpenClaw server | External tool adapter | OMX_OPENCLAW=true |
2.3 Supported Platforms (cargo-dist targets)
| Target | Platform |
|---|---|
aarch64-apple-darwin |
macOS ARM (M-series) |
x86_64-apple-darwin |
macOS Intel |
aarch64-unknown-linux-gnu |
Linux ARM64 (glibc) |
aarch64-unknown-linux-musl |
Linux ARM64 (musl/static) |
x86_64-unknown-linux-gnu |
Linux x86_64 (glibc) |
x86_64-unknown-linux-musl |
Linux x86_64 (musl/static) |
x86_64-pc-windows-msvc |
Windows x86_64 |
Important
omx-explore-harnessis POSIX-only and will not build or run on Windows. All other crates support the full target matrix above.
2.4 Network Requirements
- Outbound HTTPS to OpenAI API endpoints (via Codex CLI)
- Outbound HTTPS to Discord/Telegram/Slack APIs (if notifications enabled)
- No inbound port requirements — OMX is a CLI tool, not a server
3. Configuration Reference
3.1 Environment Variables — Complete Reference
All environment variables are sourced from config_keys.tsv. They are grouped by subsystem below.
3.1.1 Team & Session Variables
| Variable | Purpose | Default |
|---|---|---|
OMX_TEAM_STATE_ROOT |
Override team state directory path | .omx/state/ |
OMX_JOBS_DIR |
Jobs directory path | (derived from state root) |
OMX_TEAM_WORKER_CLI_MAP |
JSON mapping of worker names to CLI commands | — |
OMX_JOB_ID |
Current job identifier (injected by leader into worker env) | — |
OMX_TEAM_WORKER |
Current worker identifier (injected by leader) | — |
OMX_TEAM_WORKER_LAUNCH_ARGS |
Additional CLI arguments appended to worker launch command | — |
OMX_TEAM_MOUSE |
Enable mouse support in team tmux session | — |
OMX_TEAM_AUTO_ACCEPT_BYPASS |
Auto-accept bypass for worker prompts (dangerous — see §7) | — |
OMX_TEAM_SEND_STRATEGY |
Message delivery strategy for workers | — |
OMX_TEAM_AUTO_TRUST |
Auto-trust worker agents without confirmation | — |
OMX_TEAM_STRICT_SUBMIT |
Require strict submit validation before task acceptance | — |
OMX_RUNTIME_CLI_DISABLE_AUTO_START |
Disable automatic runtime CLI startup | — |
CODEX_HOME |
Codex home directory (read by both OMX and Codex) | ~/.codex |
OMX_SESSION_ID |
Session identifier (checked first) | — |
CODEX_SESSION_ID |
Session identifier (checked second) | — |
SESSION_ID |
Session identifier (checked third) | — |
TMUX_PANE |
Current tmux pane ID (set by tmux) | — |
SHELL |
Default shell for command execution | System default |
WSL_DISTRO_NAME |
WSL distro name (used for WSL detection) | — |
WSL_INTEROP |
WSL interop socket path (used for WSL detection) | — |
3.1.2 Notification Variables
| Variable | Purpose |
|---|---|
OMX_DISCORD_WEBHOOK_URL |
Discord incoming webhook URL |
OMX_DISCORD_NOTIFIER_BOT_TOKEN |
Discord bot token (for bot-based notifications) |
OMX_DISCORD_NOTIFIER_CHANNEL |
Discord channel ID (used with bot token) |
OMX_DISCORD_MENTION |
Discord mention string: <@!USER_ID> or <@&ROLE_ID> |
OMX_TELEGRAM_BOT_TOKEN |
Telegram bot token (primary key) |
OMX_TELEGRAM_NOTIFIER_BOT_TOKEN |
Telegram bot token (alternate key) |
OMX_TELEGRAM_CHAT_ID |
Telegram chat ID (primary key) |
OMX_TELEGRAM_NOTIFIER_CHAT_ID |
Telegram chat ID (alternate key) |
OMX_TELEGRAM_NOTIFIER_UID |
Telegram user ID (alternate key) |
OMX_SLACK_WEBHOOK_URL |
Slack incoming webhook URL |
OMX_SLACK_MENTION |
Slack mention: <@USERID>, <!channel>, <!here> |
OMX_NOTIFY_PROFILE |
Active notification profile name |
OMX_NOTIFY_VERBOSITY |
Notification verbosity level |
OMX_DISPATCH_COOLDOWN_SECONDS |
Minimum seconds between dispatched notifications |
OMX_IDLE_COOLDOWN_SECONDS |
Idle notification cooldown seconds |
OMX_HOOK_CONFIG |
Hook configuration path or JSON |
OMX_REPLY_ENABLED |
Enable reply listener (accepts commands via notification platform) |
OMX_REPLY_DISCORD_USER_IDS |
Comma-separated Discord user IDs allowed to send replies |
OMX_REPLY_POLL_INTERVAL_MS |
Polling interval (ms) for the reply listener |
OMX_REPLY_RATE_LIMIT |
Max replies per interval before throttling |
OMX_REPLY_INCLUDE_PREFIX |
Prefix required in reply messages |
OMX_NOTIFY_FALLBACK_MAX_LIFETIME_MS |
Max lifetime (ms) of the fallback notification watcher |
3.1.3 OpenClaw Variables
| Variable | Purpose |
|---|---|
OMX_OPENCLAW |
Set to true to enable OpenClaw integration |
OMX_OPENCLAW_CONFIG |
Path to OpenClaw config file (overrides auto-discovery) |
OMX_OPENCLAW_COMMAND |
OpenClaw command gateway executable |
OMX_OPENCLAW_COMMAND_TIMEOUT_MS |
Timeout (ms) for command gateway calls |
OMX_OPENCLAW_DEBUG |
Enable OpenClaw debug logging |
OPENCLAW_REPLY_CHANNEL |
Reply routing: channel name |
OPENCLAW_REPLY_TARGET |
Reply routing: target identifier |
OPENCLAW_REPLY_THREAD |
Reply routing: thread identifier |
3.1.4 SparkShell & Explore Variables
| Variable | Purpose |
|---|---|
OMX_SPARKSHELL_MODEL |
Override SparkShell model |
OMX_DEFAULT_SPARK_MODEL |
Default spark (lightweight) model |
OMX_SPARK_MODEL |
Spark model selection |
OMX_SPARKSHELL_FALLBACK_MODEL |
Fallback if primary model fails |
OMX_DEFAULT_FRONTIER_MODEL |
Default frontier (powerful) model |
OMX_SPARKSHELL_SUMMARY_TIMEOUT_MS |
Timeout (ms) for AI summary generation |
OMX_SPARKSHELL_LINES |
Line count threshold: outputs above this get frontier model |
ComSpec |
Windows command spec (used on Windows platforms) |
3.1.5 MCP Server Variables
| Variable | Purpose |
|---|---|
OMX_MCP_SERVER_DISABLE_AUTO_START |
Disable all MCP server auto-start globally |
OMX_STATE_SERVER_DISABLE_AUTO_START |
Disable state MCP server only |
OMX_MEMORY_SERVER_DISABLE_AUTO_START |
Disable memory MCP server only |
OMX_CODE_INTEL_SERVER_DISABLE_AUTO_START |
Disable code_intel MCP server only |
OMX_TRACE_SERVER_DISABLE_AUTO_START |
Disable trace MCP server only |
OMX_WIKI_SERVER_DISABLE_AUTO_START |
Disable wiki MCP server only |
OMX_MCP_TRANSPORT_DEBUG |
Enable MCP transport debug logging to stderr |
3.1.6 Runtime & Miscellaneous Variables
| Variable | Purpose |
|---|---|
OMX_AUTO_UPDATE |
Auto-update behavior on startup |
OMX_MOUSE |
Enable mouse support globally |
OMX_HOOK_DERIVED_SIGNALS |
Hook derived signals configuration |
OMX_RUNTIME_BRIDGE |
Override path to the runtime bridge binary |
OMX_RUNTIME_BINARY |
Override path to the runtime binary |
OMX_TMUX_PID_FALLBACK |
Fallback PID for tmux attachment |
3.2 Configuration Files
3.2.1 AGENTS.md (per-project)
OMX reads and writes AGENTS.md at project root. This file defines agent roles, capabilities, and inter-agent communication protocols. A template lives at templates/AGENTS.md.
Warning
GitHub issue #1671 documents a bug where
omx updatemay overwrite a project's existingAGENTS.md. Until fixed, back upAGENTS.mdbefore running update commands.
3.2.2 Catalog Manifest (templates/catalog-manifest.json)
Defines the registry of available skills and agents. The src/catalog/ module reads this manifest and validates entries against a JSON schema. Keys include skill names, entry points, and metadata.
3.2.3 Codex Hooks Config
Generated by src/config/ (the hooks config generator). Produces a JSON/TOML config consumed by Codex CLI specifying which OMX hook handlers fire on which Codex events.
3.2.4 OpenClaw Config
Path set via OMX_OPENCLAW_CONFIG or auto-discovered. Contains gateway type (HTTP or command), endpoint, timeout, and reply routing parameters.
3.3 State Directory Layout
.omx/
└── state/
├── mode/ — Active mode state files (JSON)
├── session/ — Per-session state files
├── jobs/ — Job definitions and status
├── ralph/ — Verification phase state
├── subagents/ — Subagent tracker state
└── dispatch/ — Dispatch notification log
All state files are JSON. Write operations are atomic (write temp → rename).
3.4 Skill Definitions (skills/)
Each skill is defined by a SKILL.md file. The catalog loader reads these files and registers skills into the catalog. Skills define:
- Name and description
- Required inputs / parameters
- Execution entry point
- Agent role affinity
Skills are namespaced under omx: prefix (see known issue #1648 — built-in skills not yet fully namespaced; in-progress).
3.5 Agent Prompts (prompts/)
30+ agent prompt files define role-specific system prompts. Covered roles include (non-exhaustive):
analyst.md,architect.md,debugger.md,executor.mdplanner.md,verifier.md,reviewer.md,researcher.md- Domain-specific roles added as the catalog grows
Prompts are loaded by the agent bootstrap process and injected as system context.
4. Deployment & Scaling
4.1 Installation (End-User)
# Via npm (TypeScript layer)
npm install -g oh-my-codex
# Verify
omx --version
Native Rust binaries are bundled with the npm package via cargo-dist. They are extracted to a platform-appropriate location on first run if not already present.
4.2 Building from Source
TypeScript Layer
git clone https://github.com/Yeachan-Heo/oh-my-codex.git
cd oh-my-codex
npm install
npm run build
Rust Crates
# Build all crates
cargo build --release
# Build a specific crate
cargo build -p omx-runtime --release
cargo build -p omx-mux --release
cargo build -p omx-sparkshell --release
cargo build -p omx-explore-harness --release # POSIX only
Note
omx-explore-harnesswill fail to compile on Windows (x86_64-pc-windows-msvc). Exclude it from Windows builds:cargo build --release --exclude omx-explore-harness
Running Tests
# TypeScript tests
node --test
# With coverage
npx c8 node --test
# Rust tests (all crates)
cargo test
# TypeScript <-> Rust compat tests
cargo test -p omx-runtime # includes compat suite
Coverage thresholds (team critical paths):
| Metric | Threshold |
|---|---|
| Lines | 78% |
| Functions | 90% |
| Branches | 70% |
| Statements | 78% |
4.3 Release Process (cargo-dist)
OMX uses cargo-dist for cross-platform binary distribution. The dist configuration lives in Cargo.toml or dist.toml.
# Dry-run release plan
cargo dist plan
# Build release artifacts locally
cargo dist build
# Trigger CI release (tag-based)
git tag v0.13.1
git push origin v0.13.1
CI produces native binaries for all 7 targets and publishes them as GitHub Release assets. The npm package downloads the appropriate binary for the host platform on install.
4.4 Scaling the Team
OMX team mode scales by adjusting the number of worker panes. Workers are tmux panes, not OS processes in the traditional sense — each is a Codex CLI session managed by OMX.
Scale up: Leader spawns additional worker panes via src/team/ scaling logic, assigns new worktrees via Git, and bootstraps new worker sessions.
Scale down: Leader sends graceful shutdown signal; workers finish current tasks, release worktrees, and exit. Leader kills panes.
Worktree isolation: Each worker operates in a dedicated Git worktree, providing filesystem isolation. Tasks are allocated with path-overlap scoring to minimize merge conflicts.
Tip
For CPU-bound analysis tasks, scale up workers. For I/O-bound tasks (API calls, file reads), 3-5 workers is typically optimal. Watch tmux pane activity; idle panes waste Codex API quota.
4.5 Deployment Topology
OMX has no server component. Deployment means installing the package on any machine where users run Codex CLI. For CI/CD use:
# Example GitHub Actions
- name: Install oh-my-codex
run: npm install -g oh-my-codex
- name: Run OMX pipeline
run: omx run --skill my-skill
env:
OMX_DISCORD_WEBHOOK_URL: ${{ secrets.OMX_DISCORD_WEBHOOK_URL }}
5. Operations
5.1 State Inspection
Because state is file-based, any standard UNIX tool works:
# View current mode
cat .omx/state/mode/*.json | jq .
# View job queue
ls -la .omx/state/jobs/
# View dispatch log
cat .omx/state/dispatch/*.json | jq .
# Watch for state changes
watch -n1 'cat .omx/state/mode/*.json | jq .'
5.2 MCP Server Management
MCP servers are stdio processes started automatically by OMX. Each has a parent watchdog that polls every 25ms; if the parent process disappears, the server exits within one watchdog cycle.
Disable specific servers (useful for debugging or resource constraints):
export OMX_STATE_SERVER_DISABLE_AUTO_START=1
export OMX_MEMORY_SERVER_DISABLE_AUTO_START=1
# ... etc
Disable all servers:
export OMX_MCP_SERVER_DISABLE_AUTO_START=1
Debug MCP transport:
export OMX_MCP_TRANSPORT_DEBUG=1
omx team start
# Transport frames logged to stderr
Caution
GitHub issue #1665 documents that MCP duplicate sibling processes can accumulate if parent detection fails. Monitor process counts with
ps aux | grep omx-mcpand kill stray processes if needed. The 5-second sibling detection window reduces but does not eliminate this risk.
5.3 Team Session Management
# Start a new team session
omx team start --workers 3
# Attach to existing session
omx team attach
# List active team sessions
tmux list-sessions | grep omx
# Kill a team session
omx team stop
# Or directly: tmux kill-session -t omx-SESSIONNAME
Warning
GitHub issue #1642 documents that detached leader cleanup may skip
tmux kill-session, leaving orphan sessions. Runtmux list-sessionsperiodically and kill stale sessions manually:tmux kill-session -t <session-name>
5.4 Job Queue Operations
# List pending jobs
ls .omx/state/jobs/
# Inspect a job
cat .omx/state/jobs/<job-id>.json | jq .
# Cancel a stuck job (delete the file — terminal state on next poll)
rm .omx/state/jobs/<job-id>.json
5.5 Session History
# Search session history
omx history search "query string"
# Uses fuzzy matching — partial matches are ranked by relevance
omx history search "fix auth bug"
The session history module (src/session-history/) indexes past sessions and supports fuzzy-match retrieval. History files are stored per-session in .omx/state/session/.
5.6 HUD (Heads-Up Display)
The HUD renders live team state in the tmux leader pane:
- Authority status (who holds the lease)
- Worker pane assignments and current task
- Phase progress (planning → executing → verifying → complete)
- Pending notifications
HUD state is reconciled from .omx/state/ on each render cycle. If the HUD freezes, inspect the state directory for inconsistencies.
Note
GitHub issue #1635 documents the leader UI getting stuck on MCP startup. If the HUD does not render after ~10 seconds, check MCP server stderr for startup errors and restart with
omx team stop && omx team start.
5.7 Monitoring Checklist
| Check | Command / Method |
|---|---|
| Active MCP servers | ps aux | grep omx-mcp |
| Stale tmux sessions | tmux list-sessions |
| State directory sanity | ls -la .omx/state/ |
| Ralph lock health | cat .omx/state/ralph/*.json | jq .phase |
| Dispatch cooldown | cat .omx/state/dispatch/*.json | jq .lastSent |
| Worker liveness | tmux list-panes -t <session> |
6. Performance
6.1 SparkShell Model Selection
omx-sparkshell implements a dual-model strategy for AI-assisted shell command summarization:
output_lines < OMX_SPARKSHELL_LINES → use spark model (OMX_SPARK_MODEL)
output_lines >= OMX_SPARKSHELL_LINES → use frontier model (OMX_DEFAULT_FRONTIER_MODEL)
Tuning recommendations:
| Scenario | Recommended Setting |
|---|---|
| Mostly short outputs (build logs) | Lower OMX_SPARKSHELL_LINES (e.g., 50) |
| Mostly long outputs (test suites) | Raise OMX_SPARKSHELL_LINES (e.g., 500) |
| Cost-sensitive environment | Set OMX_SPARKSHELL_MODEL to a cheap model |
| Accuracy-critical environment | Set OMX_DEFAULT_FRONTIER_MODEL to best available |
SparkShell is language-aware: it constructs prompts adapted to the programming language of the output context, improving summary quality without extra tokens.
6.2 MCP Server Lifecycle
Each MCP server is started as a stdio child process. The 25ms parent watchdog adds negligible overhead but ensures servers die with the parent.
Startup latency: Allow ~2-5 seconds for all 5 MCP servers to initialize and register with the parent. The leader HUD will show "MCP starting" during this window.
Memory footprint: Each MCP server is a lightweight Node.js process. Typical RAM per server: 30-60 MB. Total for 5 servers: ~200 MB baseline.
6.3 Team Worker Allocation Scoring
Task allocation uses a multi-factor scoring algorithm:
- Role match — Worker's assigned role vs. task's required role
- Domain hints — Keywords in task description vs. worker specialization
- Path overlap — Files in task scope vs. worker's current worktree
- Load balancing — Prefer workers with fewer in-flight tasks
Workers with the highest combined score receive the task. This is computed in src/team/ allocation logic at dispatch time.
6.4 Dispatch Cooldown
Notifications have two cooldown levels:
OMX_DISPATCH_COOLDOWN_SECONDS— Global cooldown between any dispatched notificationsOMX_IDLE_COOLDOWN_SECONDS— Cooldown specifically for idle-state notifications
Set these to avoid flooding notification channels during rapid task cycling.
6.5 Runtime Core Performance
omx-runtime-core uses an event-log architecture (DispatchLog) that enables O(1) appends and O(n) replay on restart. For long-lived sessions with thousands of events, consider periodic log rotation (no built-in mechanism; delete .omx/state/dispatch/ to reset).
The MailboxLog similarly grows unbounded over a session. For sessions running >24 hours, monitor mailbox file sizes.
7. Security
Caution
Several known security issues exist in v0.13.1. Review all items in this section before deploying OMX in shared or production environments.
7.1 Shell Injection Risks
Issue #1640 — buildWorkerStartupCommand shell injection.
Worker launch arguments (OMX_TEAM_WORKER_LAUNCH_ARGS) are interpolated into shell command strings. If this variable contains untrusted input, it can inject arbitrary shell commands.
Mitigation: Never set OMX_TEAM_WORKER_LAUNCH_ARGS from untrusted sources. Validate all values in CI pipelines before passing to OMX.
Issue #1659 — hud/state.ts git injection via remoteName.
The HUD reads the git remote name and uses it in git command construction without sanitization. A malicious remoteName (e.g., in .git/config) could inject arbitrary git flags.
Mitigation: Ensure .git/config is from a trusted source. Avoid running OMX against repositories with untrusted git configurations.
7.2 Path Traversal
Issue #1649 — Path traversal via unvalidated identifiers.
Skill names, job IDs, and other identifier fields used in file path construction are not validated for ../ sequences. A crafted identifier could traverse outside .omx/state/.
Mitigation: Until patched, enforce identifier validation at the call site (alphanumeric + hyphens only). Do not allow user-supplied identifiers to flow into OMX without sanitization.
7.3 Sensitive Data in Notifications
Issue #1661 — Reply listener leaks sensitive data.
The reply listener (OMX_REPLY_ENABLED) may include sensitive content (environment variables, file contents) in notification messages sent to Discord/Telegram/Slack.
Mitigation: Disable the reply listener unless required (OMX_REPLY_ENABLED unset or false). If enabled, restrict OMX_REPLY_DISCORD_USER_IDS to trusted operator IDs only. Use private channels for OMX notifications.
7.4 Auto-Accept Bypass
OMX_TEAM_AUTO_ACCEPT_BYPASS causes workers to skip confirmation prompts. This is intended for unattended CI runs but eliminates a human-in-the-loop safety check.
Warning
Do not set
OMX_TEAM_AUTO_ACCEPT_BYPASS=truein environments where workers have write access to production systems or sensitive credentials.
7.5 Explore Harness Sandbox
omx-explore-harness restricts the Codex subprocess's PATH to an allowlist. The sandboxed binary runs on POSIX only and provides filesystem-level isolation for exploration tasks.
The allowlist is hardcoded in the harness source. Verify its contents match your security policy before deploying explore mode.
7.6 Dependency Vulnerabilities
Issue #1660 — Transitive dependency vulnerabilities.
Run npm audit and cargo audit periodically:
npm audit
npm audit fix # for auto-fixable issues
cargo install cargo-audit
cargo audit
7.7 Signal Handling
Issue #1657 — SIGTERM without PID verification.
OMX sends SIGTERM to process groups without verifying PID before signal delivery. In unusual process tree configurations this could terminate unintended processes.
Mitigation: Run OMX in isolated process namespaces (e.g., Docker, systemd unit with PrivateTmp=yes) when operating near sensitive process groups.
7.8 Stale Lock Recovery
Issue #1655 — withTmuxExtendedKeysLeaseLock has no stale-lock recovery.
If a tmux extended keys lease is not released (e.g., process crash), subsequent operations that require this lock will hang indefinitely.
Mitigation: If OMX hangs on tmux operations, inspect .omx/state/ for stale lock files and remove them manually.
7.9 Authority Lease Security Model
The AuthorityLease in omx-runtime-core is a cooperative lock — it relies on all participants honoring the lease protocol. There is no kernel-level enforcement. In adversarial multi-user environments, a rogue process could bypass the lease.
8. Developer Internals
8.1 Repository Structure
oh-my-codex/
├── src/ TypeScript source
│ ├── cli/ CLI entry + subcommand handlers
│ ├── team/ Team orchestration
│ ├── notifications/ Notification subsystem
│ ├── mcp/ MCP servers
│ ├── hooks/ Codex hook handlers
│ │ ├── extensibility/ Plugin system
│ │ └── code-simplifier/
│ ├── hud/ Heads-up display
│ ├── autoresearch/ Experiment automation
│ ├── config/ Config generators
│ ├── adapt/ External tool adapters
│ ├── state/ Mode state management
│ ├── openclaw/ OpenClaw integration
│ ├── utils/ Shared utilities
│ ├── agents/ Agent definitions
│ ├── catalog/ Skill/agent catalog
│ ├── pipeline/ Pipeline orchestrator
│ ├── ralph/ Verification loop
│ ├── session-history/ Session history
│ ├── runtime/ Rust runtime bridge
│ ├── modes/ Mode base class
│ ├── ralplan/ RALPLAN mode
│ ├── subagents/ Subagent tracker
│ ├── planning/ Planning artifacts
│ ├── verification/ Verifier
│ └── visual/ Visual verdict validation
│
├── crates/ Rust crates
│ ├── omx-explore-harness/
│ ├── omx-mux/
│ ├── omx-runtime-core/
│ ├── omx-runtime/
│ └── omx-sparkshell/
│
├── prompts/ Agent role prompts (30+)
├── skills/ Skill definitions (35+ SKILL.md)
├── missions/ Experiment missions
├── templates/ AGENTS.md template, catalog manifest
├── playground/ Demo/benchmark scripts
├── package.json
├── tsconfig.json
└── Cargo.toml Workspace manifest
8.2 TypeScript Module Reference
src/cli/ — CLI Entry Point (28 files, ~490K chars)
The CLI uses a command-router pattern. omx dispatches to subcommand handlers based on argv[2]. Each subcommand file exports a run(args) function.
Key subcommands (inferred from architecture):
team— Team orchestration (start, stop, attach, scale)run— Single-shot skill or pipeline executionskill— Skill management (list, run, validate)plan— RALPLAN planning moderesearch— Autoresearch experiment loophistory— Session history searchconfig— Config generation (hooks, TOML, MCP registry)hud— HUD control
CLI argument parsing is handled inline (no heavy framework dependency). Flag values map directly to the environment variables documented in §3.1.
src/team/ — Team Orchestration (27 files, ~600K chars)
The largest TypeScript module. Key responsibilities:
Allocation (allocation.ts) — Scores worker-task assignments using role match, domain hints, path overlap, and load factors. Returns ranked worker list.
Worktrees (worktrees.ts) — Creates and destroys Git worktrees for worker isolation. Each worker gets its own branch checkout.
tmux Sessions (tmux-sessions.ts) — Creates the tmux session with leader pane + N worker panes. Handles pane layout, window naming, and mouse support.
Worker Bootstrap (worker-bootstrap.ts) — Injects environment variables, AGENTS.md context, and initial task into each worker pane via omx-mux.
Scaling (scaling.ts) — Adds or removes worker panes at runtime without tearing down the session.
Phases (phases.ts) — State machine for team lifecycle: planning → executing → verifying → complete. Phase transitions write to .omx/state/mode/.
Delivery (delivery.ts) — Tracks task delivery confirmation per worker. Uses omx-mux delivery confirmation to ensure injection was received.
Runtime (runtime.ts) — Bridge between TypeScript team logic and the Rust runtime binary.
Mailbox — Workers communicate via MCP-based mailbox. Messages are persisted to the dispatch log in omx-runtime-core.
src/notifications/ — Notification System (18 files, ~180K chars)
Platforms:
discord-webhook.ts— Sends via incoming webhook (simplest, no bot required)discord-bot.ts— Full Discord bot with channel targeting and mention supporttelegram.ts— Telegram Bot APIslack.ts— Slack incoming webhook
Profiles (profiles.ts) — Named notification profiles (e.g., "ci", "quiet", "verbose") that bundle platform config, verbosity, and cooldown settings. Selected via OMX_NOTIFY_PROFILE.
Cooldowns (cooldowns.ts) — Enforces OMX_DISPATCH_COOLDOWN_SECONDS and OMX_IDLE_COOLDOWN_SECONDS. State persisted to .omx/state/dispatch/.
Formatters — Platform-specific message formatters. Discord uses markdown embeds; Telegram uses HTML; Slack uses Block Kit.
Reply Listener — Polls notification platform for incoming messages that match the reply prefix. Allowed senders restricted by OMX_REPLY_DISCORD_USER_IDS. See §7.3 for security considerations.
src/mcp/ — MCP Servers (8 files, ~97K chars)
All 5 servers share a common bootstrap pattern:
// Pseudo-code — actual implementation in src/mcp/
const server = new MCPServer({
parentWatchdog: { intervalMs: 25 },
siblingDetection: { timeoutMs: 5000 },
disableEnvVar: 'OMX_<NAME>_SERVER_DISABLE_AUTO_START',
});
server.start();
state server — Exposes MCP tools to read/write .omx/state/ JSON files. Used by all team components for shared state.
memory server — Persistent key-value memory across sessions. Backed by a JSON file in .omx/state/.
code_intel server — Code intelligence queries: symbol lookup, dependency graph, file search. Backed by tree-sitter or similar parser.
trace server — Execution tracing: records tool calls, timing, and results for replay and debugging.
wiki server — Project wiki with ingest (write), query (read), lint (validate), and storage with CJK support. Known issue: #1641 — titleToSlug strips non-ASCII characters, producing hash-based filenames for CJK titles instead of readable slugs.
src/hooks/ — Codex Hook Integration (8 files, ~95K chars)
Hooks fire on Codex lifecycle events:
| Event | OMX Handler |
|---|---|
SessionStart |
Initialize MCP servers, load agent overlay, build codebase map |
PreToolUse |
Route explore requests, detect keywords, inject prompt guidance |
PostToolUse |
Update state, trigger notifications |
UserPromptSubmit |
Detect task size, adjust agent strategy |
Stop |
Cleanup, persist session state, send completion notification |
Agents overlay (agents-overlay.ts) — Injects agent role context into Codex's system prompt at session start.
Codebase map (codebase-map.ts) — Builds a structural map of the codebase (directories, key files) for hook context.
Explore routing (explore-routing.ts) — Decides whether to route a tool call through omx-explore-harness (sandboxed) or allow it to run normally.
Keyword detection (keyword-detection.ts) — Scans prompts for configured keywords and triggers associated actions or notifications.
Task-size detection (task-size-detection.ts) — Classifies incoming tasks as small/medium/large and adjusts parallelism and strategy accordingly.
src/hooks/extensibility/ — Plugin System (9 files, ~27K chars)
Plugin architecture for extending the hook system without modifying core:
Dispatcher (dispatcher.ts) — Routes hook events to registered plugins in priority order.
Events (events.ts) — Typed event definitions for all hook lifecycle points.
Loader (loader.ts) — Discovers and loads plugin modules from configured directories.
Plugin Runner (plugin-runner.ts) — Executes plugin handlers with timeout and error isolation.
SDK (sdk.ts) — Public API for plugin authors. Exposes event subscription, state access, and notification dispatch.
To create a plugin: implement the SDK interface, export a plugin object, and place the module where the loader can discover it.
src/hud/ — Heads-Up Display (9 files, ~52K chars)
Authority (authority.ts) — Reads AuthorityLease from the runtime to display who currently holds authority.
Reconcile (reconcile.ts) — Diffs current rendered state vs. live state and computes minimal update set.
Render (render.ts) — Builds the HUD layout: authority banner, worker grid, phase progress bar, notification queue.
tmux integration (tmux.ts) — Writes HUD output to the leader pane via omx-mux input injection.
Colors (colors.ts) — ANSI color constants and theme definitions.
HUD renders on a tick interval; the interval pauses when the leader pane is inactive.
src/autoresearch/ — Automated Experiment Loops (2 files, ~53K chars)
Mission contracts (missions.ts) — Defines experiment missions as typed contracts: hypothesis, evaluation criteria, max iterations, success threshold.
Sandbox parsing (sandbox.ts) — Parses experiment output from sandboxed Codex runs and extracts structured results.
Worktree management — Each experiment run uses an isolated Git worktree to prevent cross-contamination.
Evaluator scoring — Scores experiment outcomes against mission criteria. Persists scores for trend analysis.
Available experiment missions (in missions/):
adaptive-sort— Benchmark adaptive sorting algorithmsbayesopt— Bayesian optimization experiments
src/config/ — Config Generation (4 files, ~52K chars)
Codex hooks config generator — Produces the JSON/TOML config telling Codex which OMX hook handlers to call and when.
TOML config generator — Generates OMX's own TOML configuration file from environment variables and defaults.
MCP registry — Generates the MCP server registry config consumed by Codex at startup.
Model defaults — Defines default model selections for spark vs. frontier contexts.
src/adapt/ — Adapter Framework (6 files, ~47K chars)
Abstracts external tool integrations (currently OpenClaw and Hermes):
Contracts (contracts.ts) — TypeScript interfaces for the adapter API: probe(), status(), init(), envelope(), doctor().
Probe — Tests whether the external tool is available and responsive.
Status — Returns current tool status (healthy/degraded/unavailable).
Init — Initializes the tool integration (auth, config load).
Envelope — Wraps an outgoing message in the tool's required format.
Doctor — Runs diagnostics and returns actionable remediation steps.
src/state/ — Mode State Management (6 files, ~41K chars)
Operations (operations.ts) — CRUD operations for state files: read, write, delete, list. All writes are atomic (temp file + rename).
Paths (paths.ts) — Canonical path resolver for all state locations. Single source of truth for .omx/state/ structure.
Skill-active (skill-active.ts) — Tracks which skill is currently executing; prevents conflicting concurrent executions.
Workflow transitions (transitions.ts) — Validates state machine transitions. Illegal transitions (e.g., jumping from planning to complete without executing) are rejected.
File-based locking — Lock files in .omx/state/ prevent concurrent writes. See §7.8 for stale-lock risk.
src/pipeline/ — Pipeline Orchestrator (3 files, ~15K chars)
Three-stage pipeline:
RALPLAN → Team Execution → Ralph Verification
Stage 1 — RALPLAN. Planner agent produces a structured plan: tasks, assignments, acceptance criteria.
Stage 2 — Team Execution. Leader dispatches tasks to workers per plan. Workers execute in parallel worktrees.
Stage 3 — Ralph Verification. Ralph agent verifies outputs against acceptance criteria. Loops with fix attempts if criteria not met.
The pipeline writes stage outputs to .omx/state/ for cross-stage continuity.
src/ralph/ — Verification Loop (2 files, ~14K chars)
Ralph is the verification agent. Its phase contract:
starting → executing → verifying → fixing → complete
↘ failed
↘ cancelled
Ralph reads the acceptance criteria from the RALPLAN output, inspects worker outputs, and issues a PASS or FAIL verdict with structured feedback.
On FAIL, Ralph enters fixing phase: it synthesizes a remediation prompt and hands back to the execution layer for one more attempt. The cycle repeats up to a configured maximum.
Note
GitHub issue #1653 documents
withRalphSteerLockentering infinite retry if the lock is never acquired. Until fixed, set a maximum wall-clock timeout externally (e.g.,timeout 300 omx run ...).
src/openclaw/ — OpenClaw Integration (4 files, ~35K chars)
OpenClaw is an external automation gateway. OMX supports two gateway types:
HTTP gateway — POSTs structured requests to an HTTP endpoint. Configured via OMX_OPENCLAW_COMMAND_TIMEOUT_MS.
Command gateway — Executes a local command (OMX_OPENCLAW_COMMAND) with the request as stdin. Used for local OpenClaw installations.
Hook event mapping (event-mapping.ts) — Maps Codex hook events to OpenClaw event types.
Dispatcher (dispatcher.ts) — Routes events to the configured gateway; handles timeouts and retry.
src/utils/ — Shared Utilities (9 files, ~33K chars)
| File | Purpose |
|---|---|
agents-md.ts |
Parse and manipulate AGENTS.md files |
model-tables.ts |
Model name to capability/cost tables |
git-layout.ts |
Git worktree and branch helpers |
paths.ts |
Cross-platform path resolution |
platform-commands.ts |
OS-specific command wrappers (Windows vs. POSIX) |
repo-deps.ts |
Repository dependency graph analysis |
safe-json.ts |
JSON parse/stringify with error containment |
sleep.ts |
Promise-based sleep with cancellation |
index.ts |
Re-exports |
8.3 Rust Crate Reference
omx-runtime-core — Core Runtime Engine
The foundational crate. All higher-level runtime logic depends on it.
AuthorityLease — Cooperative lock granting one process authority over a session. Backed by a lease file in .omx/state/. Lease is time-limited; holder must renew periodically.
RuntimeEngine — Main event loop. Accepts events, dispatches to handlers, writes to DispatchLog.
DispatchLog — Append-only event log. Enables crash recovery by replaying events on restart. Entries are newline-delimited JSON.
MailboxLog — Per-worker message inbox. Each worker has a dedicated log file. Leader writes; worker reads and acknowledges.
ReplayState — Reconstructs in-memory state from DispatchLog on startup.
RateLimiter — Token-bucket rate limiter used for notification dispatch throttling.
omx-runtime-core/
├── src/
│ ├── authority.rs AuthorityLease
│ ├── dispatch_log.rs DispatchLog
│ ├── engine.rs RuntimeEngine
│ ├── mailbox.rs MailboxLog
│ ├── rate_limit.rs RateLimiter
│ ├── replay.rs ReplayState
│ └── lib.rs
└── Cargo.toml
omx-mux — tmux Multiplexer Abstractions
TmuxAdapter — Primary interface. Wraps the tmux binary with typed methods:
capture_pane(pane_id)returnsString— Captures current pane contentsend_keys(pane_id, keys)— Injects keystrokesconfirm_delivery(pane_id, sentinel)returnsbool— Waits for sentinel string to appear in pane output
InputEnvelope — Typed wrapper for an input injection operation, including pane target, content, and delivery confirmation parameters.
CommandOutput — Structured output from tmux command execution: exit code, stdout, stderr.
Operation types: capture, send, confirm, resize, split, kill.
omx-mux/
├── src/
│ ├── adapter.rs TmuxAdapter
│ ├── envelope.rs InputEnvelope
│ ├── output.rs CommandOutput
│ ├── operations.rs Operation enum
│ └── lib.rs
└── Cargo.toml
omx-runtime — Runtime Binary Wrapper
Thin binary crate that wraps omx-runtime-core and omx-mux into a standalone executable. Started as a child process by src/runtime/ (the TypeScript bridge). Communicates with the parent via stdin/stdout JSON protocol.
omx-runtime/
├── src/
│ └── main.rs
└── Cargo.toml (depends on omx-mux, omx-runtime-core)
omx-sparkshell — Shell Command Execution with AI Summary
Standalone binary. Called by OMX hooks to run a shell command and produce an AI-generated summary of the output.
Language-aware prompt construction — Detects the language context from file extensions or explicit hint; selects appropriate prompt template (e.g., Rust compilation errors vs. Python test output).
Line-count thresholding — Checks output line count against OMX_SPARKSHELL_LINES. Selects spark vs. frontier model accordingly.
Summary timeout — Enforced by OMX_SPARKSHELL_SUMMARY_TIMEOUT_MS. If the AI call times out, raw output is returned unchanged.
omx-sparkshell/
├── src/
│ ├── main.rs
│ ├── prompt.rs Language-aware prompt builder
│ ├── model.rs Model selection logic
│ └── summarize.rs AI call + timeout handling
└── Cargo.toml
omx-explore-harness — Sandboxed Exploration Binary
POSIX-only. Wraps Codex CLI with a restricted PATH allowlist, preventing the subprocess from accessing host tools not in the approved list.
The harness:
- Parses the allowlist (hardcoded in source)
- Constructs a sanitized
PATHcontaining only allowed tool directories execs Codex with the sanitized environment
No network sandboxing is performed — only PATH restriction.
omx-explore-harness/
├── src/
│ ├── main.rs
│ └── allowlist.rs PATH allowlist definition
└── Cargo.toml
8.4 Pipeline Architecture Deep Dive
User: omx run --skill my-analysis
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Stage 1: RALPLAN │
│ src/ralplan/ + src/planning/ │
│ │
│ Planner agent reads task description + codebase map │
│ Produces structured plan JSON: │
│ { tasks: [...], assignments: [...], criteria: [...] } │
│ Written to .omx/state/mode/ralplan.json │
└────────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Stage 2: Team Execution │
│ src/team/ + omx-runtime + omx-mux │
│ │
│ Leader creates tmux session │
│ Leader spawns N worker panes │
│ Workers bootstrap with roles + task assignments │
│ Workers execute in isolated Git worktrees │
│ Mailbox system routes inter-worker messages │
│ Phase controller tracks progress │
│ Results written to .omx/state/jobs/<job-id>.json │
└────────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Stage 3: Ralph Verification │
│ src/ralph/ │
│ │
│ Ralph reads criteria from RALPLAN output │
│ Inspects worker outputs │
│ Issues PASS / FAIL verdict │
│ On FAIL: synthesize fix prompt, back to Stage 2 │
│ On PASS: write final result, notify │
└─────────────────────────────────────────────────────────────┘
8.5 Code Patterns & Conventions
State writes are always atomic. Pattern throughout src/state/:
// Write temp, then rename (never corrupt on crash)
await fs.writeFile(tmpPath, JSON.stringify(state), 'utf8');
await fs.rename(tmpPath, finalPath);
Safe JSON everywhere. src/utils/safe-json.ts wraps JSON.parse to return null on error rather than throwing, preventing cascade failures from corrupt state files.
Environment variable resolution with fallback chain. Session ID example:
const sessionId =
process.env.OMX_SESSION_ID ??
process.env.CODEX_SESSION_ID ??
process.env.SESSION_ID;
Platform command abstraction. src/utils/platform-commands.ts provides getPlatformCommand(name) that returns the OS-appropriate command string. Used for shell invocations and tool discovery.
Rust AuthorityLease pattern — Cooperative, not kernel-enforced. All runtime components must respect the lease and not modify shared state while another holder is active.
8.6 Testing Strategy
TypeScript Tests
# Run all tests
node --test
# Run with coverage
npx c8 node --test
# Run specific file
node --test src/team/allocation.test.ts
Tests use Node.js built-in assert module. Mocking is done with manual stubs (no heavy framework).
Coverage thresholds enforced via c8 config:
{
"lines": 78,
"functions": 90,
"branches": 70,
"statements": 78
}
Rust Tests
# All crates
cargo test
# Specific crate
cargo test -p omx-runtime-core
cargo test -p omx-mux
# With output
cargo test -- --nocapture
TypeScript / Rust Compat Tests
cargo test -p omx-runtime # includes compat suite
Compat tests verify that the TypeScript bridge and the Rust runtime binary communicate correctly. They serialize test messages from TypeScript, pass through the binary, and assert round-trip fidelity.
8.7 Contributing
Branching: Single main branch development. Feature branches for non-trivial changes.
Commit style: Conventional commits preferred (feat:, fix:, chore:, docs:).
Before submitting:
# TypeScript
npm run build
node --test
npx c8 node --test # verify coverage thresholds
# Rust
cargo fmt --check
cargo clippy -- -D warnings
cargo test
New skills: Create skills/my-skill/SKILL.md, register in templates/catalog-manifest.json, add prompt in prompts/.
New MCP server: Follow the bootstrap pattern in src/mcp/; add disable env var OMX_<NAME>_SERVER_DISABLE_AUTO_START; add parent watchdog and sibling detection.
New notification platform: Implement the notifier interface (probe, send, format methods), add env vars to config_keys.tsv, add formatter.
9. Integration Points
9.1 MCP Server Integration
OMX exposes its internal state via 5 MCP servers on the stdio transport. External tools (including Codex agents) can connect as MCP clients.
Server discovery: Codex is configured via the generated MCP registry (see src/config/) to connect to all 5 servers on session start.
State server tools:
read_state(path)— Read a state file by relative path under.omx/state/write_state(path, content)— Atomic write to a state filelist_state(prefix)— List state files matching prefix
Memory server tools:
remember(key, value)— Store a key-value pairrecall(key)— Retrieve by keyforget(key)— Delete a key
Wiki server tools:
ingest(title, content)— Write a wiki pagequery(query)— Full-text searchlint(title)— Validate page structure
Note
CJK wiki titles produce hash-based filenames due to issue #1641. Until patched, use ASCII slug titles for pages that must have human-readable filenames.
9.2 OpenClaw Integration
OpenClaw is an external automation gateway. OMX supports two connection modes:
# HTTP gateway
export OMX_OPENCLAW=true
export OMX_OPENCLAW_COMMAND_TIMEOUT_MS=5000
# OpenClaw server must be running at configured endpoint
# Command gateway
export OMX_OPENCLAW=true
export OMX_OPENCLAW_COMMAND=/usr/local/bin/openclaw-cli
The adapter framework (src/adapt/) provides the doctor command to diagnose connectivity:
omx adapt doctor openclaw
9.3 Notification Platform Integration
Discord (Webhook — simplest)
export OMX_DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
export OMX_DISCORD_MENTION="<@!123456789>" # optional user ping
omx team start
Discord (Bot — full features)
export OMX_DISCORD_NOTIFIER_BOT_TOKEN="Bot ..."
export OMX_DISCORD_NOTIFIER_CHANNEL="987654321"
export OMX_DISCORD_MENTION="<@&112233445>" # role ping
Telegram
export OMX_TELEGRAM_BOT_TOKEN="123456:ABC..."
export OMX_TELEGRAM_CHAT_ID="-100123456789"
Slack
export OMX_SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."
export OMX_SLACK_MENTION="<!channel>"
Reply Listener
export OMX_REPLY_ENABLED=true
export OMX_REPLY_DISCORD_USER_IDS="111222333,444555666"
export OMX_REPLY_POLL_INTERVAL_MS=5000
export OMX_REPLY_RATE_LIMIT=10
Caution
The reply listener has a known sensitive data leak (issue #1661). Enable only in private channels with trusted users.
9.4 Hook System Extension
To add a custom hook handler via the plugin system:
// my-plugin.ts
import { OMXPlugin, HookEvent } from 'oh-my-codex/sdk';
export const plugin: OMXPlugin = {
name: 'my-plugin',
version: '1.0.0',
hooks: {
[HookEvent.PreToolUse]: async (ctx) => {
// Inspect or modify ctx.toolCall
return ctx;
},
[HookEvent.Stop]: async (ctx) => {
// Cleanup
},
},
};
Place the plugin where the loader discovers it (configured via OMX_HOOK_CONFIG).
9.5 Codex CLI Integration
OMX requires Codex CLI to be installed and configured. It integrates via:
- Config generation —
omx configwrites the Codex hooks config pointing to OMX handlers - Process spawning — Leader spawns
codexprocesses in worker panes via tmux - Hook firing — Codex calls OMX hook handlers via configured endpoints on lifecycle events
- Explore harness —
omx-explore-harnesswrapscodexfor sandboxed exploration
To initialize OMX for a project:
cd /path/to/project
omx config init # generate AGENTS.md, hooks config, MCP registry
omx team start --workers 3
9.6 Adapt Framework — Adding New Adapters
Implement the adapter contract in src/adapt/:
// src/adapt/my-tool/index.ts
import { AdapterContract } from '../contracts';
export const myToolAdapter: AdapterContract = {
probe: async () => { /* check availability */ },
status: async () => { /* return health */ },
init: async (config) => { /* initialize */ },
envelope: (message) => { /* format message */ },
doctor: async () => { /* run diagnostics */ },
};
Register in the adapter registry and add environment variables to config_keys.tsv.
9.7 Known Issues Summary Table
| Issue | Area | Severity | Workaround |
|---|---|---|---|
| #1643 | macOS TTY (omx exits immediately) | High | Run in foreground; avoid backgrounding Codex |
| #1671 | omx update overwrites AGENTS.md |
High | Backup AGENTS.md before updating |
| #1635 | Leader HUD stuck on MCP startup | Medium | Stop + restart team |
| #1665 | MCP duplicate sibling accumulation | Medium | Kill stray omx-mcp processes |
| #1657 | SIGTERM without PID verification | Medium | Run in isolated process namespace |
| #1677 | Stream error / connection recovery | Medium | Restart affected worker pane |
| #1661 | Reply listener leaks sensitive data | High | Disable OMX_REPLY_ENABLED |
| #1660 | Transitive dep vulnerabilities | Medium | npm audit fix + cargo audit |
| #1653 | withRalphSteerLock infinite retry | Medium | External timeout on omx invocations |
| #1654 | stateDirToProjectRoot hardcoded depth | Low | Keep .omx/ at repo root |
| #1656 | Leader git polling blocks event loop | Low | Reduce polling frequency (no config yet) |
| #1655 | withTmuxExtendedKeysLeaseLock no stale recovery | Medium | Delete stale lock files manually |
| #1642 | Detached leader skips tmux kill-session | Low | Kill orphan sessions manually |
| #1641 | wiki titleToSlug strips non-ASCII | Low | Use ASCII slug titles for CJK pages |
| #1648 | Built-in skills not namespaced with omx: | Low | No impact until namespacing enforced |
| #1640 | buildWorkerStartupCommand shell injection | High | Never pass untrusted LAUNCH_ARGS |
| #1649 | Path traversal via identifiers | High | Validate all identifiers before passing |
| #1659 | hud/state.ts git injection via remoteName | Medium | Ensure trusted .git/config only |