AgentSkillsCN

codex-remote-auth

将 Codex CLI 认证部署至远程机器。适用于用户询问 Codex 认证、Codex 身份验证、Codex OAuth、Codex 远程、Codex 远程登录、复制 Codex 凭据,或部署 Codex 至服务器时使用。

SKILL.md
--- frontmatter
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.
<!-- [Created by Claude: 74b7884b-c678-4264-bf72-363a827187bc 2026-01-24] -->

Codex Remote Auth

Deploy Codex CLI authentication credentials to remote machines.

Quick Start

bash
# Copy auth to remote
scp ~/.codex/auth.json remote:~/.codex/auth.json

# Test on remote
ssh remote '~/symlinks/codex exec --skip-git-repo-check "Respond: auth working"'

With custom SSH port:

bash
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:

CLIAuth File
Claude Code~/.claude/.credentials.json (with dot)
Codex~/.codex/auth.json (no dot)

⚠️ IMPORTANT: -p Flag is for Profile, NOT Prompt

bash
# WRONG - -p means profile in Codex
codex -p "my prompt"  # Error: config profile 'my prompt' not found

# CORRECT - prompt is positional argument
codex "my prompt"
codex exec "my prompt"

⚠️ IMPORTANT: Use exec for Non-Interactive Mode

For scripted/automated use, use the exec subcommand:

bash
# Interactive (opens TUI)
codex "prompt"

# Non-interactive (for scripts/testing)
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:

bash
# Error without flag
codex exec "test"
# -> Not inside a trusted directory and --skip-git-repo-check was not specified

# Works with flag
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:

bash
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

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

bash
# 1. Copy auth file
scp ~/.codex/auth.json remote:~/.codex/auth.json

# 2. Test
ssh remote 'codex exec --skip-git-repo-check "Respond: OK"'

With Custom SSH Port

bash
# 1. Copy with custom port
scp -P 22222 ~/.codex/auth.json user@host:~/.codex/auth.json

# 2. Test with custom port
ssh -p 22222 user@host 'codex exec --skip-git-repo-check "Respond: OK"'

Secure Copy Script

bash
#!/bin/bash
# deploy_codex_auth.sh - Deploy Codex auth to remote
# Usage: ./deploy_codex_auth.sh <remote_host> [ssh_port]

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

bash
ls -la ~/.codex/auth.json
# Expected: File exists with reasonable size (500-2000 bytes)

# Verify structure without exposing tokens
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

bash
codex exec --skip-git-repo-check "Respond with exactly: local OK"
# Expected: "local OK" in output

Test 3: Copy to Remote

bash
scp -P 22222 ~/.codex/auth.json remote:~/.codex/auth.json
echo "Exit code: $?"
# Expected: Exit code 0

Test 4: Remote Auth File Exists

bash
ssh -p 22222 remote 'ls -la ~/.codex/auth.json'
# Expected: File exists with same size as local

Test 5: Remote Codex Works

bash
ssh -p 22222 remote 'codex exec --skip-git-repo-check "Respond: remote OK"' 2>&1 | tail -10
# Expected output includes:
# - "codex" followed by response
# - "Respond: remote OK" or similar

Test 6: Remote with Shell Init (if PATH issues)

bash
ssh -p 22222 remote 'source ~/.zshrc 2>/dev/null; ~/symlinks/codex exec --skip-git-repo-check "test"'
# Expected: Works even if codex not in default PATH

Test 7: Timeout Behavior

bash
# Test should complete within 45 seconds
timeout 45 ssh -p 22222 remote 'codex exec --skip-git-repo-check "Say: done"'
echo "Exit code: $?"
# Expected: Exit code 0 (not 124 which indicates timeout)

Comparison: Claude vs Codex Auth

AspectClaude CodeCodex CLI
Auth file~/.claude/.credentials.json~/.codex/auth.json
Leading dotYes (.credentials.json)No (auth.json)
Refresh neededYes (token dump + convert)No (direct copy)
Non-interactive flag-p "prompt"exec "prompt"
Skip repo checkNot needed--skip-git-repo-check
ComplexityHigh (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:

bash
codex exec "your prompt"

"Not inside a trusted directory"

Cause: Codex requires git repo by default.

Fix: Add --skip-git-repo-check:

bash
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:

bash
ssh remote 'source ~/.zshrc; codex exec ...'
# or
ssh remote '~/symlinks/codex exec ...'

Auth file missing on remote

Cause: scp failed or wrong path.

Fix: Verify and retry:

bash
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:

  1. Refresh local auth: codex login
  2. Re-copy to remote

Environment Variables

VariablePurpose
CODEX_HOMEOverride default ~/.codex directory
OPENAI_API_KEYAlternative 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)