Codex CLI 사용량 끝났을 때 한도가 리셋되면 자동으로 계속하게 하기

Codex 사용량이 Plus 사용자에겐 좀 모자랄 때가 있습니다. Claude Code는 사용량이 리셋되면 알아서 재개를 해주는데 Codex는 아직 그런 기능이 없습니다.

Codex CLI에서 간단한 bash 프로그램으로 시간에 맞춰서 작업을 계속하게 할 수 있습니다. codex 실행과 함께 프롬프트를 주입하는 인터페이스가 있기 때문이죠.

실행하면 아래처럼 됩니다. (하이라이트한 부분이 사용자가 입력하는 부분입니다.)

$ codex-wakeup.sh
Codex 세션 ID: 01axxxxx-xxxx-xxxx-9786-c1e16cf601d6
재개 시각 (HH:MM, 예: 04:13): 01:50
프롬프트 입력 (빈 줄로 완료, 아무것도 입력하지 않으면 '계속해'):
계속 진행하자


세션: 01axxxxx-xxxx-xxxx-9786-c1e16cf601d6
재개: 2026-10-06 01:50:38
프롬프트:
계속 진행하자
대기: 80분

Codex 자동 재개를 기다립니다. Ctrl+C로 취소할 수 있습니다.

“계속 진행하자” 하고 프롬프트를 입력한 다음에 두 줄이 띄어져 있는데, 빈 줄에서 엔터를 한번 쳐 줘야 프롬프트 입력이 완료된다는 점에 주의하세요. 여러줄 프롬프트를 입력하기 위한 방법입니다.

제 경우 1시 40분에 리셋되는 건데, 1시 50분에 작업을 재개하는 프롬프트를 입력하도록 하고 자려고 하는 거죠.

리셋 시간 1분 후로 예약하니까 사용량 리셋이 안 되는 경우가 있더라고요. 시간 간격을 10분 정도 넉넉하게 띄워주시는 게 좋습니다.

맥과 리눅스, 윈도우 버전 스크립트를 각각 첨부했습니다.

컴퓨터가 잠자기 모드로 들어가지 않도록 명령 안에 장치가 돼 있습니다.

코드는 ChatGPT 시켜서 짰습니다. 맥, WSL, 윈도우에서 테스트해서 성공했습니다.

윈도우용은 파일이 두 개입니다. codex-wakeup.cmd를 실행하시면 됩니다. codex-wakeup.ps1도 같은 폴더에 있어야 합니다. 이게 본체고, codex-wakeup.cmd는 권한을 우회하게 도와주는 껍데기 파일입니다.

아래는 코드입니다.

맥용

#!/bin/bash

# Codex 세션 자동 재개
# macOS용

read -r -p "Codex 세션 ID: " SESSION_ID

if [[ -z "$SESSION_ID" ]]; then
    echo "세션 ID가 없습니다."
    exit 1
fi

read -r -p "재개 시각 (HH:MM, 예: 04:13): " RESUME_TIME

if [[ ! "$RESUME_TIME" =~ ^([01][0-9]|2[0-3]):[0-5][0-9]$ ]]; then
    echo "시각 형식이 잘못됐습니다. HH:MM 형식으로 입력하세요."
    exit 1
fi

echo "프롬프트 입력 (빈 줄로 완료, 아무것도 입력하지 않으면 '계속해'):"

PROMPT=""
while IFS= read -r LINE; do
    [[ -z "$LINE" ]] && break

    if [[ -z "$PROMPT" ]]; then
        PROMPT="$LINE"
    else
        PROMPT="${PROMPT}"$'\n'"${LINE}"
    fi
done

PROMPT="${PROMPT:-계속해}"

TODAY=$(date "+%Y-%m-%d")
NOW=$(date "+%s")

TARGET=$(date -j -f "%Y-%m-%d %H:%M" \
    "$TODAY $RESUME_TIME" "+%s")

# 입력한 시간이 이미 지났으면 다음 날로 설정
if (( TARGET <= NOW )); then
    TOMORROW=$(date -j -v+1d "+%Y-%m-%d")
    TARGET=$(date -j -f "%Y-%m-%d %H:%M" \
        "$TOMORROW $RESUME_TIME" "+%s")
fi

WAIT=$(( TARGET - NOW ))

echo
echo "세션: $SESSION_ID"
echo "재개: $(date -r "$TARGET" "+%Y-%m-%d %H:%M:%S")"
echo "프롬프트:"
printf '%s\n' "$PROMPT"
echo "대기: $((WAIT / 60))분"
echo
echo "Codex 자동 재개를 기다립니다. Ctrl+C로 취소할 수 있습니다."

# 대기 중 macOS 시스템 sleep 방지
caffeinate -i sleep "$WAIT"

echo
echo "Codex를 비대화형으로 재개합니다."

codex exec resume "$SESSION_ID" "$PROMPT"
EXIT_CODE=$?

if (( EXIT_CODE != 0 )); then
    echo
    echo "codex exec resume 실패 (exit $EXIT_CODE)"
    exit "$EXIT_CODE"
fi

echo
echo "Codex TUI를 엽니다."

exec codex resume "$SESSION_ID"

리눅스용

#!/usr/bin/env bash

# Codex 세션 자동 재개
# Linux / WSL2 통합용

# Codex 세션은 현재 사용자의 HOME/인증/설정을 사용해야 하므로 root 실행 금지
if [[ $EUID -eq 0 ]]; then
    echo "이 스크립트는 sudo/root로 실행하면 안 됩니다."
    echo "현재 사용자로 다시 실행하세요."
    exit 1
fi

# 기다린 뒤에야 실패하지 않도록 Codex를 미리 확인
CODEX_BIN=$(command -v codex 2>/dev/null)
if [[ -z "$CODEX_BIN" ]]; then
    echo "codex 명령을 찾을 수 없습니다."
    echo "현재 사용자 환경에서 codex가 실행되는지 확인하세요."
    exit 1
fi

# WSL 감지
IS_WSL=false
if grep -qi microsoft /proc/sys/kernel/osrelease 2>/dev/null ||
   grep -qi microsoft /proc/version 2>/dev/null; then
    IS_WSL=true
fi

read -r -p "Codex 세션 ID: " SESSION_ID
if [[ -z "$SESSION_ID" ]]; then
    echo "세션 ID가 없습니다."
    exit 1
fi

read -r -p "재개 시각 (HH:MM, 예: 04:13): " RESUME_TIME
if [[ ! "$RESUME_TIME" =~ ^([01][0-9]|2[0-3]):[0-5][0-9]$ ]]; then
    echo "시각 형식이 잘못됐습니다. HH:MM 형식으로 입력하세요."
    exit 1
fi

echo "프롬프트 입력 (빈 줄로 완료, 아무것도 입력하지 않으면 '계속해'):"
PROMPT=""
while IFS= read -r LINE; do
    [[ -z "$LINE" ]] && break
    if [[ -z "$PROMPT" ]]; then
        PROMPT="$LINE"
    else
        PROMPT+=$'\n'"$LINE"
    fi
done
PROMPT="${PROMPT:-계속해}"

NOW=$(date +%s)
TARGET=$(date -d "$(date +%Y-%m-%d) $RESUME_TIME" +%s 2>/dev/null) || {
    echo "재개 시각을 계산하지 못했습니다."
    exit 1
}

# 입력한 시간이 이미 지났으면 다음 날
if (( TARGET <= NOW )); then
    TARGET=$(date -d "tomorrow $RESUME_TIME" +%s) || {
        echo "다음 날 재개 시각을 계산하지 못했습니다."
        exit 1
    }
fi

WAIT=$((TARGET - NOW))

echo
echo "세션: $SESSION_ID"
echo "재개: $(date -d "@$TARGET" "+%Y-%m-%d %H:%M:%S")"
echo "프롬프트:"
printf '%s\n' "$PROMPT"
echo "대기: $((WAIT / 60))분"
echo "Codex: $CODEX_BIN"

if $IS_WSL; then
    echo "환경: WSL — systemd 절전 방지는 생략합니다."
else
    echo "환경: Linux"
fi

echo
echo "Codex 자동 재개를 기다립니다. Ctrl+C로 취소할 수 있습니다."

run_codex() {
    sleep "$WAIT"
    echo
    echo "Codex를 재개합니다."
    exec "$CODEX_BIN" resume "$SESSION_ID" "$PROMPT"
}

# WSL에서는 Windows가 전원 관리를 담당하므로 systemd-inhibit를 사용하지 않는다.
if $IS_WSL; then
    run_codex
fi

# 일반 Linux에서는 inhibitor를 사용할 수 있으면 절전 방지.
# 먼저 짧은 명령으로 실제 권한까지 확인하고, 실패하면 본 작업은 계속한다.
if command -v systemd-inhibit >/dev/null 2>&1; then
    if systemd-inhibit --what=sleep --mode=block --why="Codex wakeup test" true >/dev/null 2>&1; then
        export WAIT SESSION_ID PROMPT CODEX_BIN
        exec systemd-inhibit \
            --what=sleep \
            --mode=block \
            --why="Waiting to resume Codex session" \
            bash -c '
                sleep "$WAIT"
                echo
                echo "Codex를 재개합니다."
                exec "$CODEX_BIN" resume "$SESSION_ID" "$PROMPT"
            '
    else
        echo
        echo "경고: systemd-inhibit 권한이 없어 절전 방지 없이 계속합니다."
    fi
else
    echo
    echo "경고: systemd-inhibit가 없어 절전 방지 없이 계속합니다."
fi

run_codex

윈도우용

codex-wakeup.cmd:

@echo off
setlocal
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0codex-wakeup.ps1"
set "EXITCODE=%ERRORLEVEL%"
endlocal & exit /b %EXITCODE%

codex-wakeup.ps1:

# Codex 세션 자동 재개
# Windows PowerShell용

$SessionId = Read-Host "Codex 세션 ID"
if ([string]::IsNullOrWhiteSpace($SessionId)) { Write-Host "세션 ID가 없습니다."; exit 1 }

$ResumeTime = Read-Host "재개 시각 (HH:mm, 예: 04:13)"
if ($ResumeTime -notmatch '^([01]\d|2[0-3]):[0-5]\d$') {
    Write-Host "시각 형식이 잘못됐습니다. HH:mm 형식으로 입력하세요."; exit 1
}

Write-Host "프롬프트 입력 (빈 줄로 완료, 아무것도 입력하지 않으면 '계속해'):"
$Lines = @()
while ($true) {
    $Line = Read-Host
    if ([string]::IsNullOrEmpty($Line)) { break }
    $Lines += $Line
}
$Prompt = if ($Lines.Count -eq 0) { "계속해" } else { $Lines -join "`n" }

$Hour, $Minute = $ResumeTime.Split(':')
$Now = Get-Date
$Target = Get-Date -Hour ([int]$Hour) -Minute ([int]$Minute) -Second 0
if ($Target -le $Now) { $Target = $Target.AddDays(1) }
$WaitSeconds = [math]::Ceiling(($Target - $Now).TotalSeconds)

Write-Host ""
Write-Host "세션: $SessionId"
Write-Host ("재개: {0:yyyy-MM-dd HH:mm:ss}" -f $Target)
Write-Host "프롬프트:"
Write-Host $Prompt
Write-Host ("대기: {0}분" -f [math]::Floor($WaitSeconds / 60))
Write-Host ""
Write-Host "Codex 자동 재개를 기다립니다. Ctrl+C로 취소할 수 있습니다."

Add-Type @"
using System;
using System.Runtime.InteropServices;
public static class SleepControl {
    [DllImport("kernel32.dll")]
    public static extern uint SetThreadExecutionState(uint esFlags);
}
"@

[uint32]$ES_CONTINUOUS = 2147483648
[uint32]$ES_SYSTEM_REQUIRED = 1
[uint32]$KEEP_AWAKE = $ES_CONTINUOUS -bor $ES_SYSTEM_REQUIRED

try {
    $Result = [SleepControl]::SetThreadExecutionState($KEEP_AWAKE)
    if ($Result -eq 0) { Write-Warning "자동 절전 방지 설정에 실패했습니다." }

    Start-Sleep -Seconds $WaitSeconds

    Write-Host ""
    Write-Host "Codex를 재개합니다."
    & codex resume $SessionId $Prompt
}
finally {
    [void][SleepControl]::SetThreadExecutionState($ES_CONTINUOUS)
}

카테고리

17년차 풀스택 웹 개발자 Mytory입니다

웹 개발에서도 중요한 것은 개념입니다.
이 블로그에는 제가 개발하며 익힌 개념들을 정리합니다.

워드프레스를 오래 다뤄 왔고 강의도 두 편 찍었습니다.
– 인프런 “워드프레스 제대로 개발하기 어드민 편, 클라이언트 편”
– 클래스101 “누구나 할 수 있는 워드프레스 홈페이지 만들기 – 기획부터 출시까지 한 방에 OK”

유튜브 채널에 워드프레스 관련 팁들을 올리고 있습니다.

👉 소개 더 보기

대표글

댓글 남기기