- src/dist 산출물 분리 원칙 정리(.gitignore, .gitattributes) - 루트 및 주요 폴더(config/scripts/prompts/tests/src, 런타임 폴더 5종)에 안내용 README.md 추가 - CHANGELOG.md, LICENSE, docs/ops/05-release-and-versioning.md 추가 - docs/README.md 문서 지도 갱신
56 KiB
Google Antigravity CLI (agy) 정본 — 설치 · 인증 · Headless 실행
이 문서의 역할: 이 프로젝트가 채택한 유일한 AI 에이전트 CLI 인
agy에 대한 단일 정본(SSOT). 설치·인증·비대화형 실행·설정·권한·함정을 여기 한 곳에 모은다. 다른 문서는 이 문서를 참조하고 중복 서술하지 않는다.
작성 기준일: 2026-09-02
검증 방식: 공식 문서 직접 열람(WebFetch) + 로컬 머신 실측(Windows 11 Pro 10.0.26220, agy v1.1.22)
실측 머신 경로: C:\Users\encep\AppData\Local\agy\bin\agy.exe
0. 한눈에 보기
agy는 Google Antigravity 의 터미널 에이전트 CLI 다. Go 로 작성된 단일 실행 파일이며 Windows 에서%LOCALAPPDATA%\agy\bin\agy.exe에 설치된다. 실측 바이너리 크기 약 186 MB.- Headless 는 1급 기능이다.
agy -p "<프롬프트>" --output-format json으로 완전한 비대화형 실행이 되고,status/response/usage/error를 담은 JSON 봉투를 stdout 으로 뱉는다. 종료 코드도 규약이 있다. - 인증 토큰은 파일에 저장된다. 실측 결과
~/.gemini/antigravity-cli/antigravity-oauth-token평문 JSON. 공식 문서는 OS 키링(Windows Credential Manager)을 말하지만, 실측 머신의cmdkey /list에는 관련 항목이 없었다. 이는 작업 스케줄러 무인 실행에 결정적으로 유리하다 (키링 잠금 문제를 피함). 대신 파일 유출 = 계정 탈취이므로 보안 취급 주의. - 최초 1회는 대화형 로그인이 필수다. 헤드리스는 캐시된 자격증명을 쓴다. 따라서 부트스트랩 설계에 "미인증 감지 → 사용자에게 프롬프트 창 띄우기" 경로가 반드시 필요하다.
--json-schema는 신뢰할 수 없다(실측). 문서상structured_output필드로 검증된 객체가 온다고 하지만, 실측에서는structured_output이 없고response안에 JSON 조각이 4번 반복되어 섞여 나왔다. 파이프라인은 반드시 자체 파싱·검증 계층을 둬야 한다.- 첫 호출 오버헤드가 크다(실측). "OK 한 단어만 답하라"는 프롬프트에 input_tokens 28,317 / 33.7초. 시스템 프롬프트와 워크스페이스 인덱싱 비용이다. 짧은 작업을 여러 번 호출하는 설계는 비싸다. 호출을 묶어라.
- 기본
--print-timeout은 5분. 배치에서는 명시적으로 늘려 잡는다. - 자동 백그라운드 self-update 가 돌기 때문에 배치 실행 중 업데이트 충돌 위험이 있다.
AGY_CLI_DISABLE_AUTO_UPDATE=true로 끄고 주 1회 계획 업데이트하는 것을 권한다.
1. 목차
- 제품 정체성과 위치
- 설치
- 인증
- Headless(비대화형) 실행 정본
- 출력 포맷 3종 상세
- 구조화 출력과 그 함정
- 모델 · 에이전트 · 추론 강도
- 권한 모델
- 실행 모드
- 설정 파일 전체 키
- 디렉터리·파일 레이아웃 실측
- 종료 코드와 오류 처리
- 크레딧·쿼터
- 트러블슈팅
- 배치·스케줄러 관점 체크리스트
- 주변 생태계
- 부록 A. 출처 목록
- 부록 B. 미해결 질문 / 실측 필요 항목
2. 제품 정체성과 위치
공식 문서 원문 인용:
"The Antigravity CLI is the lightweight Terminal User Interface (TUI) surface of Antigravity. It brings the same core agentic capabilities as Antigravity 2.0 (such as multi-step reasoning, multi-file editing, tool calling, and conversation history) directly to your terminal."
| 항목 | 내용 |
|---|---|
| 명령어 이름 | agy (Windows: agy.exe) |
| 문서 기준 버전 | v1.1.22 |
| 실측 설치 버전 | 1.1.22 (agy --version) |
| winget 최신 | 1.1.23 (Google.AntigravityCLI) |
| 구현 언어 | Go |
| 발표 | 2026-05-19 Google I/O |
| 위치 | Antigravity 2.0(데스크톱/IDE)과 동일한 에이전트 코어, 설정 동기화, 대화 상호 export |
| Gemini CLI 와의 관계 | 후속 제품. /docs/cli/gcli-migration 에 확장·스킬·설정 일괄 마이그레이션 가이드 존재 |
| 형제 제품 | Antigravity IDE (agy-ide, winget Google.AntigravityIDE v2.5.5), Antigravity 데스크톱 (Google.Antigravity v2.11.0) |
혼동 주의: agy (CLI) 와 agy-ide (IDE 런처) 는 다른 명령이다. 2026년 5월에 IDE 런처가 agy-ide 로 이름이 바뀌었다.
주요 기능(공식 개요 페이지):
- 키보드 중심 인터페이스
- 다단계 추론, 다중 파일 편집
- 도구 호출, 대화 이력
- 헤드리스 모드 및 백그라운드 작업 실행
- 샌드박스 환경, 서브에이전트
- MCP, 플러그인, 스킬 확장
3. 설치
3.1 공식 설치 명령 (OS별)
# macOS / Linux
curl -fsSL https://antigravity.google/cli/install.sh | bash
# Windows PowerShell
irm https://antigravity.google/cli/install.ps1 | iex
:: Windows CMD
curl -fsSL https://antigravity.google/cli/install.cmd -o install.cmd && install.cmd && del install.cmd
3.2 설치 위치
| OS | 경로 |
|---|---|
| macOS / Linux | ~/.local/bin/agy |
| Windows | C:\Users\<username>\AppData\Local\agy\bin\agy.exe |
실측 확인:
$ where.exe agy
C:\Users\encep\AppData\Local\agy\bin\agy.exe
C:\Users\encep\AppData\Local\Microsoft\WinGet\Links\agy.EXE
함정:
where에 두 경로가 잡힌다. winget 으로도 설치된 이력이 있으면 WinGet Links 심볼릭이 함께 잡힌다. 배치 스크립트는 절대 경로를 고정해서 쓰는 것이 안전하다.
3.3 install.ps1 동작 해부 (전문 확인 완료)
설치 스크립트를 직접 내려받아 전문을 읽었다. 동작 순서:
- TLS 1.2 강제 (ConstrainedLanguage 모드가 아닐 때만)
- 인자 파싱:
-d/--dir로 설치 디렉터리 커스터마이즈. 나머지 인자는 뒤의agy install로 패스스루 - 기존 설치 감지:
agy.exe가 이미 있으면 아무 것도 하지 않고 종료 코드 0 으로 빠진다. 메시지:Notice: 'agy.exe' is already installed at <path>.The Antigravity CLI automatically self-updates in the background.If you want to perform a fresh installation, delete the binary first:Remove-Item "<path>" -Force - 아키텍처 감지:
PROCESSOR_ARCHITEW6432우선, 없으면PROCESSOR_ARCHITECTURE.AMD64→windows_amd64,ARM64→windows_arm64. 그 외는 치명적 오류. - 매니페스트 다운로드:
https://antigravity-cli-auto-updater-974169037036.us-central1.run.app/manifests/<platform>.json→version,url,sha512획득 - 스테이징 다운로드:
%LOCALAPPDATA%\antigravity\staging\agy.exe - SHA512 검증:
Get-FileHash우선, 실패 시certutil -hashfile ... SHA512폴백. 불일치 시:Security Halt: Checksum verification failed. The downloaded file may be corrupted or compromised. - 배치 및 Unblock:
Copy-Item후Unblock-File(Mark-of-the-Web 제거) - 네이티브 셋업 핸드오프:
& $binaryPath install $setupFlags실행. 실패해도 흡수(Unix 의|| true와 동일). - finally 블록에서 스테이징 파일 정리
배치 관점 시사점:
- 이미 설치돼 있으면 재실행이 안전(idempotent) 하다. 부트스트랩 스크립트에서 무조건 호출해도 된다.
- 업데이트 목적으로는 쓸 수 없다. 기존 바이너리가 있으면 그냥 빠진다. 업데이트는 자동 self-update 또는
agy update담당. - 무결성 검증이 내장돼 있어 별도 검증 불필요.
-d/--dir로 설치 경로를 프로젝트 전용으로 고정할 수 있다.
3.4 agy install 서브커맨드 (실측)
$ agy install --help
Usage: agy.exe install [flags]
Configure environment paths and shell settings
Flags:
--dir Custom directory target to configure PATH for
-h Show help
--help Show help
--skip-aliases Bypasses shell profile alias purging
--skip-path Bypasses shell profile PATH appending
즉 agy install 은 바이너리 설치가 아니라 환경 구성(PATH 추가, 셸 프로필 별칭 정리)이다. install.ps1 의 9단계가 이걸 호출한다.
3.5 winget 경로
$ winget list --name antigravity
이름 장치 ID 버전 사용 가능 원본
--------------------------------------------------------------------
Antigravity 2.11.0 Google.Antigravity 2.11.0 winget
Antigravity CLI Google.AntigravityCLI 1.1.10 1.1.23 winget
Antigravity IDE (User) Google.AntigravityIDE 2.5.5 winget
무인 설치 명령(권장 형태):
winget install --id Google.AntigravityCLI --silent --accept-package-agreements --accept-source-agreements
⚠️ 미검증 / 조사 필요: winget 은 SYSTEM 계정·서비스 세션에서 동작하지 않는 것으로 알려져 있다. 작업 스케줄러가 사용자 계정으로 실행될 때는 문제없지만, SYSTEM 으로 실행하면 실패할 수 있다. →
docs/research/09-agy-bootstrap-and-provisioning.md에서 결론.
3.6 자동 업데이트
- 공식 문서: "The Antigravity CLI automatically self-updates in the background."
- 비활성화 환경변수:
AGY_CLI_DISABLE_AUTO_UPDATE=true - 업데이터 락 파일:
~/.gemini/antigravity-cli/updater/update.lock - 락 충돌 경고 문자열:
Warning: another background updater process is already active (update.lock) - 수동 업데이트 서브커맨드:
agy update(실측:agy update --help는Usage of update:만 출력하고 플래그 목록이 비어 있음 — 인자 없이 쓰는 명령)
배치 정책 권고: 06:00 배치 실행 시 AGY_CLI_DISABLE_AUTO_UPDATE=true 를 설정해 업데이트가 끼어들지 않게 하고, 별도 주간 작업에서 agy update 를 돌린다. 배치 도중 바이너리가 교체되면 실행 실패 또는 예측 불가 동작이 발생한다.
4. 인증
4.1 공식 문서상 인증 경로
| 방식 | 동작 | 비대화형 적합성 |
|---|---|---|
| 로컬 키링 로그인 | OS 네이티브 보안 키링(Apple Keychain, Linux Secret Service/dbus, Windows Credential Manager) 접근. 유효한 자격증명이 있으면 조용히 인증, 없으면 기본 브라우저로 OAuth 로그인 | 최초 1회 대화형 필요 |
| 원격 SSH OAuth | SSH 감지 시 "manual URL loop" — 인증 URL 을 로컬 브라우저에 붙여넣고, 받은 영숫자 코드를 터미널에 다시 붙여넣기 | 대화형 |
| Gemini API 키 | ~/.gemini/antigravity-cli/settings.json 에 modelProvider: "gemini" 설정 + GEMINI_API_KEY 환경변수 export. 문서 원문: "The CLI skips the sign-in screen and opens the main interface directly." |
완전 비대화형 가능 |
| 커스텀 엔드포인트 | GOOGLE_GEMINI_BASE_URL 환경변수로 Gemini 호환 대체 엔드포인트 지정 |
부가 |
| 로그아웃 | CLI 안에서 /logout — 계정 연결 해제 및 OS 키링의 저장된 인증 프로필 삭제 |
— |
4.2 실측: 토큰은 파일에 있다
$ ls ~/.gemini/antigravity-cli/
-rw-r--r-- antigravity-oauth-token # 504 바이트
파일 내용 형태 (값은 마스킹):
{"token":{"access_token":"ya29.<REDACTED>","token_type":"...", ...}}
한편 Windows 자격증명 관리자에는 관련 항목이 없었다:
$ cmdkey /list | grep -i -E "antigrav|agy|google"
(결과 없음)
결론과 시사점:
| 사실 | 배치 운영에 대한 함의 |
|---|---|
| 토큰이 사용자 프로필 아래 평문 파일로 존재 | 작업 스케줄러가 동일 사용자 계정으로 실행되면 키링 잠금 문제 없이 인증이 통과한다. 이것이 이 프로젝트의 인증 전략의 근거다. |
| Windows Credential Manager 를 쓰지 않음(실측) | S4U(암호 저장 안 함) 방식으로 실행해도 키링 접근 실패 위험이 낮다. 다만 사용자 프로필이 로드돼야 파일에 접근 가능 — SYSTEM 계정 실행은 금지. |
| 토큰 = 계정 접근 권한 | 이 파일을 백업·전송·로그에 남기지 않는다. 리포지토리에 절대 커밋 금지. .gitignore 에 명시. |
| access_token 은 만료된다 | refresh 실패 시 배치가 인증 오류로 죽는다. 미인증 감지 → 사용자 알림 경로가 반드시 필요하다. |
4.3 인증 상태 비대화형 확인 방법
권장 헬스체크(가장 저렴한 형태):
$env:AGY_CLI_DISABLE_AUTO_UPDATE = "true"
$out = & "$env:LOCALAPPDATA\agy\bin\agy.exe" -p "Reply with exactly: PONG" --output-format json --print-timeout 90s 2>&1
$obj = $out | ConvertFrom-Json
if ($obj.status -ne "SUCCESS") { Write-Error $obj.error }
실측 결과(정상 인증 상태):
{"conversation_id":"eab39b4e-0a09-494f-9ded-87aaf2b9c6e1","status":"SUCCESS","response":"OK\n","duration_seconds":33.6771974,"num_turns":1,"usage":{"input_tokens":28317,"output_tokens":44,"thinking_tokens":43,"cache_read_tokens":0,"total_tokens":28361}}
종료 코드 0.
⚠️ 비용 주의: 이 헬스체크 한 번에 input 28k 토큰이 든다. 매 배치마다 별도 헬스체크를 돌리지 말고, 실제 작업 호출의 결과로 인증 실패를 판정하라.
5. Headless(비대화형) 실행 정본
5.1 전체 플래그 표 (실측 agy --help 원문 기준)
| 플래그 | 기본값 | 설명 |
|---|---|---|
-p, --print, --prompt |
— | 단일 프롬프트를 비대화형으로 실행하고 응답을 출력 |
-i, --prompt-interactive |
— | 초기 프롬프트를 실행하고 대화형 세션을 계속 |
--output-format |
text |
출력 포맷: text | json | stream-json |
--input-format |
text |
입력 포맷: text | stream-json. stream-json 은 stdin 에서 NDJSON 을 한 줄에 하나씩 읽어 턴마다 실행하며, --output-format stream-json 을 요구 |
--json-schema |
— | 구조화 출력 강제용 JSON 스키마 문자열 또는 스키마 파일 경로. stream-json 에서는 최종 result 에만 적용 |
--model |
— | 이 세션의 모델 (agy models 참조) |
--effort |
— | 추론 강도: low | medium | high |
--agent |
— | 이 세션의 에이전트 (agy agents 참조) |
-c, --continue |
false |
가장 최근 대화 이어가기 |
--conversation |
— | 대화 ID 로 이전 대화 재개 |
--dangerously-skip-permissions |
false |
모든 도구 권한 요청을 자동 승인 |
--disable-slash-commands |
— | print 모드에서 슬래시 명령·스킬 확장 비활성화 |
--print-timeout |
5m0s |
print 모드 응답 대기 제한 시간 |
--mode |
— | 에이전트 실행 모드 (accept-edits, plan) |
--sandbox |
false |
터미널 제한이 걸린 샌드박스로 실행 |
--add-dir |
[] |
워크스페이스에 디렉터리 추가 (반복 가능) |
--project |
— | 이 세션의 프로젝트 ID 또는 이름 |
--new-project |
— | 이 세션용 새 프로젝트 생성 |
--log-file |
— | CLI 로그 파일 경로 재정의 |
5.2 서브커맨드 (실측)
| 서브커맨드 | 설명 |
|---|---|
agent / agents |
사용 가능한 에이전트 목록 |
changelog |
변경 로그·릴리스 노트 |
help |
서브커맨드 도움말 |
install |
환경 경로·셸 설정 구성 |
mcp |
MCP 서버 관리 (add, remove, list, enable, disable) |
mic-serve |
이 머신의 마이크를 다른 호스트의 CLI 에 제공 |
models |
사용 가능한 모델 목록 |
plugin / plugins |
플러그인 관리 (install, uninstall, list, enable, disable) |
update |
CLI 업데이트 |
5.3 표준 스트림 규약
공식 문서 원문:
Output goes to
stdout; diagnostics (errors, auth prompts, progress) go tostderr.
배치 설계: stdout 만 파싱하고, stderr 는 통째로 로그 파일에 남긴다. 둘을 섞으면(2>&1) JSON 파싱이 깨진다.
5.4 인증 전제
공식 문서 원문:
"Headless mode uses your cached credentials. Authenticate once with an interactive
agysession first."
6. 출력 포맷 3종 상세
6.1 text (기본)
agy -p "In one sentence, what does the command git bisect do?"
응답 본문만 평문으로 나온다. 배치에서는 오류 판별이 어려우므로 사용하지 않는다.
6.2 json — 단일 봉투 (이 프로젝트의 기본 선택)
agy -p "In one sentence, what is a git rebase?" --output-format json | jq
봉투 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
conversation_id |
string | 대화 ID (재개용) |
status |
string | SUCCESS | ERROR | CANCELED | INTERRUPTED | INVALID | WAITING | RUNNING |
response |
string | 응답 본문 |
error |
string | 실패 시에만 존재 |
duration_seconds |
number | 소요 시간 |
num_turns |
number | 턴 수 |
usage |
object | input_tokens, output_tokens, thinking_tokens, cache_read_tokens, total_tokens |
structured_output |
object | --json-schema 사용 시 (⚠️ 6.3/7 절 참조 — 실측에서 누락됨) |
json_schema |
object | 적용된 스키마 에코백 |
status 값 의미:
| 값 | 의미 |
|---|---|
SUCCESS |
응답과 함께 정상 완료 |
ERROR |
오류로 종료 |
CANCELED |
취소됨 |
INTERRUPTED |
인터럽트(예: SIGINT) |
INVALID |
유효하지 않은 상태에 도달 |
WAITING |
입력 대기 중 종료 |
RUNNING |
종료 상태에 도달하지 못함 |
6.3 stream-json — NDJSON 이벤트 스트림
agy -p "In one sentence, what is a git rebase?" --output-format stream-json
이벤트 종류: init(1회) → step_update(여러 번) → result(1회)
init 이벤트 예:
{"event":"init","conversation_id":"c3b66b04-872b-4fbe-a3a4-058a026ef20a","init":{"cwd":"/home/user/project","tools":["ask_permission","run_command","write_to_file","..."],"permission_mode":"request-review"}}
step_update (에이전트 응답 델타):
{"event":"step_update","step_update":{"conversation_id":"c3b66b04-872b-4fbe-a3a4-058a026ef20a","step_index":3,"state":"DONE","step_type":"agent_response","text_delta":"Git rebase destructively rewrites...","duration_seconds":6.28,"usage":{"input_tokens":10302,"output_tokens":582,"thinking_tokens":551,"cache_read_tokens":8113,"total_tokens":10884}}}
step_update (도구 호출 — 감사 로그로 매우 유용):
{"event":"step_update","step_update":{"conversation_id":"edb1c8c1-50ba-4f3f-87eb-412d0e9d47c3","step_index":4,"state":"DONE","step_type":"tool","tool_name":"run_command","duration_seconds":0.07,"tool_info":{"name":"run_command","parameters":{"CommandLine":"echo hello_headless_demo"},"output":"hello_headless_demo\r\n"}}}
tool_info 는 name, parameters, output, 실패 시 error 를 담는다.
result 이벤트:
{"event":"result","result":{"conversation_id":"...","status":"SUCCESS","response":"Git rebase...","duration_seconds":6.88,"num_turns":1,"usage":{"input_tokens":10418,"output_tokens":589,"thinking_tokens":551,"cache_read_tokens":8113,"total_tokens":11007}}}
jq 파싱 레시피:
# 응답 텍스트만 추출
agy -p "Name three popular version control systems, comma-separated." --output-format json | jq -r '.response'
# 스트리밍 텍스트 이어붙이기
agy -p "Explain merge conflicts in two sentences." --output-format stream-json \
| jq -j 'select(.event=="step_update") | .step_update.text_delta // empty'
# 토큰 사용량만
agy -p "In one sentence, what is a git rebase?" --output-format stream-json \
| jq 'select(.event=="result") | .result.usage'
6.4 stdin 스트리밍 입력 (--input-format stream-json)
여러 프롬프트를 한 세션에서 연속 실행한다. --output-format stream-json 과 반드시 짝이어야 한다.
printf '%s\n' \
'{"event":"user","message":{"content":"Reply with exactly the word: apple. Nothing else."}}' \
'{"event":"user","message":{"content":"What word did I ask you to reply with? Answer with just that word."}}' \
| agy --input-format stream-json --output-format stream-json
content 는 문자열 또는 텍스트 블록 리스트 둘 다 허용:
{ "event": "user", "message": { "content": "Reply with exactly: banana" } }
{ "event": "user", "message": { "content": [{ "type": "text", "text": "Reply with exactly: banana" }] } }
메타데이터 범위 주의: response 는 현재 턴의 것이지만, num_turns / usage / duration_seconds 는 세션 누적이다.
세션 종료: stdin 을 닫으면 현재 턴 완료 후 프로세스가 종료된다. 정상 종료는 코드 0.
지원하지 않는 입력과 그 결과:
| 입력 | 결과 | 종료 코드 |
|---|---|---|
인식되지 않는 event 이름 |
건너뜀, stderr 에 경고 | — |
control_request / control_response 이벤트 |
ERROR result, 세션 종료 |
2 |
CLI 가 처리하는 슬래시 명령(/model, /usage) |
ERROR result, 세션 종료 |
2 |
event 필드 누락 |
ERROR result, 세션 종료 |
1 |
| 잘못된 JSON 줄 | ERROR result, 세션 종료 |
1 |
text 외의 content block 타입 |
ERROR result, 세션 종료 |
1 |
슬래시 명령 오류 메시지 원문:
{ "event": "result", "result": { "conversation_id": "4fae3a70-409d-42a4-86ea-9de206a49ff4", "status": "ERROR", "response": "", "error": "/model is answered by the CLI itself and is unavailable with --input-format stream-json; run it as its own --print /model invocation", "duration_seconds": 0, "num_turns": 0, "usage": { "input_tokens": 0, "output_tokens": 0, "thinking_tokens": 0, "cache_read_tokens": 0, "total_tokens": 0 } } }
흔한 실수 표(공식 문서):
| 실수 | 왜 실패하나 | 해결 |
|---|---|---|
--output-format json 또는 text 와 조합 |
종료 시 단일 봉투만 나와 턴이 유실됨 | --output-format stream-json 사용 |
-p 로 프롬프트 전달 |
스트리밍 모드는 stdin 만 수신 | 프롬프트를 stdin 의 user 메시지로 전송 |
/model, /usage 를 스트림에 전송 |
CLI 내부 처리라 JSON 흐름이 깨짐 | 별도 agy -p /model 로 실행 |
num_turns 를 턴별 카운트로 오해 |
세션 누적 값 | 현재 턴은 response 필드 사용 |
| stdout 을 프로세스 종료 후 읽으려 함 | stdin 닫을 때까지 세션 유지 | 줄 단위로 즉시 읽기 |
파이썬으로 세션을 구동하는 공식 예제:
import json
import subprocess
proc = subprocess.Popen(
["agy", "--input-format", "stream-json", "--output-format", "stream-json"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True,
bufsize=1,
)
def ask(prompt):
"""Send one prompt and return the response for that turn."""
message = {"event": "user", "message": {"content": prompt}}
proc.stdin.write(json.dumps(message) + "\n")
proc.stdin.flush()
for line in proc.stdout:
event = json.loads(line)
if event["event"] == "result":
return event["result"]["response"]
first = ask("Name one popular version control system. Answer with one word.")
print(ask(f"Name a competitor to {first.strip()}. Answer with one word."))
proc.stdin.close()
proc.wait()
6.5 대화 이어가기
# 가장 최근 대화 이어가기
agy -p "Now explain your previous answer in more detail" --continue
# 특정 대화 ID 재개
agy -p "Summarize what we discussed" --conversation 055a398f-db14-4c5f-abbb-1bf03f8120a7
배치에서는 --continue 를 쓰지 마라. 배치는 매번 독립적이어야 하며, 최근 대화가 무엇인지 예측할 수 없다. 필요하면 conversation_id 를 명시적으로 저장·전달한다.
7. 구조화 출력과 그 함정
7.1 문서상 동작
agy -p "Parse v2.14.3 into major, minor, patch." \
--output-format json \
--json-schema '{"type":"object","properties":{"major":{"type":"integer"},"minor":{"type":"integer"},"patch":{"type":"integer"}},"required":["major","minor","patch"]}' | jq
스키마는 문자열, 파일 경로, 또는 원시 타입(string, number, integer, boolean)을 받는다. 결과는 봉투의 structured_output 필드에 담긴다.
7.2 실측 결과 — 기대와 다르다 ⚠️
명령:
agy -p "Return today's weekday name in Korean." --output-format json \
--json-schema '{"type":"object","properties":{"weekday":{"type":"string"}},"required":["weekday"]}' \
--print-timeout 90s
실제 출력:
{"conversation_id":"cb636581-e8de-4375-8542-4f83fca1db9c","status":"SUCCESS","response":"{\"toolAction\":\"Finishing task\",\"toolSummary\":\"Return weekday in Korean\",\"weekday\":\"수요일\"}\n오늘(2026년 9월 2일)의 요일은 **수요일**입니다.\n{\"toolAction\":\"Finish task\",\"toolSummary\":\"Task completion\",\"weekday\":\"수요일\"}\n오늘의 요일은 **수요일**입니다.\n{\"toolAction\":\"Finish task\",\"toolSummary\":\"Finish task\",\"weekday\":\"수요일\"}\n오늘(2026년 9월 2일)의 요일은 **수요일**입니다.\n{\"toolAction\":\"Finish task\",\"toolSummary\":\"Finish task\",\"weekday\":\"수요일\"}\n오늘(2026-09-02)의 요일은 **수요일**입니다.\n","duration_seconds":52.9313561,"num_turns":4,"json_schema":{"type":"object","properties":{"weekday":{"type":"string"}},"required":["weekday"]},"usage":{"input_tokens":86038,"output_tokens":2378,"thinking_tokens":2169,"cache_read_tokens":163370,"total_tokens":88416}}
관찰된 문제:
| 증상 | 상세 |
|---|---|
structured_output 필드 부재 |
봉투에 json_schema 는 에코백됐지만 structured_output 이 없다 |
response 오염 |
JSON 조각과 한국어 산문이 뒤섞여 있다 |
| 4회 반복 | num_turns: 4 — 모델이 스키마를 만족시키려 4번 시도했다 |
| 스키마에 없는 필드 | toolAction, toolSummary 가 섞여 나왔다 (내부 도구 래퍼로 추정) |
| 비용 폭증 | input 86k, output 2.4k, 총 88k 토큰, 52.9초. 같은 답을 얻는 단순 호출의 3배 |
설계 결론 (이 프로젝트의 규칙):
--json-schema를 1차 수단으로 신뢰하지 않는다.- 프롬프트 자체에 출력 형식을 강하게 못박는다: "오직 JSON 객체 하나만 출력하고, 코드 펜스·설명·서문을 붙이지 마라."
- 파이프라인은
response에서 JSON 을 견고하게 추출한다: 코드 펜스 제거 → 첫{부터 균형 잡힌 마지막}까지 슬라이스 →json.loads→ jsonschema 로 자체 검증. - 검증 실패 시 최대 N회 재시도하고, 그래도 실패하면 AI 결과 없이 리포트를 생성한다(graceful degradation).
--json-schema를 쓰더라도 보조 수단으로만 병행하고,structured_output이 있으면 우선 사용하되 없으면 4번 경로로 폴백한다.
권장 추출 함수:
import json, re
_FENCE = re.compile(r"^\s*```(?:json)?\s*|\s*```\s*$", re.MULTILINE)
def extract_json_object(text: str) -> dict | None:
"""agy 의 response 문자열에서 첫 번째 완결 JSON 객체를 견고하게 추출한다."""
if not text:
return None
s = _FENCE.sub("", text)
start = s.find("{")
while start != -1:
depth, in_str, esc = 0, False, False
for i in range(start, len(s)):
ch = s[i]
if in_str:
if esc:
esc = False
elif ch == "\\":
esc = True
elif ch == '"':
in_str = False
continue
if ch == '"':
in_str = True
elif ch == "{":
depth += 1
elif ch == "}":
depth -= 1
if depth == 0:
try:
return json.loads(s[start:i + 1])
except json.JSONDecodeError:
break
start = s.find("{", start + 1)
return None
8. 모델 · 에이전트 · 추론 강도
8.1 모델 목록 (실측 agy models, 2026-09-02)
| 슬러그 | 표시 이름 |
|---|---|
gemini-3.7-flash-high |
Gemini 3.7 Flash (High) |
gemini-3.7-flash-medium |
Gemini 3.7 Flash (Medium) |
gemini-3.7-flash-low |
Gemini 3.7 Flash (Low) |
gemini-3.6-flash-high |
Gemini 3.6 Flash (High) |
gemini-3.6-flash-medium |
Gemini 3.6 Flash (Medium) |
gemini-3.6-flash-low |
Gemini 3.6 Flash (Low) |
gemini-3.1-pro-high |
Gemini 3.1 Pro (High) |
gemini-3.1-pro-low |
Gemini 3.1 Pro (Low) |
claude-sonnet-4-6 |
Claude Sonnet 4.6 (Thinking) |
claude-opus-4-6-thinking |
Claude Opus 4.6 (Thinking) |
gpt-oss-120b-medium |
GPT-OSS 120B (Medium) |
참고: 공식 문서 예시에는
gemini-3.5-flash-medium도 등장하지만 실측 목록에는 없었다. 모델 슬러그는 하드코딩하지 말고, 부트스트랩 때agy models로 검증하는 것이 안전하다.
# 모델 고정
agy -p "Reverse the string antigravity." --model gemini-3.5-flash-medium
# 추론 강도
agy -p "Outline a plan to add caching to this service." --effort high
# 에이전트 선택
agy -p "Review this function for edge cases." --agent <agent-name>
알 수 없는 모델을 주면 종료 코드 비0 + status: ERROR:
agy -p "hi" --model does-not-exist-model --output-format json; echo "exit=$?"
{"conversation_id":"","status":"ERROR","response":"","error":"invalid model selection (--model \"does-not-exist-model\" --effort \"\"): model does-not-exist-model is not recognized as a known model or custom model in settings\nAvailable models:\n Gemini 3.6 Flash (High)\n ...","duration_seconds":0,"num_turns":0,"usage":{...}}
exit=1
8.2 이 프로젝트의 모델 선택 지침
| 유스케이스 | 권장 모델 | 이유 |
|---|---|---|
| 일일 변경사항 한국어 요약 | gemini-3.7-flash-medium |
정형 입력의 요약, 속도·비용 우위 |
| 셀렉터 자가 복구 제안 | gemini-3.1-pro-high 또는 claude-sonnet-4-6 |
HTML 구조 추론은 난도가 높음 |
| 이상 탐지 해석 | gemini-3.7-flash-high |
짧은 추론 |
| 주간 트렌드 코멘터리 | gemini-3.1-pro-high |
종합·서술 품질 |
8.3 에이전트 (실측 agy agents)
flutter_a11y_agent
현재 머신에는 커스텀 에이전트가 하나 등록돼 있다. 이 프로젝트는 커스텀 에이전트를 만들지 않고 기본 에이전트 + 프롬프트 파일로 간다(단순성 우선).
9. 권한 모델
9.1 세밀 권한 엔진
리소스 표기는 action(target) 형식이며 세 목록으로 통제한다.
| 목록 | 동작 |
|---|---|
deny |
즉시 차단 |
ask |
명시적 승인 대기 |
allow |
프롬프트 없이 자동 승인 |
우선순위: Deny > Ask > Allow (충돌 시 엄격하게 이 순서로 평가)
9.2 지원 액션과 타깃
| 액션 | 형식 | 동작 |
|---|---|---|
read_file |
경로 또는 * |
절대 경로 또는 워크스페이스 루트 기준 상대 경로 매칭. 재귀적 읽기 권한 부여 |
write_file |
경로 또는 * |
같은 타깃에 대해 read_file 을 암묵적으로 함께 부여 |
read_url |
도메인 또는 * |
호스트명과 서브도메인 매칭 (예: google.com 은 mail.google.com 포함) |
execute_url |
도메인 또는 * |
웹 액추에이션(클릭, 타이핑) |
command |
접두사/정규식 또는 * |
공백으로 분리된 각 토큰이 앵커된 정규식으로 평가됨 |
unsandboxed |
접두사 또는 * |
컨테이너 격리 밖에서 명령 실행 |
mcp |
server/tool 또는 * |
MCP 도구 접근 |
암묵 규칙:
- 파일 쓰기 권한은 그 경로의 읽기 권한을 자동 부여
- 경로에 읽기를 거부하면 그 경로 쓰기도 차단
기본 동작:
- 워크스페이스 자동 허용: 활성 프로젝트 디렉터리 안의 파일 읽기·쓰기는 자동 허용
- 웹은 기본 ask
- 설정되지 않은 액션은 기본 ask
9.3 헤드리스에서의 권한
공식 문서 원문 요지: 헤드리스에는 대화형 프롬프트가 없고 정책으로 처리된다. 워크스페이스 파일 읽기/쓰기는 자동 허용되지만, 셸 명령은 기본 Ask 이며 권한이 없으면 soft-deny 된다.
이것이 배치에서 가장 흔한 실패 원인이다. 반드시 사전 허용 규칙을 넣어라.
설정 예시 (~/.gemini/antigravity-cli/settings.json):
{
"permissions": {
"allow": [
"command(git)",
"command(npm run (build|lint|test))",
"read_url(google.com)",
"mcp(linter/*)",
"write_file(src/)"
],
"deny": [
"command(sudo)",
"write_file(.git/)"
],
"ask": ["command(*)", "mcp(sql/execute_mutation)"]
}
}
전부 자동 승인(위험):
agy -p "Run the test suite and report failures" --dangerously-skip-permissions
공식 경고 원문:
"
--dangerously-skip-permissionsapproves all tool calls, including file writes and command execution. Prefer scopedpermissions.allowrules unless you fully trust the prompt and environment."
이 프로젝트의 결론: --dangerously-skip-permissions 를 쓰지 않는다. 이유는 크롤링한 외부 텍스트가 프롬프트에 들어가므로 프롬프트 인젝션 표면이 존재하기 때문이다. 대신 이 프로젝트 전용 permissions.allow 를 최소 범위로 설정한다. 상세는 docs/research/10-agy-agent-integration-patterns.md.
9.4 크로스 플랫폼 경로 정규화
공식 문서 원문:
"Antigravity automatically normalizes paths prior to rule evaluation by stripping drive letters (e.g., C:) and converting all backslashes () to forward slashes (/)."
즉 규칙에 D:\workspace\DMF_Crawler 대신 workspace/DMF_Crawler 형태를 쓴다. 드라이브 문자는 제거되고 슬래시로 변환된다.
9.5 대화형 프롬프트에서의 범위 확장
승인 카드에서 타깃 문자열을 직접 편집해 권한 범위를 넓힐 수 있다. CLI 가 편집을 검증하고 그 세션 동안 확장된 권한을 적용한다.
10. 실행 모드
| 모드 | 동작 |
|---|---|
default |
파일 수정·생성 전에 대화형 diff 리뷰로 일시정지 |
accept-edits |
파일 편집·생성(mkdir, touch, 파일 쓰기)을 자동 승인 |
plan |
/plan 지시 접두사를 붙여 코드 작성 전 단계 분석·개요 작성 |
accept-edits 에서는 write_to_file, replace_file_content, multi_replace_file_content 가 자동 실행되며, 세션 중 생성된 서브에이전트도 이 설정을 상속한다.
설정 방법:
agy --mode=accept-edits
agy --mode=plan
{"agentMode": "accept-edits"}
대화형에서는 /settings 로 기본 모드를 고르거나 Shift+Tab 으로 순환한다.
권한과 모드는 독립적이다. 공식 문서 원문:
"Tool permission rules configured via
/permissionsor--dangerously-skip-permissionscontinue to govern shell commands (run_command) across all execution modes."
즉 모드는 파일 작업을, 권한은 셸 명령을 각각 통제한다.
11. 설정 파일 전체 키
11.1 위치
| 파일 | 경로 |
|---|---|
| 설정 | ~/.gemini/antigravity-cli/settings.json (Windows 도 %USERPROFILE%\.gemini\antigravity-cli\settings.json) |
| 키바인딩 | ~/.gemini/antigravity-cli/keybindings.json |
희소 저장(sparse persistence): 기본값과 다른 값만 디스크에 기록한다.
프로젝트 단위 설정은 문서화돼 있지 않다 — 사용자 단위 설정만 존재. 프로젝트별 차이는 CLI 플래그로 준다.
11.2 전체 키 표
| 키 | 타입 | 기본값 | 값/설명 |
|---|---|---|---|
colorScheme |
string | "terminal" |
"light", "solarized light", "colorblind-friendly light", "dark", "solarized dark", "colorblind-friendly dark", "tokyo night", "terminal" |
altScreenMode |
string | "default" |
"default"(적응형), "always"(대체 화면 버퍼 강제), "never"(인라인 강제) |
toolPermission |
string | "request-review" |
"request-review", "proceed-in-sandbox", "always-proceed", "strict" |
artifactReviewPolicy |
string | "asks-for-review" |
"asks-for-review", "agent-decides", "always-proceed" |
notifications |
boolean | false |
작업 완료 시 시스템 데스크톱 알림 및 터미널 벨 |
showTips |
boolean | true |
생성 중 프롬프트 패널 위에 팁 표시 |
showFeedbackSurvey |
boolean | true |
주기적 품질 피드백 설문 표시 |
editor |
string | "auto" |
"auto", "vim", "emacs", 커스텀 |
editorMode |
string | "default" |
"default"(평문 편집), "vim"(모달 편집) |
vimInsertFirst |
boolean | false |
Vim 편집을 Insert 모드로 시작하고 Enter 로 제출 |
allowNonWorkspaceAccess |
boolean | false |
에이전트 파일 도구가 Git/워크스페이스 루트 밖으로 나갈 수 있게 허용 |
enableTerminalSandbox |
boolean | false |
에이전트가 실행하는 로컬 명령을 OS 격리 링으로 제한 |
useG1Credits |
boolean | false |
플랜 쿼터 소진 후 개인 AI 크레딧 사용 |
enableTelemetry |
boolean | true |
메트릭 수집·크래시 로그 전송 허용 |
verbosity |
string | "high" |
"high"(전체 사고·출력), "low"(최소 표시) |
runningLightSpeed |
string | "medium" |
"fast", "medium", "slow", "off" |
agentMode |
string | "default" |
"accept-edits", "plan" (모드 문서 기준) |
permissions |
object | — | allow / deny / ask 배열 (9절 참조) |
statusLine |
object | — | {"type":"command","command":"<경로>"} (실측 확인) |
trustedWorkspaces |
array | — | 신뢰 워크스페이스 경로 목록 (실측 확인) |
modelProvider |
string | — | "gemini" 로 설정 시 GEMINI_API_KEY 사용, 로그인 화면 건너뜀 (설치 문서 기준) |
model |
string | — | 실측 파일에는 슬러그가 아니라 표시 이름("Gemini 3.7 Flash (High)")으로 저장돼 있었다 |
문서 예시:
{
"colorScheme": "tokyo night",
"altScreenMode": "always",
"toolPermission": "request-review",
"notifications": true,
"enableTerminalSandbox": true
}
11.3 toolPermission 값 의미 (베스트 프랙티스 문서)
| 값 | 동작 |
|---|---|
request-review (기본) |
쓰기 작업, bash 명령, 원격 네트워크 호출 전에 매번 확인 |
proceed-in-sandbox |
모든 터미널 실행을 보안 샌드박스 격리 링으로 제한. 안전한 명령은 자율 실행, 위험한 명령은 리뷰 요청 |
always-proceed |
자동 진행 |
strict |
모든 비읽기 작업에 대해 항상 확인, 완전한 라인별 투명성 |
11.4 환경변수
| 변수 | 용도 |
|---|---|
GEMINI_API_KEY |
modelProvider: "gemini" 와 함께 사용하는 API 키 |
GOOGLE_GEMINI_BASE_URL |
대체 Gemini 호환 엔드포인트 |
AGY_CLI_DISABLE_AUTO_UPDATE |
true 로 자동 업데이트 비활성화 |
LOCALAPPDATA |
Windows 설치 경로 결정에 사용 |
PROCESSOR_ARCHITEW6432 / PROCESSOR_ARCHITECTURE |
설치 스크립트의 아키텍처 감지 |
⚠️ 공식 설정 문서는 "환경변수로 설정을 덮어쓰는 방법은 문서화돼 있지 않다"고 명시한다. 런타임 재정의는 CLI 플래그로만 한다.
12. 디렉터리·파일 레이아웃 실측
~/.gemini/antigravity-cli/ 실측 목록:
| 항목 | 종류 | 설명 |
|---|---|---|
settings.json |
파일 | 사용자 설정 |
keybindings.json |
파일 | 키바인딩(문서 기준) |
antigravity-oauth-token |
파일 | OAuth 토큰 평문 JSON (보안 주의) |
installation_id |
파일 | 설치 식별자 |
history.jsonl |
파일 | 프롬프트 이력 (실측 213 KB) |
conversation_summaries.db |
파일 | 대화 요약 SQLite (실측 140 KB) |
conversations/ |
디렉터리 | 대화 저장소 |
log/ |
디렉터리 | 로그 (cli-YYYYMMDD_HHMMSS.log 형식) |
cli.log |
심볼릭 링크 | 최신 로그 파일로의 링크 |
crashes/ |
디렉터리 | 크래시 덤프 |
cache/ |
디렉터리 | 캐시 |
brain/ |
디렉터리 | 세션별 작업 공간 (하위에 scratch/) |
knowledge/ |
디렉터리 | 지식 저장소 |
rules/ |
디렉터리 | 규칙 파일 |
skills/ |
디렉터리 | 스킬 |
mcp/ |
디렉터리 | MCP 설정 |
plugins/bin/builtin/implicit/presence/annotations |
디렉터리 | 내부 |
updater/ |
디렉터리 | 자동 업데이터 (update.lock 포함) |
last_check.timestamp |
파일 | 업데이트 확인 시각 |
statusline.cmd, statusline.py |
파일 | 커스텀 상태줄 (사용자 설정) |
로그 경로 규약: 실행마다 새 로그 파일이 생기고 cli.log 가 최신을 가리킨다. --log-file 로 재정의 가능 → 배치에서는 실행 ID별 로그 파일을 지정하는 것을 권장한다.
13. 종료 코드와 오류 처리
| 코드 | 의미 |
|---|---|
0 |
성공 |
1 |
일반 실패 (잘못된 모델, 잘못된 JSON 입력, event 필드 누락, 잘못된 content block 타입) |
2 |
스트림 입력에서 control_request/control_response 또는 CLI 처리 슬래시 명령 수신 |
| 비0 (기타) | 실패, 사유는 stderr 로 |
json / stream-json 모드에서는 실패가 status 와 error 필드에도 나타난다. 배치는 종료 코드와 status 를 둘 다 확인해야 한다.
CI 실행 공식 예제:
#!/usr/bin/env bash
set -euo pipefail
result=$(agy -p "Name three popular version control systems, comma-separated." \
--output-format json \
--print-timeout 10m)
status=$(echo "$result" | jq -r '.status')
if [[ "$status" != "SUCCESS" ]]; then
echo "Agent run failed: $(echo "$result" | jq -r '.error')" >&2
exit 1
fi
echo "$result" | jq -r '.response' > result.txt
타임아웃 늘리기:
agy -p "Summarize the design tradeoffs of optimistic locking." --print-timeout 15m
14. 크레딧·쿼터
| 항목 | 내용 |
|---|---|
| 상태줄 표시 | 남은 크레딧 표시 (예: AI Credits: 42) |
/credits |
상세 통계 패널, 구매 링크 |
/usage (별칭 /quota) |
모델별 API 쿼터 조회 |
useG1Credits 설정 |
true 면 플랜 쿼터 소진 시 개인 크레딧으로 폴백, false 면 차단 |
⚠️ 공식 크레딧 문서에는 무료/유료 티어 구분, 일일·주간 한도, 모델별 단가, 쿼터 소진 시 오류 메시지·종료 동작,
GEMINI_API_KEY과금 차이, 레이트 리밋, 자동화 사용 가이드가 없다./docs/plans페이지를 참조하라고만 안내한다. → 부록 B 미해결 항목.
배치 관점 대응: usage.total_tokens 를 매 호출 로깅하고, 일일 누적 상한을 파이프라인 자체에서 강제한다. 쿼터 소진은 status: ERROR + error 문자열로 감지하고, 감지되면 AI 단계를 건너뛰고 리포트를 생성한다.
15. 트러블슈팅
| 증상 | 오류 문자열 | 해결 |
|---|---|---|
| 명령을 찾을 수 없음 | bash: agy: command not found |
~/.local/bin 을 PATH 에 추가(~/.bashrc/~/.zshrc), Windows 는 레지스트리 PATH 등록. 배치는 절대 경로 사용으로 회피 |
| 키링 접근 실패 | Error: failed to retrieve token: secret keyring is locked |
키체인 잠금 해제, 앱 권한 확인, 헤드리스 Linux 는 D-Bus 세션 초기화 |
| SSH 클립보드 실패 | Error: local pasteboard is empty or unreachable over SSH connection |
iTerm2/Ghostty 사용, OSC 52 쓰기 채널 활성화, tmux 클립보드 설정 |
| 업데이터 락 | Warning: another background updater process is already active (update.lock) |
~/.gemini/antigravity-cli/updater/update.lock 삭제 또는 AGY_CLI_DISABLE_AUTO_UPDATE=true |
| 설치 디렉터리 권한 | — | ~/.local/bin/(Unix) 또는 %LOCALAPPDATA%\agy\bin(Windows) 소유권·쓰기 권한 확인 |
| 체크섬 실패 | Security Halt: Checksum verification failed. |
네트워크·프록시 문제 또는 변조. 재시도, 실패 시 중단 |
| 알 수 없는 모델 | invalid model selection (--model "..." --effort "") |
agy models 로 슬러그 확인 |
16. 배치·스케줄러 관점 체크리스트
이 프로젝트가 06:00 무인 실행에서 반드시 지켜야 할 규칙.
- 절대 경로로 호출한다.
%LOCALAPPDATA%\agy\bin\agy.exe— 스케줄러 세션의 PATH 를 신뢰하지 않는다. - 작업은 로그인한 사용자 계정으로 실행한다. SYSTEM 계정은
~/.gemini/antigravity-cli/antigravity-oauth-token에 접근할 수 없다. AGY_CLI_DISABLE_AUTO_UPDATE=true를 작업 환경에 설정해 실행 중 자동 업데이트를 막는다.--output-format json을 쓰고stdout만 파싱한다.stderr는 로그로 분리 저장한다.- 종료 코드와
status를 둘 다 검사한다. --print-timeout을 명시한다. 기본 5분은 긴 요약 작업에 부족할 수 있다. 권장10m.--json-schema결과를 맹신하지 않는다. 자체 JSON 추출 + jsonschema 검증을 반드시 통과시킨다.--continue를 쓰지 않는다. 매 실행은 독립적이어야 한다.--dangerously-skip-permissions를 쓰지 않는다. 대신permissions.allow를 최소 범위로 설정한다.--disable-slash-commands를 붙여, 크롤링한 텍스트에 우연히 들어간/명령이 확장되는 것을 막는다.- 호출 횟수를 최소화한다. 첫 호출 오버헤드가 input 28k 토큰이다. 여러 질문을 한 프롬프트로 묶는다.
usage를 매번 로깅하고 일일 토큰 상한을 코드로 강제한다.--log-file로 실행 ID별 로그 경로를 지정한다.- AI 실패가 배치 실패가 되지 않게 한다. agy 가 죽어도 xlsx 리포트는 생성돼야 한다.
- 미인증 감지 시 사용자에게 알린다. 토스트 알림 + 재로그인용 콘솔 창 띄우기 경로를 준비한다.
권장 호출 형태(PowerShell):
$agy = Join-Path $env:LOCALAPPDATA 'agy\bin\agy.exe'
$env:AGY_CLI_DISABLE_AUTO_UPDATE = 'true'
$runId = (Get-Date -Format 'yyyyMMdd_HHmmss')
$logDir = 'D:\workspace\DMF_Crawler\logs'
New-Item -ItemType Directory -Force -Path $logDir | Out-Null
$stdout = Join-Path $logDir "agy_$runId.stdout.json"
$stderr = Join-Path $logDir "agy_$runId.stderr.log"
$args = @(
'-p', (Get-Content -Raw 'D:\workspace\DMF_Crawler\prompts\daily_summary.md'),
'--output-format', 'json',
'--model', 'gemini-3.7-flash-medium',
'--effort', 'medium',
'--print-timeout', '10m',
'--disable-slash-commands',
'--log-file', (Join-Path $logDir "agy_cli_$runId.log")
)
$proc = Start-Process -FilePath $agy -ArgumentList $args -NoNewWindow -Wait -PassThru `
-RedirectStandardOutput $stdout -RedirectStandardError $stderr
if ($proc.ExitCode -ne 0) { throw "agy exited with $($proc.ExitCode). See $stderr" }
$envelope = Get-Content -Raw $stdout | ConvertFrom-Json
if ($envelope.status -ne 'SUCCESS') { throw "agy status=$($envelope.status): $($envelope.error)" }
17. 주변 생태계
npm 레지스트리 검색 결과 — agy 를 감싸는 서드파티 어댑터가 활발하다. 이 프로젝트가 직접 쓰지는 않지만, 호출 규약의 참고 구현으로 가치가 있다.
| 패키지 | 설명 | 최근 게시 |
|---|---|---|
@claudexor/harness-agy |
"Google Antigravity CLI adapter (agy -p --output-format stream-json)" — stream-json 어댑터 참고 구현 |
2026-09-01 |
@aibridge/driver-agy |
Antigravity (agy) CLI driver for aibridge | 2026-08-22 |
dsh-agy-provider |
로컬 인증된 AGY CLI 를 DSH 모델 프로바이더로 노출 | 2026-08-24 |
dsh-agy-link |
thinking, tool activity, token usage 포함 연동 | 2026-08-28 |
dsh-agy |
OAuth 인증 + 멀티 계정 풀 | 2026-08-22 |
agy-auth |
AGY CLI 멀티 계정 관리 도구 | 2026-08-12 |
agy-multi |
멀티 Google 계정 OAuth (login, quota, rotate) | 2026-08-13 |
@anthonyhaussman/opencode-agy-auth |
OpenCode 인증 플러그인 (OAuth, quota, 모델 조회) | 2026-09-02 |
opencode-agy-plugin |
OpenCode 프롬프트를 agy 로 라우팅 | 2026-08-15 |
agy-pi, @bacnh85/pi-agy, @tian.zuo/pi-antigravity |
Pi 코딩 에이전트 브리지 | 2026-08 |
agy-plugin-cc |
Claude Code 에서 agy 를 쓰는 플러그인 설치기 | 2026-08-26 |
n8n-nodes-agy |
n8n 커뮤니티 노드 — agy 명령 실행 통합 (워크플로 자동화 참고) | 2026-08-18 |
@bash0816/agy-termux |
Termux(Android ARM64) 용 agy | 2026-09-01 |
linkgravity |
Discord/Telegram 봇 브리지 (음성 지원) | 2026-08-26 |
시사점: 멀티 계정 로테이션 도구(agy-auth, agy-multi, dsh-agy)가 여럿 존재한다는 것은 쿼터 제약이 실제로 존재하고 사용자들이 부딪히고 있다는 신호다. 이 프로젝트의 일일 토큰 상한 설계는 필수다.
로컬에 등록된 MCP 서버 실측:
NAME TYPE STATUS COMMAND/URL
chrome-devtools stdio enabled npx -y chrome-devtools-mcp@latest --browser-url=http://localhost:9222
data-agent-kit stdio enabled node ...\mcp_proxy_bundle.js dataAgentKit-antigravityide
haramlog-ops stdio enabled node d:\workspace\HaramLog\tools\mcp\haramlog-ops-mcp.mjs
notebooks stdio enabled node ...\mcp_proxy_bundle.js notebooks-antigravityide
unityMCP http enabled http://localhost:8080/mcp
visualization stdio enabled node ...\mcp_proxy_bundle.js visualization-antigravityide
⚠️ 배치 관점 위험: 등록된 MCP 서버는
agy실행 시 함께 기동을 시도한다.chrome-devtools는npx를 호출하고unityMCP는 localhost:8080 을 찾는다. 무인 배치에서 이들이 없으면 기동 지연이나 오류가 날 수 있다. 배치 전용으로 MCP 를 비활성화하는 방안을 검토하라 (agy mcp disable <name>). → 부록 B.
부록 A. 출처 목록
전체 문서 사이드바 목록(향후 참조용): overview, getting-started, install, tutorial, using, features, gcli-migration, prompting, artifacts, conversations, modes, headless, subagents, sandbox, permissions, projects, settings, vim-editor-mode, credits, mcp, plugins, statusline, title, commands/agents, commands/codesearch, commands/credits, commands/diff, commands/permissions, commands/resume, commands/statusline, commands/title, commands/usage, commands/voice, best-practices, troubleshooting, reference
부록 B. 미해결 질문 / 실측 필요 항목
--json-schema의structured_output필드가 어떤 조건에서 채워지는가? 모델별 차이인가, 프롬프트 형식 문제인가? (실측에서 누락됨)- 쿼터 소진 시 정확한
error문자열과 종료 코드는? 감지 로직을 정확히 쓰려면 필요하다./docs/plans확인 필요. agy update의 정확한 동작과 종료 코드. 실행 중 다른 인스턴스가 있으면 어떻게 되는가?- winget 이 작업 스케줄러(사용자 계정 / SYSTEM 계정)에서 동작하는가?
modelProvider: "gemini"+GEMINI_API_KEY경로에서 사용 가능한 모델 목록이 OAuth 경로와 다른가? Claude 모델도 쓸 수 있는가?- 등록된 MCP 서버를 배치 실행에서만 비활성화하는 방법이 있는가? (프로젝트 단위 설정이 없다면 전역 비활성화뿐인가)
--project/--new-project의 정확한 의미와 배치에서의 활용 가치.--sandbox가 Windows 에서 실제로 무엇을 제한하는가?- 첫 호출 input_tokens 28k 의 구성 — 시스템 프롬프트인가 워크스페이스 인덱싱인가? 빈 디렉터리에서 실행하면 줄어드는가? (배치 비용 최적화 직결)
--add-dir로 워크스페이스를 좁히면 토큰 사용량이 감소하는가?- OAuth access_token 만료 주기와 자동 갱신 실패 시 정확한 오류 표면.
conversations/와history.jsonl이 무한히 커지는가? 배치 장기 운영 시 정리 정책 필요.
이 문서는 프로젝트의 SSOT 다. 새로운 사실을 확인하면 여기를 갱신하고, 다른 문서는 여기를 링크로 참조한다.