| name | codex-remote-auth |
| description | Deploy Codex CLI authentication to remote machines. Use when user asks about codex auth, codex authentication, codex oauth, codex remote, codex login remote, copy codex credentials, or deploy codex to server. |
Codex Remote Auth
Deploy Codex CLI authentication credentials to remote machines.
Quick Start
scp ~/.codex/auth.json remote:~/.codex/auth.json
ssh remote '~/symlinks/codex exec --skip-git-repo-check "Respond: auth working"'
With custom SSH port:
scp -P 22222 ~/.codex/auth.json user@host:~/.codex/auth.json
ssh -p 22222 user@host '~/symlinks/codex exec --skip-git-repo-check "test"'
Critical Knowledge (Lessons Learned)
⚠️ IMPORTANT: File is auth.json (No Leading Dot)
Unlike Claude Code's .credentials.json, Codex uses auth.json without a leading dot:
| CLI | Auth File |
|---|
| Claude Code | ~/.claude/.credentials.json (with dot) |
| Codex | ~/.codex/auth.json (no dot) |
⚠️ IMPORTANT: -p Flag is for Profile, NOT Prompt
codex -p "my prompt"
codex "my prompt"
codex exec "my prompt"
⚠️ IMPORTANT: Use exec for Non-Interactive Mode
For scripted/automated use, use the exec subcommand:
codex "prompt"
codex exec "prompt"
⚠️ IMPORTANT: --skip-git-repo-check for Non-Repo Directories
Codex requires being in a git repository by default. To run from any directory:
codex exec "test"
codex exec --skip-git-repo-check "test"
⚠️ IMPORTANT: Remote SSH May Need Shell Init
SSH non-interactive shells may not load PATH. Source profile if needed:
ssh remote 'source ~/.zshrc 2>/dev/null; ~/symlinks/codex exec --skip-git-repo-check "test"'
⚠️ IMPORTANT: Never Log/Print Auth Tokens
When agents handle auth files:
- NEVER read auth.json and print contents
- NEVER cat/echo auth files
- Use scp to copy directly without viewing
- Tokens in conversation logs = security risk
File Schema
~/.codex/auth.json
{
"OPENAI_API_KEY": null,
"tokens": {
"id_token": "string (JWT)",
"access_token": "string (JWT)",
"refresh_token": "string (JWT)",
"account_id": "string (UUID)"
},
"last_refresh": "ISO 8601 timestamp"
}
Notes:
OPENAI_API_KEY is null when using OAuth (Codex Cloud login)
- If using API key auth instead,
tokens may be absent and OPENAI_API_KEY populated
Remote Deployment Workflow
Simple Copy
scp ~/.codex/auth.json remote:~/.codex/auth.json
ssh remote 'codex exec --skip-git-repo-check "Respond: OK"'
With Custom SSH Port
scp -P 22222 ~/.codex/auth.json user@host:~/.codex/auth.json
ssh -p 22222 user@host 'codex exec --skip-git-repo-check "Respond: OK"'
Secure Copy Script
#!/bin/bash
REMOTE=${1:?Usage: $0 <remote_host> [ssh_port]}
PORT=${2:-22}
if [ ! -f ~/.codex/auth.json ]; then
echo "ERROR: ~/.codex/auth.json not found"
echo "Run 'codex login' first"
exit 1
fi
echo "Deploying Codex auth to $REMOTE:$PORT..."
scp -P "$PORT" ~/.codex/auth.json "$REMOTE":~/.codex/auth.json
echo "Testing..."
ssh -p "$PORT" "$REMOTE" 'codex exec --skip-git-repo-check "Respond: auth OK"' 2>&1 | tail -5
Smoke Test Strategy
Test 1: Local Auth Exists
ls -la ~/.codex/auth.json
python -c "
import json
with open('$HOME/.codex/auth.json') as f:
d = json.load(f)
assert 'tokens' in d or 'OPENAI_API_KEY' in d, 'Missing auth'
if d.get('tokens'):
assert 'access_token' in d['tokens'], 'Missing access_token'
print('✅ Auth structure valid')
"
Test 2: Local Codex Works
codex exec --skip-git-repo-check "Respond with exactly: local OK"
Test 3: Copy to Remote
scp -P 22222 ~/.codex/auth.json remote:~/.codex/auth.json
echo "Exit code: $?"
Test 4: Remote Auth File Exists
ssh -p 22222 remote 'ls -la ~/.codex/auth.json'
Test 5: Remote Codex Works
ssh -p 22222 remote 'codex exec --skip-git-repo-check "Respond: remote OK"' 2>&1 | tail -10
Test 6: Remote with Shell Init (if PATH issues)
ssh -p 22222 remote 'source ~/.zshrc 2>/dev/null; ~/symlinks/codex exec --skip-git-repo-check "test"'
Test 7: Timeout Behavior
timeout 45 ssh -p 22222 remote 'codex exec --skip-git-repo-check "Say: done"'
echo "Exit code: $?"
Comparison: Claude vs Codex Auth
| Aspect | Claude Code | Codex CLI |
|---|
| Auth file | ~/.claude/.credentials.json | ~/.codex/auth.json |
| Leading dot | Yes (.credentials.json) | No (auth.json) |
| Refresh needed | Yes (token dump + convert) | No (direct copy) |
| Non-interactive flag | -p "prompt" | exec "prompt" |
| Skip repo check | Not needed | --skip-git-repo-check |
| Complexity | High (2-step process) | Low (single file copy) |
Troubleshooting
"config profile 'X' not found"
Cause: Used -p flag which means profile in Codex.
Fix: Use positional argument or exec subcommand:
codex exec "your prompt"
"Not inside a trusted directory"
Cause: Codex requires git repo by default.
Fix: Add --skip-git-repo-check:
codex exec --skip-git-repo-check "prompt"
"command not found: codex"
Cause: Codex not in PATH for non-interactive SSH.
Fix: Source shell config or use full path:
ssh remote 'source ~/.zshrc; codex exec ...'
ssh remote '~/symlinks/codex exec ...'
Auth file missing on remote
Cause: scp failed or wrong path.
Fix: Verify and retry:
ssh remote 'mkdir -p ~/.codex'
scp ~/.codex/auth.json remote:~/.codex/auth.json
"Unauthorized" or auth errors
Cause: Token expired or corrupted during copy.
Fix:
- Refresh local auth:
codex login
- Re-copy to remote
Environment Variables
| Variable | Purpose |
|---|
CODEX_HOME | Override default ~/.codex directory |
OPENAI_API_KEY | Alternative to OAuth (if not using Codex login) |
Dependencies
- Codex CLI installed on both local and remote
- SSH access to remote machine
~/.codex/ directory on remote (created if missing)