Skip to content

Instantly share code, notes, and snippets.

@lpenguin
Last active August 13, 2026 18:31
Show Gist options
  • Select an option

  • Save lpenguin/8372ed4fca659007a07a2184b20b1ef3 to your computer and use it in GitHub Desktop.

Select an option

Save lpenguin/8372ed4fca659007a07a2184b20b1ef3 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
set -Eeuo pipefail
# Prevent credentials and expanded commands from appearing in setup logs.
set +x
# =============================================================================
# Configuration
# =============================================================================
readonly AUTH_DIR="$HOME/.config/codex-cloud-auth"
readonly ENV_FILE="$AUTH_DIR/env.sh"
readonly GH_TOKEN_FILE="$AUTH_DIR/github-token"
readonly NOTION_TOKEN_FILE="$AUTH_DIR/notion-token"
readonly BIN_DIR="$HOME/.local/bin"
readonly PLAYWRIGHT_BROWSER_DIR="$HOME/.cache/ms-playwright"
# Override through an ordinary Cloud environment variable if needed.
readonly NOTION_CLI_VERSION="${NOTION_CLI_VERSION:-0.7.0}"
# =============================================================================
# Helpers
# =============================================================================
require_secret() {
local name="$1"
if [[ -z "${!name:-}" ]]; then
echo "ERROR: Cloud secret '$name' is missing or empty." >&2
exit 1
fi
}
append_line_once() {
local line="$1"
local file="$2"
touch "$file"
if ! grep -Fqx "$line" "$file"; then
printf '\n%s\n' "$line" >> "$file"
fi
}
# =============================================================================
# Credentials
#
# Codex Cloud Secrets are removed before the agent phase. The credentials are
# copied into protected files because gh and notion need live API access later.
# Use narrowly scoped, short-lived tokens.
# =============================================================================
require_secret CODEX_GITHUB_TOKEN
require_secret CODEX_NOTION_TOKEN
install -d -m 700 "$AUTH_DIR"
install -d -m 755 "$BIN_DIR"
install -d -m 755 "$PLAYWRIGHT_BROWSER_DIR"
install -m 600 /dev/null "$GH_TOKEN_FILE"
install -m 600 /dev/null "$NOTION_TOKEN_FILE"
printf '%s' "$CODEX_GITHUB_TOKEN" > "$GH_TOKEN_FILE"
printf '%s' "$CODEX_NOTION_TOKEN" > "$NOTION_TOKEN_FILE"
{
printf '%s\n' '# Generated by codex-cloud-tools-setup.sh'
printf '%s\n' 'export PATH="$HOME/.local/bin:$PATH"'
printf '%s\n' 'export GH_TOKEN="$(<"$HOME/.config/codex-cloud-auth/github-token")"'
printf '%s\n' 'export NOTION_TOKEN="$(<"$HOME/.config/codex-cloud-auth/notion-token")"'
printf '%s\n' 'export PLAYWRIGHT_BROWSERS_PATH="$HOME/.cache/ms-playwright"'
printf '%s\n' 'export PLAYWRIGHT_DOWNLOAD_CONNECTION_TIMEOUT="120000"'
} > "$ENV_FILE"
chmod 600 "$ENV_FILE"
readonly SOURCE_LINE='. "$HOME/.config/codex-cloud-auth/env.sh"'
append_line_once "$SOURCE_LINE" "$HOME/.bashrc"
append_line_once "$SOURCE_LINE" "$HOME/.profile"
# Make the configuration available to the rest of this setup run.
# shellcheck disable=SC1090
. "$ENV_FILE"
# Remove the original Cloud Secret variables from this process.
unset CODEX_GITHUB_TOKEN
unset CODEX_NOTION_TOKEN
# =============================================================================
# GitHub CLI
# =============================================================================
echo
echo "Configuring GitHub CLI..."
if ! command -v gh >/dev/null 2>&1; then
echo "ERROR: GitHub CLI (gh) is not installed in this Cloud image." >&2
exit 1
fi
echo "GitHub CLI: $(gh --version | head -n 1)"
gh auth status --hostname github.com
# Configure HTTPS git operations such as `git push` to retrieve credentials
# through gh, which in turn uses GH_TOKEN.
gh auth setup-git --hostname github.com
printf 'GitHub account: '
gh api user --jq '.login'
# =============================================================================
# 4ier/notion-cli
#
# Install the binary from GitHub Releases. The npm package's Node downloader
# may bypass the Codex Cloud HTTP proxy.
# =============================================================================
echo
echo "Configuring notion-cli..."
case "$NOTION_CLI_VERSION" in
v*)
readonly NOTION_TAG="$NOTION_CLI_VERSION"
;;
*)
readonly NOTION_TAG="v$NOTION_CLI_VERSION"
;;
esac
readonly NOTION_VERSION="${NOTION_TAG#v}"
case "$(uname -m)" in
x86_64|amd64)
readonly NOTION_ARCH="amd64"
;;
aarch64|arm64)
readonly NOTION_ARCH="arm64"
;;
*)
echo "ERROR: Unsupported architecture: $(uname -m)" >&2
exit 1
;;
esac
readonly NOTION_ASSET="notion-cli_${NOTION_VERSION}_linux_${NOTION_ARCH}.tar.gz"
notion_tmp_dir="$(mktemp -d)"
cleanup() {
if [[ -n "${notion_tmp_dir:-}" && -d "$notion_tmp_dir" ]]; then
rm -rf -- "$notion_tmp_dir"
fi
}
trap cleanup EXIT
echo "Downloading notion-cli $NOTION_TAG ($NOTION_ARCH)..."
gh release download "$NOTION_TAG" \
--repo 4ier/notion-cli \
--pattern "$NOTION_ASSET" \
--pattern "checksums.txt" \
--dir "$notion_tmp_dir"
expected_checksum="$(
awk -v asset="$NOTION_ASSET" \
'$2 == asset || $2 == "*" asset { print $1; exit }' \
"$notion_tmp_dir/checksums.txt"
)"
if [[ -z "$expected_checksum" ]]; then
echo "ERROR: No checksum found for $NOTION_ASSET." >&2
exit 1
fi
actual_checksum="$(
sha256sum "$notion_tmp_dir/$NOTION_ASSET" |
awk '{ print $1 }'
)"
if [[ "$actual_checksum" != "$expected_checksum" ]]; then
echo "ERROR: notion-cli checksum verification failed." >&2
echo "Expected: $expected_checksum" >&2
echo "Actual: $actual_checksum" >&2
exit 1
fi
tar -xzf "$notion_tmp_dir/$NOTION_ASSET" \
-C "$notion_tmp_dir"
if [[ ! -f "$notion_tmp_dir/notion" ]]; then
echo "ERROR: notion binary was not found in the release archive." >&2
exit 1
fi
install -m 0755 \
"$notion_tmp_dir/notion" \
"$BIN_DIR/notion"
echo "Notion CLI: $(notion --version 2>/dev/null || echo "$NOTION_TAG")"
notion auth status
notion user me >/dev/null
echo "Notion API authentication verified."
# =============================================================================
# Project dependencies
# =============================================================================
echo
echo "Installing project dependencies..."
if [[ -f pnpm-lock.yaml ]]; then
corepack enable
pnpm install --frozen-lockfile
elif [[ -f yarn.lock ]]; then
corepack enable
if yarn --version | grep -qE '^[23-9]\.'; then
yarn install --immutable
else
yarn install --frozen-lockfile
fi
elif [[ -f package-lock.json ]]; then
npm ci
elif [[ -f package.json ]]; then
echo "WARNING: package.json exists without a recognized lockfile."
echo "Running npm install."
npm install
else
echo "No Node.js project detected; skipping dependency installation."
fi
# =============================================================================
# Playwright Chromium
#
# Browser installation happens during setup, when Codex Cloud setup networking
# is available. The agent should not need to download Chromium later.
# =============================================================================
echo
echo "Configuring Playwright Chromium..."
PLAYWRIGHT_BIN=""
if [[ -x "$PWD/node_modules/.bin/playwright" ]]; then
PLAYWRIGHT_BIN="$PWD/node_modules/.bin/playwright"
elif command -v playwright >/dev/null 2>&1; then
PLAYWRIGHT_BIN="$(command -v playwright)"
fi
if [[ -n "$PLAYWRIGHT_BIN" ]]; then
echo "Playwright CLI: $PLAYWRIGHT_BIN"
echo "Browser directory: $PLAYWRIGHT_BROWSERS_PATH"
# --only-shell is sufficient for ordinary headless tests and screenshots
# and downloads less data than the full browser.
"$PLAYWRIGHT_BIN" install chromium --only-shell
echo
echo "Installed Playwright browsers:"
"$PLAYWRIGHT_BIN" install --list
else
echo "WARNING: Playwright is not installed in this repository."
echo "Add @playwright/test or playwright to devDependencies."
echo "Chromium installation was skipped."
fi
# =============================================================================
# Summary
# =============================================================================
echo
echo "============================================================"
echo "Codex Cloud tools configured successfully"
echo "============================================================"
echo
echo "GitHub:"
echo " gh auth status"
echo " gh issue list --repo OWNER/REPO"
echo
echo "Notion:"
echo " notion auth status"
echo " notion search \"query\""
echo
echo "Playwright:"
echo " ./node_modules/.bin/playwright install --list"
echo " npm test"
echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment