본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 15. 17:29

Agent Poke: AI CLI 사용을 위한 윈도우(Window) 관리

요약

agent-poke는 AI CLI(Command Line Interface) 사용량을 관리하기 위해 개발된 헬퍼 도구입니다. 이 도구는 복잡한 상태 추적이나 웹 UI 없이, 정해진 시간에 에이전트들에게 작은 메시지를 보내어 구독 기반의 AI 서비스 사용량 측정 문제를 해결합니다. Docker Compose를 사용하여 서버 환경에서 안정적으로 실행되며, 기존 CLI의 인증 흐름을 유지하면서 예약된 체크인(check-in) 작업을 수행하는 것이 특징입니다.

핵심 포인트

  • AI CLI 사용량을 롤링 타임 윈도우 방식으로 관리하여 구독 서비스 이용 타이밍 문제를 해결합니다.
  • 복잡한 상태 관리 대신, 정적 스케줄러를 사용하여 지정된 시간에 에이전트들에게 작은 메시지를 보내는 단순한 접근 방식을 채택했습니다.
  • Docker Compose 환경에서 배포되어 서버 안정성을 확보하며, 데이터베이스나 웹 UI 같은 복잡한 구성 요소를 배제했습니다.
  • 사용자가 공식 CLI 흐름을 통해 수동으로 로그인하도록 하여 인증 정보가 이미지에 포함되는 것을 방지하고 보안을 유지합니다.

저는 하루 동안 Codex CLI와 Claude Code를 많이 사용합니다. API를 통해서도 아니고, 커스텀 통합을 통해서도 아닙니다. 대부분 제가 작업 중인 프로젝트 내부에서 구독 계정으로 로그인하여 실행하는 일반적인 로컬 CLI를 사용합니다. 그 워크플로우는 충분히 간단하지만, 계속 머릿속을 맴도는 작은 문제가 하나 있었습니다. 이러한 도구 중 일부는 롤링 타임 윈도우(rolling time windows) 방식으로 사용량을 측정합니다. 실제로 첫 번째 메시지가 윈도우를 시작합니다. 만약 제가 하루 중 나중에야 도구를 여는 것을 기억한다면, 여전히 동일한 구독을 가지고 있더라도 타이밍이 기대만큼 유용하지 않을 수 있습니다. 그래서 저를 위한 작은 헬퍼(helper)를 만들었습니다: agent-poke. 리포지토리: github.com/semiherdogan/agent-poke. 이 도구는 똑똑해지려고 노력하지 않습니다. 그저 정해진 시간에 에이전트(agent)들에게 작은 메시지를 보낼 뿐입니다. 네! 그것이 전체 아이디어입니다.

해결하고 싶었던 문제
Claude는 업무 시간인 대략 09:00에서 19:00 사이에 저에게 가장 유용합니다. Codex는 거의 항상 유용합니다. 처음에는 스케줄러(scheduler)를 동적으로 만들 생각을 했습니다. 마지막 실행을 추적하고, 다음 허용 시간을 계산하며, 에이전트별 윈도우를 처리하고, 자체 상태를 유지할 수도 있었을 것입니다. 하지만 이 문제를 해결하기에는 너무 과했습니다. 제가 실제로 필요했던 것은 하루 일정과 충분히 잘 맞아떨어지는 정적 스케줄(static schedule)이었습니다. 현재 스케줄은 다음과 같습니다:

0 6 * * * /app/scripts/run-checkin.sh
6 11 * * * /app/scripts/run-checkin.sh
12 16 * * * /app/scripts/run-checkin.sh
18 21 * * * /app/scripts/run-checkin.sh

쉬운 영어로 설명하자면:
06:00는 업무 시간 전 첫 번째 윈도우를 시작합니다.
11:06은 5시간 6분 뒤입니다.
16:12는 업무 종료 시점까지 윈도우를 이어갑니다.
21:18은 약간의 버퍼(buffer)를 두어 저녁 윈도우를 엽니다.

추가된 6분은 의도적인 것입니다. 경계선에 정확히 맞출 필요는 없습니다. 단지 너무 일찍 실행되는 것만 피하면 됩니다. 컨테이너 타임존(timezone)은 docker-compose.yml의 TZ를 통해 설정됩니다. 저의 경우 다음과 같습니다: TZ : Europe/Istanbul

왜 Docker인가
저는 이것이 제 노트북이 아닌 서버에서 실행되기를 원합니다. 그래서 Docker Compose가 가장 간단한 배포 대상이 되었습니다.

컨테이너에는 두 개의 CLI가 설치되어 있으며, 스케줄러(scheduler)와 작은 러너 스크립트(runner script)가 포함되어 있습니다. 구조는 의도적으로 단순하게 설계되었습니다: agent-poke/ Dockerfile docker-compose.yml config/ schedule.cron scripts/ login-codex.sh login-claude.sh run-checkin.sh logs/ workspace/ 데이터베이스는 없습니다. 웹 UI도 없습니다. 큐(queue)도 없습니다. 서비스 프레임워크도 없습니다. 그저 몇 개의 CLI 명령어를 감싸는 데 필요한 만큼의 컨테이너일 뿐입니다.

로그인은 여전히 수동입니다. 이 부분은 저에게 중요했습니다. 저는 인증 정보(credentials)를 이미지에 구워 넣거나(bake), 구독 로그인이 API 키와 동일한 것처럼 가장하고 싶지 않았습니다. 사용자는 공식 CLI 흐름을 사용하여 한 번 로그인합니다. Codex의 경우: docker compose run --rm agent-poke login-codex를 실행하면 codex login --device-auth가 실행됩니다. Claude의 경우: docker compose run --rm agent-poke login-claude를 실행하면 claude auth login --claudeai가 실행됩니다.

두 CLI 모두 컨테이너 사용자의 홈 디렉터리 아래에 로그인 상태를 저장합니다. 해당 디렉터리는 Docker 볼륨(volume)입니다:
volumes :

  • agent_home:/home/agent
    따라서 이미지를 다시 빌드할 수 있지만, 로그인 상태는 유지됩니다. 피해야 할 명령어는 하나입니다: docker compose down -v. 이 명령어는 볼륨을 제거하며, 저장된 로그인 정보도 함께 제거합니다.

대화형 체크인 (Interactive check-ins)
제 첫 번째 생각은 대화형 CLI를 완전히 피하는 것이었습니다. 예약된 작업(scheduled jobs)의 경우, 비대화형(non-interactive) 명령어가 보통 더 깔끔합니다: codex exec "Hey!" 또는 claude -p "Hey!". 하지만 이 특정 도구의 경우, 저는 그렇게 하지 않기로 결정했습니다. 목표는 일반적인 CLI 사용 방식처럼 동작하는 것입니다. 저는 Codex와 Claude가 서로 다른 경로를 사용하는 것을 원하지 않으며, Claude의 사용량 측정(metering) 방식이 변경되더라도 Claude가 실수로 별도의 프로그래밍 방식 사용 범주(programmatic usage bucket)로 분류되는 것을 원하지 않습니다. 따라서 최종 버전은 두 CLI를 동일한 방식으로 구동합니다:

  1. "Hey!"를 초기 프롬프트로 하여 대화형 CLI를 엽니다.
  2. 응답이 안정될 때까지 기다립니다.
  3. CLI를 종료합니다.

러너(runner)는 에이전트들을 병렬로 시작합니다. 이는 한쪽의 응답이 느리다는 이유만으로 Claude가 Codex보다 몇 분 뒤에 시작되는 상황을 방지하기 위해 중요합니다.

메시지를 초기 프롬프트 (initial prompt)로 전달하는 것은 취약한 타이밍 문제도 방지합니다. 즉, 스케줄러 (scheduler)가 타이핑을 하기 전에 TUI 입력창이 준비될 때까지 기다릴 필요가 없습니다. 이는 expect를 다시 사용할 수 있음을 의미합니다. 순수한 비대화형 (non-interactive) 명령보다는 약간 덜 우아하지만, 제가 실제로 도구를 사용하는 방식과 일치합니다. 한 가지 운영상의 결과가 있습니다: 로그인 후, 두 CLI 모두 워크스페이스 신뢰 프롬프트 (workspace trust prompt)를 묻고 기억할 수 있도록 한 번의 수동 확인을 실행합니다. docker compose run --rm agent-poke checkin. 그 이후의 예약된 실행들은 동일한 대화형 (interactive) 경로를 사용합니다. 러너 (runner)는 최근 로그만 유지합니다. 기본값은 LOG_KEEP : 20입니다. 이는 작은 도우미가 디스크를 천천히 가득 채우게 만들지 않으면서 최근 실행을 검사하기에 충분한 양입니다. TUI 도구들은 많은 이스케이프 시퀀스 (escape sequences)를 방출하기 때문에, 원시 터미널 출력 (Raw terminal output)은 기본적으로 비활성화되어 있습니다. 실제 화면 출력을 디버깅해야 하는 경우, RAW_AGENT_OUTPUT : 1로 다시 켤 수 있습니다. 일반 로그는 각 에이전트가 성공적으로 시작되고 완료되었는지만 기록합니다. 저는 Codex나 Claude의 작은 포맷 변경이 시스템을 취약하게 만들 수 있기 때문에 의도적으로 TUI 출력을 파싱 (parsing)하는 것을 피했습니다.

작은 배포 세부 사항
컨테이너는 루트가 아닌 사용자 (non-root user)로 실행됩니다. 이는 보통 올바른 기본값이지만, 호스트에 마운트된 logs/workspace/ 디렉토리가 해당 사용자에 의해 쓰기 가능해야 함을 의미합니다. 이 이미지에서 에이전트 사용자는 1001:1001이므로, 다음과 같은 설정이 필요합니다: mkdir -p logs workspacechown -R 1001:1001 logs workspace. 이것이 제가 겪은 유일한 실제 배포 문제를 해결했습니다. 이것이 없으면 체크인 (check-in) 스크립트가 시작될 수는 있지만, 로그 파일을 생성하려고 할 때 실패합니다.

이 도구에서 마음에 드는 점
이것은 주요 기능이 '많은 기능이 없다'는 점인 도구 중 하나입니다. 최종 버전은 다음과 같습니다:

  • 고정된 스케줄 (fixed schedule)
  • 수동 로그인 (manual login)
  • 지속적인 홈 볼륨 (persistent home volume)
  • 대화형 CLI 체크인 (interactive CLI check-ins)
  • 일반 로그 파일 (plain log files)
  • Docker Compose 배포 (Docker Compose deployment)
    지금은 이것으로 충분합니다. 나중에 에이전트별 스케줄링이나 더 스마트한 상태 관리가 필요해지면 그때 추가할 수 있습니다. 하지만 이 문제에 있어서는 정적인 버전이 더 신뢰하기 쉽습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0