# Codex Remote Auth

> 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.

- Skill: `tankygranny05/codex-remote-auth` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tankygranny05/codex-remote-auth`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tankygranny05/codex-remote-auth/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: tankygranny05 (https://skillmd.com/u/tankygranny05)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/tankygranny05/codex-remote-auth

---

<!-- [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:

| CLI | Auth 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

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

| 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)

