Skip to content

Instantly share code, notes, and snippets.

@phyous
Last active July 23, 2026 00:14
Show Gist options
  • Select an option

  • Save phyous/7ba4406502af7b958a696094528c0d53 to your computer and use it in GitHub Desktop.

Select an option

Save phyous/7ba4406502af7b958a696094528c0d53 to your computer and use it in GitHub Desktop.
Codex CLI on GitHub Copilot — direct (no proxy), native web search, and the multi-account 401 fix
# Merge into ~/.codex/config.toml to route Codex through GitHub Copilot, DIRECT (no proxy).
# Requests go straight to api.githubcopilot.com, authenticated with `gh auth token`.
#
# TOML ordering: the scalar keys (model, model_provider, web_search, ...) must appear
# BEFORE any [table]. The [model_providers.*] tables can go anywhere after them.
model = "gpt-5.6-sol"
model_provider = "github-copilot-direct"
web_search = "live" # native hosted web search
# model_reasoning_effort = "xhigh" # optional: low | medium | high | xhigh
# model_catalog_json = "~/.codex/model-catalog.json" # optional: keeps GPT-5.6 on full Responses (web search)
# approvals_reviewer = "auto_review" # optional
[model_providers.github-copilot-direct]
name = "GitHub Copilot Direct"
base_url = "https://api.githubcopilot.com"
[model_providers.github-copilot-direct.auth]
# `command` runs on every request; its stdout is used as the bearer token.
# Use "gh" if it's on PATH, or an absolute path (e.g. "/opt/homebrew/bin/gh").
command = "gh"
# IMPORTANT: pin --hostname/--user so the token is deterministic across multiple gh
# accounts. Without --user, `gh auth token` returns whichever account is "active", which
# can flip and cause: 401 "input item does not belong to this connection".
args = ["auth", "token", "--hostname", "github.com", "--user", "YOUR_COPILOT_ACCOUNT"]
#!/usr/bin/env bash
# Configure the OpenAI Codex CLI to run on a GitHub Copilot subscription — DIRECT, no proxy.
# Codex talks straight to https://api.githubcopilot.com, authenticated with `gh auth token`.
# Idempotent: safe to re-run.
#
# Usage: ./setup.sh <copilot-github-username> [github-hostname]
set -euo pipefail
ACCOUNT="${1:-}"
HOST="${2:-github.com}"
CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
CONFIG="$CODEX_HOME/config.toml"
BASE_URL="https://api.githubcopilot.com"
die() { echo "ERROR: $*" >&2; exit 1; }
command -v codex >/dev/null 2>&1 || die "codex CLI not found. Install it first."
command -v gh >/dev/null 2>&1 || die "gh (GitHub CLI) not found. brew install gh"
command -v curl >/dev/null 2>&1 || die "curl not found."
GH_BIN="$(command -v gh)"
mkdir -p "$CODEX_HOME"
# 1. Which gh account holds your Copilot subscription?
if [ -z "$ACCOUNT" ]; then
echo "Accounts logged into $HOST:"
gh auth status --hostname "$HOST" 2>/dev/null \
| sed -n 's/.*account \([A-Za-z0-9_-]*\).*/ - \1/p' | sort -u
echo
die "Re-run with the Copilot account: $0 <github-username> [$HOST]"
fi
# 2. Verify the account's token reaches Copilot.
TOKEN="$("$GH_BIN" auth token --hostname "$HOST" --user "$ACCOUNT" 2>/dev/null)" \
|| die "No gh token for '$ACCOUNT' on $HOST. Run: gh auth login --hostname $HOST"
[ -n "$TOKEN" ] || die "Empty token for '$ACCOUNT'."
CODE="$(curl -s -m 15 -o /dev/null -w '%{http_code}' \
-H "Authorization: Bearer $TOKEN" \
-H "Copilot-Integration-Id: vscode-chat" \
-H "Editor-Version: Codex" \
"$BASE_URL/models" || echo 000)"
echo "Copilot /models check for '$ACCOUNT': HTTP $CODE"
[ "$CODE" = "200" ] || echo "WARNING: expected HTTP 200. Continuing — verify '$ACCOUNT' has Copilot."
# 3. Add the provider (pinned to the account) without corrupting existing TOML.
read -r -d '' AUTH_BLOCK <<EOF || true
# --- Codex on GitHub Copilot (DIRECT, no proxy) — added by setup.sh ---
[model_providers.github-copilot-direct]
name = "GitHub Copilot Direct"
base_url = "$BASE_URL"
[model_providers.github-copilot-direct.auth]
command = "$GH_BIN"
args = ["auth", "token", "--hostname", "$HOST", "--user", "$ACCOUNT"]
EOF
if [ ! -f "$CONFIG" ]; then
# Fresh config: scalar keys FIRST (TOML requires this), then the provider tables.
{
echo 'model = "gpt-5.6-sol"'
echo 'model_provider = "github-copilot-direct"'
echo 'web_search = "live"'
printf '%s\n' "$AUTH_BLOCK"
} > "$CONFIG"
echo "Wrote fresh $CONFIG"
elif grep -q '\[model_providers.github-copilot-direct\]' "$CONFIG"; then
echo "Provider already in $CONFIG — not modifying."
echo "(Confirm the pinned --user in that block is '$ACCOUNT'.)"
else
cp "$CONFIG" "$CONFIG.backup.$(date +%Y%m%d%H%M%S)"
printf '%s\n' "$AUTH_BLOCK" >> "$CONFIG" # tables are safe to append at the end
echo "Appended provider to $CONFIG (backup saved)."
if ! grep -q '^model_provider' "$CONFIG"; then
cat >&2 <<MSG
NOTE: add these TOP-LEVEL keys near the START of $CONFIG (before any [table]):
model = "gpt-5.6-sol"
model_provider = "github-copilot-direct"
web_search = "live"
MSG
fi
fi
# 4. Smoke test.
echo "Smoke test (codex exec):"
codex exec -m gpt-5.6-sol "reply with exactly: OK" 2>&1 | tail -3 || true
echo
echo "Done. Pinned to '$ACCOUNT' on $HOST — codex stays deterministic even if your active gh account changes."
name codex-github-copilot
description Configure the OpenAI Codex CLI to run inference on a GitHub Copilot subscription DIRECTLY (no proxy) — requests go straight to api.githubcopilot.com, authenticated with a pinned `gh auth token`. Includes native web search with GPT-5.6 Sol. Use when setting up Codex on Copilot credits/models, or fixing a 401 "input item does not belong to this connection".

Run Codex on GitHub Copilot inference (direct, no proxy)

Point the OpenAI Codex CLI at your GitHub Copilot subscription so it uses your Copilot credits/models — no OpenAI API key, and no local proxy. Codex talks straight to https://api.githubcopilot.com, authenticating with a GitHub CLI token supplied by a command-backed provider (gh auth token).

An earlier version of this gist used a local copilot-api proxy on localhost:4141. That still works, but the direct method below is simpler — no background daemon and no LaunchAgent to keep alive.

How it works

codex ──Responses API──▶ https://api.githubcopilot.com
        Authorization: Bearer $(gh auth token --user <copilot-account>)
  • Codex's [model_providers.*.auth] runs gh auth token on every request and uses the result as the bearer token — nothing is stored in the config file.
  • Your GitHub CLI (gh) must be logged into the account that holds the Copilot subscription.

Key constraint — which models are reachable

Codex 0.144+ only speaks the Responses API (wire_api = "chat" was removed). Copilot serves each model on exactly one API surface, so from Codex you can reach only the responses-capable models:

Reachable from Codex (responses) NOT reachable
all GPT-5.x: gpt-5.3-codex, gpt-5.4(/-mini), gpt-5.5, gpt-5.6-luna/sol/terra, gpt-5-mini; plus mai-code-1-flash-picker Gemini (Copilot serves it chat-only) and Claude (Anthropic /v1/messages only)

Check your live list:

curl -s -H "Authorization: Bearer $(gh auth token)" \
  https://api.githubcopilot.com/models | jq -r '.data[].id'

Prerequisites

  • macOS/Linux with the Codex CLI (codex --version) and GitHub CLI (gh --version).
  • An active GitHub Copilot subscription on a github.com account.
  • gh logged into that account: gh auth login --hostname github.com.

Setup

./setup.sh <your-copilot-github-username>

The script is idempotent. It verifies codex/gh, checks that the account's token reaches Copilot, writes the github-copilot-direct provider into ~/.codex/config.toml (pinned to that account — see below), and runs a smoke test. Prefer to do it by hand? Merge config-snippet.toml into ~/.codex/config.toml.

⚠️ Multi-account gotcha (the #1 cause of breakage)

gh auth token with no --user returns whichever account is currently active for that host. If you have more than one gh account (e.g. work + personal), the active one can flip — and then Codex authenticates as the wrong identity. Symptom:

401 Unauthorized: input item does not belong to this connection
  url: https://api.githubcopilot.com/responses

This is not a token/subscription failure (every valid GitHub token returns 200 on /models). It's the Responses API rejecting a previous_response_id that was created under a different connection — i.e. the account changed mid-session.

Fix: pin the provider's auth command to the exact account so it's deterministic no matter which account is "active" for git:

[model_providers.github-copilot-direct.auth]
command = "gh"
args = ["auth", "token", "--hostname", "github.com", "--user", "YOUR_COPILOT_ACCOUNT"]

Then start a fresh Codex session (don't resume the broken one) to drop the stale previous_response_id. List your accounts with gh auth status.

Web search

Codex's web_search is a hosted tool: the model asks Copilot's backend to run the search server-side — no MCP server and no separate search API key. Enable it with the top-level setting:

web_search = "live"

GPT-5.6 Sol ships as use_responses_lite = true in Codex's bundled catalog, and Responses Lite omits hosted tools — so Sol needs a catalog override that switches it to full Responses. Point model_catalog_json at a copy of Codex's catalog with gpt-5.6-sol -> use_responses_lite = false, and regenerate it after upgrading Codex.

Usage

codex                       # default model
codex -m gpt-5.5 ""        # any responses model, ad-hoc
codex --search ""          # ad-hoc live web search

Troubleshooting

  • 401 "input item does not belong to this connection" — multi-account token flip; pin --user (see above) and start a fresh session.
  • 401/403 on every requestgh isn't logged into a Copilot account, or the pinned --user is wrong. Check gh auth status; confirm with curl -s -o /dev/null -w '%{http_code}' -H "Authorization: Bearer $(gh auth token --user <acct>)" https://api.githubcopilot.com/models (want 200).
  • wire_api = "chat" is no longer supported — remove it; the direct provider needs no wire_api (Codex defaults to responses). Only responses-capable models work.
  • codex can't find gh — set command to the absolute path (which gh, e.g. /opt/homebrew/bin/gh); the auth command may run with a minimal PATH.
  • GPT-5.6 has no web_search tool — regenerate the catalog with Sol on full Responses and confirm web_search = "live", then start a new Codex process.

Caveats

Using your Copilot token from a non-editor client may be against your Copilot plan's terms, and heavy automated use can trip Copilot abuse-detection. Use at your own risk.

Teardown

Remove the [model_providers.github-copilot-direct] block plus the model* / web_search keys from ~/.codex/config.toml.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment