Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186#!/usr/bin/env bash
set -euo pipefail
usage() { echo "Usage: $0 HOST [RSYNC_OPTION]..." >&2}
if [[ $# -lt 1 ]]; then usage exit 2fi
case "$1" in -h|--help) usage exit 0 ;;esac
remote_host="$1"shift
remote_path='~/code/codex-sync'local_exec_server_port="${CODEX_REMOTE_EXEC_SERVER_LOCAL_PORT:-8765}"remote_exec_server_start_timeout_seconds="${CODEX_REMOTE_EXEC_SERVER_START_TIMEOUT_SECONDS:-15}"
remote_exec_server_pid=''remote_exec_server_log_path=''remote_exec_server_pid_path=''remote_repo_root=''
cleanup() { local exit_code=$?
trap - EXIT INT TERM
if [[ -n "${remote_exec_server_pid_path}" ]]; then ssh "${remote_host}" \ "if [[ -f '${remote_exec_server_pid_path}' ]]; then kill \$(cat '${remote_exec_server_pid_path}') >/dev/null 2>&1 || true; fi; rm -f '${remote_exec_server_pid_path}' '${remote_exec_server_log_path}'" \ >/dev/null 2>&1 || true fi
exit "${exit_code}"}
trap cleanup EXIT INT TERM
if ! command -v git >/dev/null 2>&1; then echo "git is required" >&2 exit 1fi
if ! command -v ssh >/dev/null 2>&1; then echo "ssh is required" >&2 exit 1fi
if ! command -v rsync >/dev/null 2>&1; then echo "local rsync is required" >&2 exit 1fi
repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || { echo "run this script from inside a git repository" >&2 exit 1}
ssh "${remote_host}" "mkdir -p ${remote_path}"ssh "${remote_host}" -C "sudo apt-get install rsync libcap-dev"
sync_instance_id="$(date +%s)-$$"
rsync \ --archive \ --compress \ --human-readable \ --itemize-changes \ --exclude '.git/' \ --exclude 'codex-rs/target/' \ --filter=':- .gitignore' \ "$@" \ "${repo_root}/" \ "${remote_host}:${remote_path}/" \ >&2
remote_exec_server_log_path="/tmp/codex-exec-server-${sync_instance_id}.log"remote_exec_server_pid_path="/tmp/codex-exec-server-${sync_instance_id}.pid"
remote_start_output="$( ssh "${remote_host}" bash -s -- \ "${remote_exec_server_log_path}" \ "${remote_exec_server_pid_path}" \ "${remote_exec_server_start_timeout_seconds}" <<'EOF'set -euo pipefail
remote_exec_server_log_path="$1"remote_exec_server_pid_path="$2"remote_exec_server_start_timeout_seconds="$3"remote_repo_root="$HOME/code/codex-sync"remote_codex_rs="$remote_repo_root/codex-rs"
cd "${remote_codex_rs}"cargo build -p codex-cli --bin codex
rm -f "${remote_exec_server_log_path}" "${remote_exec_server_pid_path}"nohup ./target/debug/codex exec-server --listen ws://127.0.0.1:0 \ >"${remote_exec_server_log_path}" 2>&1 &remote_exec_server_pid="$!"echo "${remote_exec_server_pid}" >"${remote_exec_server_pid_path}"
deadline=$((SECONDS + remote_exec_server_start_timeout_seconds))while (( SECONDS < deadline )); do if [[ -s "${remote_exec_server_log_path}" ]]; then listen_url="$(head -n 1 "${remote_exec_server_log_path}" || true)" if [[ "${listen_url}" == ws://* ]]; then printf 'remote_exec_server_pid=%s\n' "${remote_exec_server_pid}" printf 'remote_exec_server_log_path=%s\n' "${remote_exec_server_log_path}" printf 'remote_repo_root=%s\n' "${remote_repo_root}" printf 'listen_url=%s\n' "${listen_url}" exit 0 fi fi
if ! kill -0 "${remote_exec_server_pid}" >/dev/null 2>&1; then cat "${remote_exec_server_log_path}" >&2 || true echo "remote exec server exited before reporting a listen URL" >&2 exit 1 fi
sleep 0.1done
cat "${remote_exec_server_log_path}" >&2 || trueecho "timed out waiting for remote exec server listen URL" >&2exit 1EOF)"
listen_url=''while IFS='=' read -r key value; do case "${key}" in remote_exec_server_pid) remote_exec_server_pid="${value}" ;; remote_exec_server_log_path) remote_exec_server_log_path="${value}" ;; remote_repo_root) remote_repo_root="${value}" ;; listen_url) listen_url="${value}" ;; esacdone <<< "${remote_start_output}"
if [[ -z "${remote_exec_server_pid}" || -z "${listen_url}" || -z "${remote_repo_root}" ]]; then echo "failed to parse remote exec server startup output" >&2 exit 1fi
remote_exec_server_port="${listen_url##*:}"if [[ -z "${remote_exec_server_port}" || "${remote_exec_server_port}" == "${listen_url}" ]]; then echo "failed to parse remote exec server port from ${listen_url}" >&2 exit 1fi
echo "Remote exec server: ${listen_url}"echo "Remote exec server log: ${remote_exec_server_log_path}"echo "Press Ctrl-C to stop the SSH tunnel and remote exec server."echo "Start codex via: "printf ' CODEX_EXEC_SERVER_URL=ws://127.0.0.1:%s codex -C %q\n' \ "${local_exec_server_port}" \ "${remote_repo_root}"
ssh \ -nNT \ -o ControlMaster=no \ -o ControlPath=none \ -o ExitOnForwardFailure=yes \ -o ServerAliveInterval=30 \ -o ServerAliveCountMax=3 \ -L "${local_exec_server_port}:127.0.0.1:${remote_exec_server_port}" \ "${remote_host}"