MyAI(마이아이)개발 · 제품 · 운영 학습 노트

Headless · CI · Cloud 실행

학습 목표: 사람이 지켜보지 않는 Agent 실행(Headless CLI, SDK, GitHub Actions, Cloud Session, 예약 실행)을 구분하고, 각 실행에서 권한 · 네트워크 · 비용 한도를 명시적으로 정하며, 실행 기록을 남기고 흔한 설정 문제를 순서대로 진단할 수 있다.

기준일: 2026-09-29. Claude Code는 공식 문서, Codex는 공개 소스와 공식 Action 저장소 기준이며 Flag 이름은 자주 바뀐다. 이 문서의 모든 명령은 실행 전에 --help로 다시 확인한다.

핵심 개념

실행 방식 Claude Code Codex 맞는 일
Headless CLI claude -p codex exec Script · Makefile에서 한 번 묻고 결과 받기
SDK Claude Agent SDK (Python · TypeScript) 확인 필요 내 Program 안에 Agent Loop 넣기
CI Action anthropics/claude-code-action openai/codex-action PR · Issue 이벤트에 반응
Cloud Session Claude Code on the web Codex cloud 노트북을 닫아도 계속되는 작업
예약 실행 Routines, Actions schedule Actions schedule 매일 보고서, 주간 정리
flowchart LR
    T1[사람의 명령] --> R[실행기]
    T2[PR 또는 Issue 이벤트] --> R
    T3[Cron 일정] --> R
    R --> A[Agent: 권한 · 네트워크 · 예산 적용]
    A --> O[산출물: Branch · PR · 댓글 · 보고서]
    O --> G{사람이 검토했는가}
    G -->|예| MG[Merge 또는 반영]

원리

사람이 없으면 설정이 대신 답한다

대화형 Session에서는 사람이 권한 질문에 답하고, 멈추고, 비용을 본다. Headless에서는 그 답을 미리 적어 두어야 한다. dontAsk는 물어야 할 호출을 전부 거부하고 허용 규칙에 걸린 것만 실행하므로 잠근 CI에 맞다. 규칙 Bash(git diff *)의 공백은 중요하다. 공백 없이 Bash(git diff*)라 쓰면 git diff-index도 맞는다.

질문 Claude Code Codex
무엇을 묻지 않고 해도 되나 --allowedTools "Read,Bash(git diff *)", --permission-mode dontAsk --sandbox read-only · workspace-write
어디까지 닿나 Cloud Environment의 네트워크 수준, --strict-mcp-config Sandbox, Cloud의 Agent 단계 인터넷 설정
얼마나 쓰나 --max-turns, --max-budget-usd, --model --model, Workflow timeout-minutes

재현 가능한 실행은 암묵적 설정을 싫어한다

claude -p는 기본적으로 대화형과 같은 설정(CLAUDE.md, Hook, Skill, Plugin, .mcp.json)을 읽고, 신뢰 확인 없이 저장소의 Hook과 MCP Server를 실행한다. --bare는 이 자동 탐색을 모두 건너뛰며 Script용으로 권장되고, 앞으로 -p의 기본값이 될 예정이다. 대신 필요한 것을 --append-system-prompt-file, --mcp-config, --agents, --settings로 명시적으로 넘긴다. 남이 올린 코드를 도는 CI일수록 이쪽이 안전하다.

적용: 이 저장소의 설정

2026-09-29 현재 이 저장소에는 .github/workflows/도 .claude/settings.json도 없으므로 아래 설정은 "도입한다면"의 형태다(Model 이름은 예시, <commit-sha>는 검토한 Action Commit). 도입 전에 .ai/HARNESS.md가 요구하는 두 가지:

Headless 한 줄

claude --bare -p "Summarize the failing tests in test.log" --allowedTools "Read" --output-format json --max-turns 5 --max-budget-usd 1.00
codex exec --sandbox read-only --json -o summary.md "Summarize the failing tests in test.log"

GitHub Actions

name: agent-review
on: pull_request
permissions:
  contents: read
  pull-requests: read
  id-token: write
jobs:
  review:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    concurrency:
      group: agent-review-${{ github.event.pull_request.number }}
      cancel-in-progress: true
    steps:
      - uses: actions/checkout@<commit-sha>
      - uses: anthropics/claude-code-action@<commit-sha>
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: "Use the adversarial-reviewer subagent to review this pull request against its description."
          claude_args: |
            --max-turns 8
            --allowedTools "Read,Grep,Glob,Bash(git diff *)"
      - uses: openai/codex-action@<commit-sha>
        with:
          openai-api-key: ${{ secrets.OPENAI_API_KEY }}
          prompt-file: .github/codex/review.md
          permission-profile: ":read-only"
          safety-strategy: drop-sudo
          output-file: codex-review.md

