Setup on macOS
March 24, 2026 ยท View on GitHub
Prerequisites
- Codex CLI installed and authenticated
- Node.js 20+
- Tailscale connected on Mac
- Xcode 15+
xcodegeninstalled to generateapps/ios/CodexRemote.xcodeprojfromapps/ios/project.yml
Install dependencies
npm install
npm run build
Run companion manually
npm run dev:companion
By default, the companion binds to your detected Tailscale IPv4 address.
If Tailscale is not available, it falls back to 127.0.0.1.
If you want to override that, set:
BIND_HOST=...
For closed-loop debugging:
npm run dev:debug
Run as LaunchAgent
cd apps/mac-companion
npm run install:launchagent
Logs are written to logs/mac-companion.out.log and logs/mac-companion.err.log.
Structured trace logs are written to logs/companion.ndjson.
Build and install the iPhone app
npm run ios:open
apps/ios/project.yml is the shared source of truth.
The generated apps/ios/CodexRemote.xcodeproj is local-only and ignored by Git so your personal signing and device setup stay out of the repo.
In Xcode:
- Select the
CodexRemotetarget. - Set your Apple signing team.
- Pick your iPhone as the run destination.
- Press
Play.
If you need to share iPhone project changes, edit apps/ios/project.yml and regenerate the project with npm run ios:generate.
The first dictation attempt will ask for:
- Microphone permission
Closed-loop verification
Start the companion in debug mode first:
npm run dev:debug
Run the end-to-end debug loop:
npm run debug:loop
The loop creates a real chat through the companion, sends a unique message, and verifies through a visible Mac desktop screenshot plus OCR that the Codex desktop app shows that message.
Run this from an active logged-in macOS desktop session. The verification step needs Screen Recording permission plus enough UI automation access to activate the Codex app window.
If the report says missing_display or error of type -10827, the shell that launched the loop does not have access to the visible desktop session. Re-run it from your normal logged-in Mac desktop.
Use only one active companion while you run the proof loop. If you launch a second companion against the same local Codex runtime, codex app-server initialize can time out before the desktop verification starts.
Artifacts are written to logs/e2e/.
What you can test on iPhone now
- Pair with the Mac companion
- Open an existing chat with loaded history
- Send a follow-up message
- Use the mic button for live dictation
- Open
Session - Inspect branch, diffs, changed files, and runtime settings
- Switch to an existing branch
- Commit already staged changes
- Change approval policy or sandbox mode
TLS (optional but recommended)
Set env variables before launch:
TLS_KEY_PATH=/path/to/key.pemTLS_CERT_PATH=/path/to/cert.pem
With these values configured, companion serves HTTPS/WSS.
Bind host defaults
- default: detected Tailscale IPv4
- fallback without Tailscale:
127.0.0.1 - manual override:
BIND_HOST=...
OpenAI dictation setup
Set these before you launch the companion if you want iPhone dictation to use OpenAI transcription:
OPENAI_API_KEY=...- optional
OPENAI_TRANSCRIPTION_MODEL=gpt-4o-transcribe - optional
OPENAI_BASE_URL=https://api.openai.com/v1
You can put them in .env, .env.local, or your shell environment. The companion reads .env and .env.local from the repo root automatically.