Skip to content

Instantly share code, notes, and snippets.

@sirmalloc
Last active May 30, 2026 14:29
Show Gist options
  • Select an option

  • Save sirmalloc/fefef0b65729d9644794a3c67d1a28b9 to your computer and use it in GitHub Desktop.

Select an option

Save sirmalloc/fefef0b65729d9644794a3c67d1a28b9 to your computer and use it in GitHub Desktop.
List / Delete Codex remote control environments

First make these executable:

chmod +x list-environments.zsh
chmod +x delete-environment.zsh

Next: run ./list-environments.zsh and you will get output like this:

  {
    "items": [
      {
        "env_id": "[redacted-env-id]",
        "kind": "single",
        "display_name": "[redacted-device-name]",
        "host_name": "[redacted-host-name]",
        "name": "[redacted-device-name]",
        "online": false,
        "busy": false,
        "os": "Mac OS",
        "os_version": "26.x",
        "arch": "arm64",
        "app_server_version": "0.131.x-alpha",
        "installation_id": "[redacted-installation-id]",
        "client_type": "CODEX_DESKTOP_APP",
        "originator": "Codex Desktop",
        "terminal": "unknown",
        "client_name": "codex-backend",
        "client_version": "unknown",
        "last_seen_at": "[redacted-timestamp]"
      },
      {
        "env_id": "[redacted-env-id]",
        "kind": "single",
        "display_name": "[redacted-device-name]",
        "host_name": "[redacted-host-name]",
        "name": "[redacted-device-name]",
        "online": false,
        "busy": false,
        "os": "Mac OS",
        "os_version": "26.x",
        "arch": "arm64",
        "app_server_version": "0.130.x",
        "installation_id": null,
        "client_type": "CODEX_CLI",
        "originator": "codex-backend",
        "terminal": "xterm-256color",
        "client_name": "codex-backend",
        "client_version": "unknown",
        "last_seen_at": "[redacted-timestamp]"
      }
    ],
    "cursor": null
  }

You can remove an environment using ./delete-environment.zsh '<env_id>', using the env_id from the first script. Sometimes this script hangs after running, but you can refresh the mobile app and the environment will be gone.

#!/usr/bin/env zsh
set -euo pipefail
if [[ $# -ne 1 ]]; then
print -u2 "usage: $0 <environment-id>"
exit 2
fi
ENVIRONMENT_ID="$1"
AUTH_JSON="${AUTH_JSON:-${CODEX_HOME:-$HOME/.codex}/auth.json}"
BASE="${CODEX_API_BASE_URL:-https://chatgpt.com/backend-api}"
if ! command -v node >/dev/null 2>&1; then
print -u2 "node is required to read the Codex auth token"
exit 1
fi
if [[ ! -r "$AUTH_JSON" ]]; then
print -u2 "cannot read auth file: $AUTH_JSON"
exit 1
fi
TOKEN="$(
AUTH_JSON="$AUTH_JSON" node -e '
const fs = require("fs");
const path = process.env.AUTH_JSON;
const auth = JSON.parse(fs.readFileSync(path, "utf8"));
const token = auth.tokens?.access_token ?? auth.access_token ?? auth.accessToken;
if (!token) {
console.error(`no access token found in ${path}`);
process.exit(1);
}
process.stdout.write(token);
'
)"
CHATGPT_ACCOUNT_ID="$(
TOKEN="$TOKEN" node -e '
function decodeBase64Url(value) {
value = value.replace(/-/g, "+").replace(/_/g, "/");
value += "=".repeat((4 - value.length % 4) % 4);
return Buffer.from(value, "base64").toString("utf8");
}
try {
const payload = JSON.parse(decodeBase64Url(process.env.TOKEN.split(".")[1]));
const accountId = payload["https://api.openai.com/auth"]?.chatgpt_account_id;
if (accountId) {
process.stdout.write(accountId);
}
} catch {
}
'
)"
USER_AGENT="${CODEX_DESKTOP_USER_AGENT:-Codex Desktop/${CODEX_DESKTOP_VERSION:-26.513.20950} (Macintosh; $(uname -m))}"
headers=(
-H "Authorization: Bearer $TOKEN"
-H "originator: Codex Desktop"
-H "User-Agent: $USER_AGENT"
-H "OAI-Language: en"
)
if [[ -n "$CHATGPT_ACCOUNT_ID" ]]; then
headers+=(-H "ChatGPT-Account-Id: $CHATGPT_ACCOUNT_ID")
fi
encoded_environment_id="$(ENVIRONMENT_ID="$ENVIRONMENT_ID" node -e 'process.stdout.write(encodeURIComponent(process.env.ENVIRONMENT_ID))')"
curl -i -sS -X DELETE "${headers[@]}" \
"$BASE/codex/remote/control/environments/$encoded_environment_id"
#!/usr/bin/env zsh
set -euo pipefail
AUTH_JSON="${AUTH_JSON:-${CODEX_HOME:-$HOME/.codex}/auth.json}"
BASE="${CODEX_API_BASE_URL:-https://chatgpt.com/backend-api}"
LIMIT="${LIMIT:-100}"
CURSOR="${1:-}"
if ! command -v node >/dev/null 2>&1; then
print -u2 "node is required to read the Codex auth token"
exit 1
fi
if [[ ! -r "$AUTH_JSON" ]]; then
print -u2 "cannot read auth file: $AUTH_JSON"
exit 1
fi
TOKEN="$(
AUTH_JSON="$AUTH_JSON" node -e '
const fs = require("fs");
const path = process.env.AUTH_JSON;
const auth = JSON.parse(fs.readFileSync(path, "utf8"));
const token = auth.tokens?.access_token ?? auth.access_token ?? auth.accessToken;
if (!token) {
console.error(`no access token found in ${path}`);
process.exit(1);
}
process.stdout.write(token);
'
)"
CHATGPT_ACCOUNT_ID="$(
TOKEN="$TOKEN" node -e '
function decodeBase64Url(value) {
value = value.replace(/-/g, "+").replace(/_/g, "/");
value += "=".repeat((4 - value.length % 4) % 4);
return Buffer.from(value, "base64").toString("utf8");
}
try {
const payload = JSON.parse(decodeBase64Url(process.env.TOKEN.split(".")[1]));
const accountId = payload["https://api.openai.com/auth"]?.chatgpt_account_id;
if (accountId) {
process.stdout.write(accountId);
}
} catch {
}
'
)"
USER_AGENT="${CODEX_DESKTOP_USER_AGENT:-Codex Desktop/${CODEX_DESKTOP_VERSION:-26.513.20950} (Macintosh; $(uname -m))}"
headers=(
-H "Authorization: Bearer $TOKEN"
-H "originator: Codex Desktop"
-H "User-Agent: $USER_AGENT"
-H "OAI-Language: en"
)
if [[ -n "$CHATGPT_ACCOUNT_ID" ]]; then
headers+=(-H "ChatGPT-Account-Id: $CHATGPT_ACCOUNT_ID")
fi
request_path="/codex/remote/control/environments?limit=$LIMIT"
if [[ -n "$CURSOR" ]]; then
encoded_cursor="$(CURSOR="$CURSOR" node -e 'process.stdout.write(encodeURIComponent(process.env.CURSOR))')"
request_path="$request_path&cursor=$encoded_cursor"
fi
response="$(curl -sS "${headers[@]}" "$BASE$request_path")"
if command -v jq >/dev/null 2>&1; then
print -r -- "$response" | jq .
else
print -r -- "$response"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment