CLI
cd1b45c2d(버전 0.67.0-nightly)입니다.이 커밋의 README는 무료 등급과 Google One 사용자에 대해 2026년 6월 18일부로 Gemini CLI가 Antigravity CLI로 대체되었다고 안내하고, 최신 Gemini 모델에는 최적화되어 있지 않다고 밝힙니다. 그래도 저장소는 계속 갱신되고(매일 nightly 배포), 구조 자체는 다른 에이전트 CLI를 읽는 좋은 교재입니다. 실사용 전에는 본인 계정 등급에 어떤 안내가 적용되는지 공지 링크로 확인하세요.
gemini-cli는 터미널에서 gemini를 치면 뜨는 대화형 코딩 에이전트로, 모델 호출·도구 실행·권한 확인·확장 로딩을 한 프로그램에 묶어 둔 npm 패키지(@google/gemini-cli)입니다. 같은 엔진을 gemini -p "질문" 같은 비대화형 모드로도 쓸 수 있어 스크립트와 CI에 끼우기도 쉽습니다.
README가 내세우는 쓰임은 세 가지입니다. 큰 코드베이스를 질문·수정하기, 이미지나 PDF에서 앱 초안 만들기, PR 조회나 리베이스 같은 운영 작업 자동화입니다. MCP 서버를 붙이면 이미지·영상 생성 같은 외부 능력도 같은 대화에서 부릅니다.
모델은 "무엇을 하면 좋겠다"고 제안하는 비서입니다. 실제로 파일을 지우거나 명령을 돌리는 손은 별도의 도구 계층이 맡고, 그 앞에는 "이건 물어보고, 이건 바로 허용, 이건 금지"를 적은 규칙(정책 엔진)이 서 있습니다.
이 저장소를 읽는 재미는 모델 호출 코드가 아니라 이 경비 규칙과 도구 계층이 얼마나 촘촘하게 나뉘어 있는지에 있습니다.
# 설치 없이 실행
npx @google/gemini-cli
# 전역 설치 (README 기준: npm / Homebrew / MacPorts / conda 환경 안의 npm)
npm install -g @google/gemini-cli
brew install gemini-cli
# 대화형 시작, 비대화형 질의, 파이프 입력
gemini
gemini -p "summarize README.md"
cat logs.txt | gemini
릴리스 채널은 latest(매주 화요일 UTC 20:00 안정판), preview(화요일 UTC 23:59), nightly(매일 UTC 00:00)로 나뉘며 각각 npm install -g @google/gemini-cli@preview처럼 태그로 받습니다.
인증은 README가 세 가지를 안내합니다. Google 계정 로그인(OAuth), GEMINI_API_KEY, Vertex AI입니다. 조직 유료 라이선스는 GOOGLE_CLOUD_PROJECT 설정이 필요하다고 적혀 있습니다.
트렌딩 이유를 저장소가 직접 말해 주지는 않으므로, 소스에서 확인되는 특징을 근거로 세 가지를 짚습니다. 순위 자체는 TrendShift 모멘텀 점수일 뿐 품질 평가가 아닙니다.
| 특징 | 근거(저장소 안) | 의미 |
|---|---|---|
| 완전한 오픈소스 | LICENSE Apache-2.0, 모든 소스 파일 머리에 SPDX 헤더 | 에이전트 CLI의 내부를 통째로 읽고 포크할 수 있음 |
| 확장 지점이 많음 | MCP, Extensions, Skills, Hooks, Subagents, 커스텀 슬래시 명령(docs/ 하위 문서) | 코드를 안 고치고 행동을 바꿀 길이 여러 개 |
| 권한 모델이 코드화됨 | packages/core/src/policy/ 와 policies/*.toml | "무엇을 물어볼지"가 TOML 규칙으로 선언됨 |
| OS별 샌드박스 | core/src/sandbox/{linux,macos,windows} | 셸 명령을 가두는 구현이 플랫폼마다 따로 존재 |
| 비대화형·임베딩 | nonInteractiveCli.ts, packages/sdk, packages/a2a-server | 터미널 밖(스크립트, 다른 앱, 에이전트 간 통신)에서도 쓰기 위한 패키지 |
이 사이트에는 같은 분류의 openai/codex, anthropics/claude-code, opencode 딥다이브도 있습니다. 공통 골격(에이전트 루프, 도구, 권한, 컨텍스트 파일)은 같고, 다른 점은 기본 모델 계열과 컨텍스트 파일 이름(GEMINI.md)입니다. 세부 기능 우열은 각 저장소가 빠르게 바뀌므로 이 문서에서는 판정하지 않습니다.
README는 "최신 모델에는 최적화되어 있지 않다"고 밝힙니다. 모델 선택 문서(docs/cli/model.md)는 Auto 모드가 Gemini 3 계열 또는 2.5 계열 중 하나를 고르는 구조로 설명합니다. 어떤 모델이 실제로 열리는지는 시점과 계정에 따라 다를 수 있습니다.
추적 파일 약 3,036개 중 TypeScript(.ts) 1,774개, TSX(.tsx) 420개로 코드의 대부분이 TypeScript입니다. 나머지는 문서 168개(.md), 스냅샷 120개, 아이콘 98개(.svg) 등이고, 테스트 관련 파일이 1,300개 남짓이라 코드 못지않게 검증 자산이 큽니다(파일명에 test가 들어간 수 기준).
| 층 | 기술 | 확인한 위치 |
|---|---|---|
| 런타임 | Node.js 20 이상, ESM("type":"module") | 루트 package.json engines |
| 언어·빌드 | TypeScript 5.8.3, esbuild 번들링, npm workspaces | package.json, esbuild.config.js |
| 터미널 UI | React + Ink (터미널에 React 컴포넌트를 그리는 라이브러리) | GEMINI.md, packages/cli/src/ui/ |
| 모델 SDK | @google/genai 1.30.0 | packages/cli/package.json |
| 도구 확장 | @modelcontextprotocol/sdk 1.23.0, @agentclientprotocol/sdk 0.16.1, @a2a-js/sdk | cli·core package.json |
| 관측성 | OpenTelemetry(trace·metrics·logs 다수 exporter), Google Cloud Logging | packages/core/package.json |
| 테스트 | Vitest 3.2.4, 통합 테스트·evals·memory-tests·perf-tests 별도 디렉터리 | 루트 스크립트와 폴더 |
| 샌드박스 | Linux bubblewrap(bwrapArgsBuilder), macOS seatbelt, Windows C# 헬퍼(GeminiSandbox.cs), 컨테이너 이미지 Docker/Podman | core/src/sandbox/, Dockerfile |
| 설정·정책 형식 | JSON 설정 + JSON Schema, 정책은 TOML(@iarna/toml) | schemas/settings.schema.json, policy/toml-loader.ts |
백엔드 서버는 없습니다. 모델 호출은 사용자 PC에서 Google API로 직접 나가며, 로그인 토큰과 API 키는 keychainService.ts, fileKeychain.ts, apiKeyCredentialStorage.ts 같은 파일이 저장·조회를 맡습니다(파일 이름으로 확인한 구조이고 저장 위치 세부는 읽지 않았습니다).
루트 GEMINI.md는 구조를 이렇게 설명합니다. packages/cli는 사용자와 맞닿는 터미널 UI·입력 처리, packages/core는 Gemini API 호출·프롬프트 조립·도구 실행을 맡습니다. 나머지 패키지(a2a-server, sdk, devtools, vscode-ide-companion, test-utils)는 이 두뇌를 다른 방식으로 쓰기 위한 껍데기입니다.
client.ts의 GeminiClient.sendMessageStream()은 비동기 제너레이터입니다. 호출되면 먼저 루프 감지기를 리셋하고, 훅이 켜져 있으면 BeforeAgent 훅을 실행합니다. 훅이 실행을 멈추거나 막을 수 있고, 추가 문맥을 <hook_context> 태그로 요청에 덧붙일 수도 있습니다. 그 뒤 processTurn()이 컨텍스트 압축(tryCompressChat)을 시도하고 Turn.run()으로 모델 응답을 스트리밍합니다.
스트림 이벤트는 core/turn.ts의 GeminiEventType으로 정의됩니다. 내용(content), 생각(thought), 도구 호출 요청, 압축 완료(chat_compressed), 루프 감지(loop_detected), 재시도(retry), 컨텍스트 창 초과 예고(context_window_will_overflow) 등 18개 안팎입니다. UI는 이 이벤트를 받아 그릴 뿐이라 같은 두뇌를 다른 화면에 붙이기 쉽습니다.
모델이 도구 호출을 요청하면 scheduler/scheduler.ts(1,018줄)의 Scheduler 클래스가 큐로 받아 처리합니다. _processNextItem 안의 순서가 이 저장소에서 가장 읽을 가치가 큰 부분입니다.
BeforeTool)이 인자를 고쳐 쓸 수 있습니다. 고쳐졌다면 호출 객체의 인자와 invocation이 교체됩니다.checkPolicy()가 정책 엔진에서 ALLOW / ASK_USER / DENY 중 하나를 얻습니다. 훅이 ask를 돌려주면 ASK_USER로 강제됩니다.hasTaintedOrBuildFileRisk)이 감지된 호출은 ALLOW였어도 대화형이면 확인을 요구하고, 비대화형이면 아예 DENY로 바꿉니다.DENY면 오류 응답을 만들어 모델에게 돌려주고, ASK_USER면 확인 루프에서 사용자 응답(ToolConfirmationOutcome)을 기다립니다.# packages/core/src/policy/policies/write.toml 의 규칙 모양 (발췌)
[[rule]]
toolName = "replace" # 파일 수정 도구
decision = "ask_user" # 기본: 물어본다
priority = 10
interactive = true
[[rule]]
toolName = "replace"
decision = "allow"
priority = 15
modes = ["autoEdit"] # auto-edit 모드에서는 허용
정책 파일 머리말 주석이 우선순위 규칙을 설명합니다. 높은 숫자가 이기고, 계층은 기본 < 확장 < 워크스페이스 < 사용자 < 관리자 순으로 정수부가 1~5로 나뉩니다(예: 기본 계층 우선순위 100은 1.100, 사용자 계층은 4.x). 그래서 조직 관리자가 정한 규칙을 개인 설정이 뒤집지 못합니다. 승인 모드는 ApprovalMode 열거형의 default, autoEdit, yolo, plan 네 가지이고, policies/ 폴더에는 read-only.toml, write.toml, plan.toml, yolo.toml, sandbox-default.toml 등이 모드별로 나뉘어 있습니다.
규칙이 여러 겹인 사무실 출입증 시스템과 같습니다. 건물 기본 규칙 위에 부서 규칙, 개인 규칙이 덧씌워지되, 보안팀(관리자) 규칙이 항상 최종 결정권을 갖습니다.
core/src/routing/modelRouterService.ts는 전략 목록을 구성해 순서대로 시도합니다. 코드에서 확인되는 전략은 Fallback, Override, ApprovalMode, Default, Classifier, NumericalClassifier, GemmaClassifier이고, CompositeStrategy가 이를 묶습니다. 결과는 사용할 모델 문자열과 source, latencyMs, reasoning을 담은 메타데이터입니다. 쉬운 질문은 작은 모델, 어려운 계획은 큰 모델로 보내는 "Auto" 선택이 이 층에서 일어납니다(docs/cli/model-routing.md).
| 확장점 | 무엇을 바꾸나 | 코드·문서 위치 |
|---|---|---|
컨텍스트 파일 GEMINI.md | 프로젝트 지침을 매 요청에 포함. 전역(~/.gemini/GEMINI.md) → 워크스페이스 → 필요 시 로딩(JIT) 순 | docs/cli/gemini-md.md, tools/jit-context.ts |
| MCP 서버 | 외부 도구·리소스 추가 | core/src/tools/mcp-client*.ts, core/src/mcp/ (OAuth 포함) |
| Skills | 필요할 때 불러오는 작업 지침 묶음 | core/src/skills/skillLoader.ts, activate-skill.ts |
| Hooks | 에이전트 생명주기의 정해진 지점에서 외부 스크립트 실행 (SessionStart, BeforeModel, BeforeTool, AfterTool, PreCompress 등) | core/src/hooks/, docs/hooks/ |
| Subagents / Extensions | 전문 하위 에이전트를 도구처럼 호출 / 위 요소들을 패키지로 설치 | core/src/agents/, cli/src/config/extension-manager.ts |
서브에이전트는 "메인 에이전트에게 도구 이름으로 노출"됩니다. agents/에는 codebase-investigator.ts, generalist-agent.ts, cli-help-agent.ts, 브라우저를 조작하는 browser/ 하위 폴더, 원격 에이전트(remote-invocation.ts, a2a-client-manager.ts) 구현이 보입니다. 서브에이전트는 자체 시스템 프롬프트와 독립된 컨텍스트 창을 가져 메인 대화의 토큰을 아낍니다(docs/core/subagents.md).
sandboxManagerFactory.ts가 OS별 구현을 고릅니다. macOS는 seatbelt 프로필(baseProfile.ts, seatbeltArgsBuilder.ts), Linux는 bubblewrap 인자 빌더, Windows는 C# 헬퍼가 있습니다. 컨테이너 방식은 --sandbox 플래그와 GEMINI_SANDBOX 환경변수로 켭니다(docs/cli/sandbox.md, 루트 Dockerfile).trustedFolders.ts와 --skip-trust 플래그가 낯선 폴더의 설정·훅 자동 실행을 막는 용도로 보입니다.services/environmentSanitization.ts(자식 프로세스로 넘기는 환경에서 민감값을 거르는 것으로 읽히지만 세부 규칙은 확인하지 않음).loopDetectionService.ts가 같은 호출을 반복하는 상황을 찾고, 이벤트 loop_detected로 UI에 알립니다.파일 수는 테스트 파일(*.test.ts)을 뺀 .ts/.tsx 기준으로 cli 558, core 466, a2a-server 21, sdk 11, devtools 5, vscode-ide-companion 6입니다. 테스트가 소스 옆에 나란히 있는 구조라 읽을 때 테스트 파일이 함수 사용 예시 역할을 합니다.
| 순서 | 파일 | 볼 것 |
|---|---|---|
| 1 | packages/cli/src/gemini.tsx | main()(467행~)이 설정 로딩·샌드박스 재실행·UI/비대화형 분기를 하는 방식 |
| 2 | packages/core/src/core/client.ts | sendMessageStream → processTurn → 압축 |
| 3 | packages/core/src/core/turn.ts | 이벤트 종류와 도구 호출 요청 수집 |
| 4 | packages/core/src/scheduler/scheduler.ts | 도구 호출 큐·정책·확인 |
| 5 | packages/core/src/policy/policies/*.toml | 모드별 기본 규칙 |
| 6 | packages/core/src/tools/shell.ts | 셸 도구(1,314줄)와 명령 안전 검사 |
async *sendMessageStream이 이벤트를 yield하고 UI가 소비하는 방식은 대화형 UI, 비대화형 출력, SDK가 같은 엔진을 공유하게 하는 핵심 설계입니다. nonInteractiveCli.ts와 interactiveCli.tsx를 나란히 열어 같은 이벤트를 어떻게 다르게 처리하는지 비교해 보세요.
"어떤 도구를 어떤 모드에서 허용할지"를 선언형 규칙과 우선순위 계층으로 풀었습니다. 내 도구에 권한 확인을 붙일 때 if 문을 흩뿌리는 대신 규칙 테이블로 모으는 설계 연습이 됩니다. 테스트 policy-engine.test.ts와 shell-safety.test.ts가 경계 사례를 보여줍니다.
tryCompressChat, context_window_will_overflow 이벤트, chatRecordingService(대화 기록), tokenLimits.ts가 모여 긴 세션을 유지하는 방법을 보여줍니다. 대화 되감기(docs/cli/rewind.md)와 체크포인트(checkpointing.md) 문서도 같은 문제의 사용자 쪽 모습입니다.
npm workspaces, esbuild 번들(esbuild.config.js), 단위 테스트, 통합 테스트(샌드박스 none/docker/podman 변형), 행동 평가(evals), 메모리·성능 기준선(test:memory, test:perf)까지 갖춘 CI 구성이 한 곳에 있습니다. 루트 package.json의 scripts가 목차 역할을 합니다.
에이전트 CLI에서 어려운 부분은 모델 호출이 아니라 "도구 실행 전에 누가 무엇을 허락하는가"이고, 이 저장소는 그 답을 정책 엔진·훅·샌드박스 세 겹으로 코드에 남겨 두었습니다.
docs/get-started/installation.mdx의 권장 사양을 옮깁니다.
| 항목 | 내용 |
|---|---|
| OS | macOS 15 이상, Windows 11 24H2 이상, Ubuntu 20.04 이상 |
| 메모리 | 가벼운 사용 4GB 이상, 긴 세션·큰 코드베이스 16GB 이상 권장 |
| 런타임 | Node.js 20.0.0 이상 (개발 시 20.19 안팎 권장은 GEMINI.md) |
| 네트워크 | 모델 호출을 위해 인터넷 필요. 인증은 Google 로그인, API 키, Vertex AI 중 선택 |
| 샌드박스(선택) | GEMINI_SANDBOX=true|docker|podman|sandbox-exec|runsc|lxc (docs/cli/sandbox.md). Docker/Podman을 쓰려면 컨테이너 엔진이 필요 |
--approval-mode=yolo는 모든 도구를 묻지 않고 허용합니다(--yolo 플래그는 문서에서 deprecated로 표시). 처음 열어 보는 저장소에서는 폴더 신뢰 대화상자에서 "Don't trust"를 고르면 제한된 안전 모드로 동작하고, 선택은 ~/.gemini/trustedFolders.json에 저장됩니다. 낯선 코드베이스에서는 기본 모드와 샌드박스를 함께 쓰는 편이 안전합니다.
소스를 직접 빌드하려면 npm install 뒤 npm run build, 실행은 npm run start입니다(GEMINI.md). 이 분석은 어떤 빌드나 테스트도 실행하지 않고 코드를 읽기만 했습니다.
npx @google/gemini-cli -p "이 폴더의 파일 구조를 3줄로 요약해줘"
cat package.json | gemini -p "의존성 중 눈에 띄는 것 3개를 골라 이유를 설명해줘"
목표: 대화형 모드와 -p 모드의 차이를 체감하고, 파이프 입력이 프롬프트에 붙는 방식을 확인합니다.
연습용 저장소 루트에 GEMINI.md를 만들어 "답변은 한국어로, 변경 전 항상 계획을 먼저 말할 것" 같은 지침을 넣고 같은 질문을 지침 유무로 비교합니다. 로딩 순서(전역 → 워크스페이스 → JIT)는 docs/cli/gemini-md.md와 대조합니다.
gemini --approval-mode plan # 읽기 전용 계획 모드
gemini --approval-mode auto_edit # 파일 수정은 자동 승인
gemini --approval-mode default # 수정마다 확인
같은 요청("README 오탈자 고쳐줘")을 세 모드로 실행해 확인 대화상자가 언제 뜨는지 기록합니다. 그다음 policies/write.toml, plan.toml의 규칙과 관찰 결과를 대조하세요. 연습은 반드시 버려도 되는 저장소에서 합니다.
docs/hooks/writing-hooks.md를 따라 BeforeTool 훅 스크립트를 만들고, 셸 도구 호출 인자에 rm -rf가 있으면 차단하게 해 봅니다. 훅 이벤트 표(docs/hooks/index.md)와 scheduler.ts의 훅 처리 코드(인자 수정, ask 결정)를 함께 읽으면 어디에 끼어드는지 보입니다.
코드를 실행하지 않고, 사용자가 "파일 하나 고쳐줘"라고 입력한 순간부터 replace 도구가 실행되기까지의 호출 경로를 gemini.tsx → client.ts → turn.ts → scheduler.ts → tools/edit.ts 순으로 따라가며 함수 이름과 줄 번호를 표로 정리합니다. 막히는 곳은 같은 이름의 *.test.ts가 호출 예시를 보여줍니다.
| 주차 | 주제 | 할 일 |
|---|---|---|
| 1주 | 사용자로 익히기 | 설치, 인증, docs/cli/tutorials/의 파일 관리·셸·웹 도구 튜토리얼 따라 하기 |
| 2주 | 컨텍스트와 확장 | GEMINI.md, 커스텀 슬래시 명령(docs/cli/custom-commands.md), Skills 만들기 |
| 3주 | MCP | docs/tools/mcp-server.md와 gemini mcp 명령으로 서버 하나 연결, 직접 만든 간단 서버 붙이기 |
| 4주 | 안전 모델 | 승인 모드, 정책 TOML, 폴더 신뢰, 샌드박스 비교 |
| 5주 | 코드 읽기 | 4장의 흐름을 따라 client → turn → scheduler 정독, 테스트로 동작 확인 |
| 6주 | 임베딩·확장 개발 | packages/sdk로 프로그램에서 호출, Extension 패키징(docs/extensions/writing-extensions.md) |
비교 학습으로 이 사이트의 openai/codex, anthropics/claude-code 딥다이브를 같은 질문("도구 실행 전 권한은 누가 정하나")으로 읽으면 설계 차이가 선명해집니다.
| 용어 | 뜻 |
|---|---|
| GEMINI.md | 프로젝트·전역 지침을 담아 모든 요청에 붙이는 컨텍스트 파일 |
| MCP | Model Context Protocol. 외부 도구와 데이터를 에이전트에 연결하는 표준 규약 |
| ACP / A2A | 편집기와 에이전트(ACP), 에이전트끼리(A2A) 통신하는 규약. 각각 cli/src/acp, packages/a2a-server가 관련 코드 |
| 승인 모드 | default, autoEdit, yolo, plan — 도구 호출을 얼마나 묻는지 정함 |
| 정책 엔진 | 도구 호출을 ALLOW / ASK_USER / DENY 중 하나로 판정하는 규칙 평가기 |
| Hook | 에이전트 생명주기 지점에서 실행되는 사용자 스크립트 |
| Skill | 필요할 때 활성화해 읽는 작업별 지침 묶음 |
| Subagent | 독립된 프롬프트·도구·컨텍스트를 가진 하위 에이전트. 도구 이름으로 호출 |
| Extension | 프롬프트·MCP·명령·테마·훅·스킬을 묶어 설치하는 패키지 |
| 샌드박스 | 셸 명령과 파일 접근을 제한된 환경에 가두는 장치(seatbelt, bubblewrap, 컨테이너 등) |
| 컨텍스트 압축 | 대화가 길어졌을 때 요약해 창을 비우는 동작(tryCompressChat) |
| nightly / preview / latest | 매일 / 매주 화요일 사전판 / 매주 화요일 안정판 배포 채널 |