Codex App Server Persisted
[Created by Codex: 019b74f5-a7d5-7121-ac48-8e66cd2bdc92]
Purpose
Provide a repeatable workflow to keep a single Codex process running in memory via codex app-server, and drive multi-turn interactions by sending thread/start once and turn/start repeatedly on the same threadId.
When To Use
- Need a warm, long-lived Codex PID to minimize turn-to-turn latency
- Need programmatic control over turns (JSON-RPC over stdio) instead of a TUI
- Need built-in observability via
sse_lines.jsonl (works with app-server, not with mcp-server)
Workflow
1) Confirm requirements
- Identify whether the goal is: single-controller (one process drives Codex) or multi-client daemon/broker.
- Identify whether approvals must be supported or bypassed (risk/permissions).
- Identify desired observability target: centralized
~/centralized-logs/codex/sse_lines.jsonl or isolated --log-dir.
2) Start a long-lived app-server process
- Spawn
codex app-server as a subprocess with stdin=PIPE and keep stdin open for the lifetime of the controller.
- Read stdout line-by-line and parse each line as JSON (JSON-RPC-like).
- Treat stderr as inherited or actively drained to avoid deadlocks.
3) Create a thread once, then reuse it
- Send
initialize.
- Send
thread/start and store threadId.
- For each user prompt, send
turn/start with the same threadId.
4) Stream events and detect completion
- Expect notifications interleaved with responses on stdout.
- Print/collect assistant output using
codex/event/agent_message_content_delta.
- Consider a turn complete when either:
- notification method
codex/event/task_complete arrives, or
- notification method
turn/completed arrives.
5) Handle approvals if enabled
- Detect serverβclient JSON-RPC requests (messages that include both
method and id but no result).
- For V2 approval requests, handle at least:
item/commandExecution/requestApproval
item/fileChange/requestApproval
- Reply with a JSON-RPC response
{ "id": <same>, "result": { "decision": "accept" | "decline" } }.
6) Validate observability logging
- Prefer to run
codex with --log-dir when isolation is needed (creates sse_lines.jsonl under that directory).
- Otherwise, verify the centralized
~/centralized-logs/codex/sse_lines.jsonl changes while the app-server PID stays alive.
Bundled Resources
- Reference guide:
references/codex-app-server-persisted-process.md
- Starter script:
scripts/app_server_persisted_repl.py