심화

Claude Agent SDK

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    options = ClaudeAgentOptions(allowed_tools=["Read", "Grep", "Glob"], max_turns=5, max_budget_usd=1.0)
    async for message in query(prompt="List TODO comments in src/ grouped by file.", options=options):
        print(message)

asyncio.run(main())

설치는 pip install claude-agent-sdk 또는 npm install @anthropic-ai/claude-agent-sdk. Claude Code와 같은 도구 · Agent Loop · Context 관리를 Library로 쓰며, .claude/의 Skill과 설정도 읽는다. 다른 언어에서는 claude -p --output-format json을 Subprocess로 부르면 된다. 제3자 제품에서 claude.ai 로그인을 제공하는 것은 허용되지 않으므로 API Key 인증을 쓴다.

Cloud Session

항목 Claude Code on the web Codex cloud
네트워크 Environment마다 None · Trusted(기본) · Full · Custom Setup 단계는 인터넷 가능, Agent 단계는 기본 차단 + 허용 목록
준비 Setup Script: Claude Code 시작 전 root로 실행, Ubuntu 24.04, 0으로 끝나야 함 Setup Script, 선택적 Maintenance Script
Cache 약 5분 안에 끝난 Setup 결과를 Snapshot, 약 7일 뒤 재생성 Script · 변수 · Secret이 바뀌면 무효화
Secret 환경 변수는 그 Environment 사용자 모두가 읽는다. Secret을 넣지 않는다 Secret은 Setup Script에만 주고 Agent 단계 전에 제거
저장소 설정 CLAUDE.md, .claude/settings.json, .mcp.json, Skill · Agent는 따라온다. ~/.claude와 Plugin은 안 온다 AGENTS.md를 읽는다

Claude Code에서 Setup Script는 VM 준비(도구 설치), SessionStart Hook은 로컬과 Cloud 모두에서 도는 Project 준비(npm install)에 쓴다. 터미널에서는 claude --cloud "작업"으로 Cloud Session을 만들고 claude --teleport로 가져온다.

예약 실행

비용 통제와 관측

수단 설정 효과
Model --model, Subagent model: haiku 단순 분류 · 탐색을 싼 Model로
턴 · 예산 --max-turns, --max-budget-usd(print 모드, Subagent 사용량 포함) 폭주 차단
시간 · 동시성 timeout-minutes, concurrency 중복 실행 · 무한 대기 차단
기록 JSON의 total_cost_usd, /usage, CLAUDE_CODE_ENABLE_TELEMETRY=1(OpenTelemetry), Codex [otel] 추정 비용 · 이벤트 수집. 청구서의 정답은 Console

문제 해결 체크리스트

증상 먼저 볼 것 흔한 원인
지시를 무시한다 /context에 CLAUDE.md가 있는가 --bare로 안 읽힘, 하위 폴더 CLAUDE.md는 그 폴더 파일을 읽을 때 로드, 지시가 모호하거나 충돌. 반드시 지킬 규칙은 권한 · Hook으로
권한 질문이 계속 뜬다 /permissions 규칙 문법 오류, 로컬에서만 허락하고 커밋 안 함. Headless는 --allowedTools
MCP Server가 안 뜬다 /mcp, claude mcp list, codex mcp list 승인 대기, 환경 변수 누락 경고, OAuth 미완료. claude --debug=mcp 로그
Hook이 안 돈다 /hooks 별도 파일에 정의(설정 파일의 "hooks" 키여야 함), matcher를 배열로 씀, --bare, Cloud에 없는 사용자 설정
Cloud Session이 시작 안 됨 Setup 단계 Log Script가 0이 아닌 값으로 끝남, 네트워크 None에서 설치 시도
429 · 529 오류 오류 Reference, /usage 동시 Subagent · Job 과다. 동시성 제한, --fallback-model
어디부터 볼지 모르겠다 /doctor · claude doctor, codex doctor 설치 · 인증 · 설정 파일 오류

흔한 오해

자기 점검 질문

  1. claude -p와 claude --bare -p는 저장소의 Hook과 .mcp.json을 어떻게 다르게 다루는가?
  2. Fork PR을 리뷰하는 Workflow에서 pull_request_target이 위험한 이유를 설명하라.
  3. Cloud Setup Script와 SessionStart Hook에 각각 무엇을 넣어야 하는가?
  4. 에이전트 실행 결과를 나중에 인용하려면 무엇을 함께 기록해야 하는가?

참고 자료