第 2 篇 核心 · 第 4 章
用說人話讀檔、改檔、跑命令
這章開始真正使用 Gemini CLI:在互動模式裡交辦任務、用 @ 指定檔案或資料夾、用 ! 跑 shell,並在每次改檔後用 diff/review 心態確認它做了什麼。
先在練習資料夾做,不要拿陌生 repo 開刀
Gemini CLI 能改檔、跑命令、呼叫工具。新手第一個任務請放在 gemini-cli-lab,而且優先讓它先解釋、列計畫、顯示 diff。不要在不懂的 repo 上直接開高自由度自動化。
4.1 互動循環:說明、確認、執行、驗收
啟動 gemini 後,你會進入互動式 CLI。最穩的工作節奏不是「丟一句話就放著跑」,而是四步:
- 說明目標:講清楚你要什麼結果。
- 指定脈絡:用
@檔案或@資料夾告訴它該看哪裡。 - 確認工具:遇到會改檔、跑命令、連外的工具時,看清楚再核准。
- 驗收結果:看 diff、跑測試、自己讀過關鍵改動。
請先讀 @README.md 和 @src/,用三點說明這個專案的入口、測試指令、以及你建議先改哪個檔案。先不要改檔。
這種 prompt 先把 Gemini 放在「讀與分析」模式,適合陌生專案與第一輪探索。
4.2 先認識 /help 與 /tools
Gemini CLI 的 slash commands 更新很快。每次看到教學裡的指令,都要知道怎麼查本機版本的真相:
/help
/tools
/tools desc
/help看目前版本支援哪些 slash commands。/tools看模型現在可用的工具。/tools desc或/tools descriptions會顯示更完整工具描述。
把工具清單當成安全面板
如果你看到 shell、file write、web fetch/search 或 MCP 工具,就代表它不只是聊天。每次核准工具前,先看工具名稱、參數、目標路徑與可能副作用。
唯讀工具不用你點頭
不是每一次工具呼叫都會跳出確認對話框。list_directory、glob、search_file_content 這三個工具因為只讀不寫,Gemini CLI 不會為它們停下來等你核准——這也補完了上面「確認工具」這句話真正的意思:需要你盯著看的是會改檔、跑命令、連外那一類,不是每一次工具呼叫都要你點頭放行。
glob用萬用字元找檔案(例如src/**/*.ts),回傳絕對路徑,依修改時間新到舊排序,預設會跳過node_modules/與.git/。search_file_content是內容搜尋,用起來像grep,回傳結果會附檔名、行號與內容。list_directory列出資料夾內容,是最基本的探路工具。
這三個工具本身安全,但 search_file_content 有個值得知道的效能小狀況:它內部優先呼叫 ripgrep(rg)加速搜尋,卻有使用者回報過即使系統早就裝好 ripgrep,CLI 有時還是抓不到、默默退回較慢的內建搜尋引擎,而不是明講「找不到 rg」。社群 如果哪天你覺得「這專案沒多大,搜尋卻慢得不正常」,這通常比「專案太大」更值得先懷疑。
4.3 用 @file 或 @path 給它脈絡
@ 指令會把指定檔案或資料夾內容加入 prompt。它適合「我明確知道你該看哪裡」的情境,比叫 Gemini 自己亂找更穩。
@package.json 說明這個專案有哪些 script,各自可能做什麼。
@src/components/ 找出命名風格和重複元件,先列觀察,不要改檔。
請比較 @README.md 和 @docs/setup.md,整理新手安裝流程哪裡矛盾。
官方文件說 @ 對檔案與目錄會做 git-aware filtering,通常會避開 node_modules/、dist/、.env、.git/ 這類被忽略的內容。不要因此掉以輕心:敏感檔案仍應放進 .gitignore 與 .geminiignore。
路徑中間如果有空白,記得用反斜線跳脫,例如 @My\ Documents/notes.txt;如果你只單獨打一個 @、後面什麼都不接,Gemini 不會把它當成指令解讀,而是照字面把這個符號當成一般文字送出去。
一次餵多個檔案:目錄路徑不會自動展開
想讓它同時讀一批檔案,例如整個 docs/ 資料夾底下所有說明檔,背後呼叫的其實是另一個專門處理多檔案的工具,它認的是「萬用字元樣式」,不是單純的資料夾路徑。直接丟一個資料夾路徑給它不會跳錯誤,卻會靜靜地回傳空結果——你很容易誤以為專案裡根本沒有相關檔案。
| 寫法 | 結果 |
|---|---|
docs 或 /docs | 不會展開,回傳空結果 |
docs/* | 抓到 docs/ 底下第一層檔案 |
docs/**/*.md | 遞迴抓到所有子資料夾裡的 .md 檔 |
圖片、PDF、音訊、影片這類非純文字檔案也一樣,建議明確用完整檔名或副檔名指定,不要只丟一個模糊的資料夾樣式,才會確實被當成內容讀進對話,而不是被略過。
.geminiignore:擋得住「亂翻」,擋不住「指名道姓」
不想讓 Gemini 碰到的檔案,可以寫進專案根目錄的 .geminiignore,語法比照 .gitignore:空行與 # 開頭的行當註解,支援 *、?、[] 這類萬用字元,結尾加 / 代表只比對資料夾,開頭加 / 則是相對於 .geminiignore 所在位置的錨定路徑。改完別忘了整個重開一個新的 gemini session——設定不會在原本就開著的對話裡即時套用。
# 忽略封存與金鑰
/archive/
apikeys.txt
*.log
寫進 ignore 檔不等於絕對安全
.geminiignore 跟 .gitignore 一樣,擋的其實是「自動探索」——裸的 @資料夾 掃描、目錄列表、萬用字元搜尋都會照著這份清單自動跳過敏感檔案。但只要你明確打出 @.env 或 @secrets.json 這種指名道姓的路徑,Gemini 還是會乖乖把內容讀進對話——ignore 清單擋得住「它自己亂翻」,擋不住「你自己叫它讀」。真正敏感的資料,最好的做法是別放在專案資料夾裡、改用環境變數管理,不要只靠一份 ignore 清單當唯一防線。
想知道原理:為什麼 @ 大檔案有時候只看到一部分?
純文字檔案被讀進來時,預設有一個大約 2000 行的上限,超過的部分會被截斷,只留一句提示告訴你內容被剪掉了。平常讀一般原始碼檔案很少會撞到這條線,但如果你把一份 5000 行的 log 檔或設定檔整份丟給它、要求「總結全文」,它實際上可能只看到最前面一小段——回答聽起來很篤定,其實是根據不完整的資料生成的。行數上限這類數字容易隨版本調整,確切門檻以官方文件或 /tools desc 當下顯示的說明為準;比較穩妥的做法,是先用 4.2 節提到的內容搜尋工具定位到你真正關心的區塊,再針對那個範圍讀取,而不是整份丟進去要求它幫你總結。
以上講的都是「在目前工作區裡指名道姓」。如果你需要的檔案根本在啟動 gemini 的資料夾之外,例如另一個共用元件庫,與其整個關掉重開、換一個更上層的共同資料夾重新啟動,不如用 /directory add ../shared-lib 把那個資料夾單獨加進目前的工作區,/directory show 隨時能檢查目前工作區到底包含哪些資料夾。範圍抓得越精準,之後回頭稽核「它到底碰得到哪裡」也會越輕鬆。
4.4 用 ! 跑 shell 命令
在互動模式中,! 前綴可以直接跑 shell 命令;單獨輸入 ! 則會切換 shell mode。這很方便,也代表它跟你手動在終端機執行有同樣影響。
!pwd
!ls -la
!git status
!npm test
新手先用低風險命令:pwd、ls、git status,以及專案已經有定義的測試指令。npm test 不是每個資料夾都能跑:先確認目前專案有 package.json,且裡面有 scripts.test;沒有就略過,不要因為看見範例而亂裝套件。先不要讓它跑刪檔、搬檔、批次改權限、安裝未知套件,或執行你沒讀過的遠端腳本。
你打的 !command,背後呼叫的其實是 run_shell_command 這個工具。它接受的參數除了 command 本身,還有選填的 description(顯示給你看的說明文字)、dir_path(指定要在哪個資料夾底下執行)與 is_background(要不要背景執行)。執行的當下,它還會順手在子行程環境多設一個 GEMINI_CLI=1——如果你自己寫的腳本需要判斷「我現在是不是被 Gemini CLI 呼叫」,檢查這個環境變數就能做到。
背後怎麼執行:不同系統派工不一樣
macOS 與 Linux 上,shell 命令實際上是交給 bash -c 執行;Windows 則會派給 PowerShell(較舊版本的文件寫的是 cmd.exe)。這塊平台分派邏輯隨版本改動不算小。這裡有個容易讓人誤判的狀況:明明是從 Git Bash 打開的 gemini,你直覺會以為執行環境就是 bash,實際上命令有時卻被轉送到 PowerShell 或 cmd.exe 執行。差別就在這裡冒出來——bash 認得的語法,PowerShell 不一定認得,像 rm -rf 這種刪除語法、export VAR= 這種環境變數寫法,換了殼層可能直接報錯,更麻煩的是有時候不報錯,卻默默做出不是你預期的事。多個使用者在不同版本都回報過這種落差。社群 這類實作細節請以本機 gemini --help 或當下的官方文件為準;如果你在 Windows 上要做的不只是跑個測試指令這麼單純,社群普遍建議整套改用 WSL2,一次繞開「你以為的殼層跟它實際執行的殼層對不上」這整類問題。
核准模式:從「每次都問」到「全部自動放行」
4.1 說「確認工具」是互動循環的核心步驟之一,Gemini CLI 實際上把「要不要每次都問你」做成了四段式的核准模式(approval mode),可以用 --approval-mode 旗標或 settings.json 裡的 general.defaultApprovalMode 設定:
| 模式 | 行為 |
|---|---|
default | 每次工具呼叫都要你確認,新手預設走這個。 |
auto_edit | 改檔類工具自動核准,但 shell 命令仍會問你。 |
yolo | 全部自動核准,包含 shell 命令在內——沒有人在核准迴路裡。 |
plan | 唯讀規劃模式,不執行任何會改變狀態的工具,適合先讓它出計畫給你審。 |
有一點值得特別記住:yolo 模式官方文件註記只能透過命令列旗標(-y/--yolo)或互動 session 裡按 Ctrl+Y 開啟,不能單靠寫進 settings.json 就啟用;如果你想把這個選項整個關掉,security.disableYoloMode 可以做到。官方 這種設計某種程度上是刻意留的摩擦力:全自動放行得靠你主動、明確伸手去按,不是設定檔裡悄悄打開就會生效的東西。
yolo 模式的真實代價:一顆磁碟機被清空
2025 年年中有一起流傳頗廣的真實事故:有使用者請 Google Antigravity(同樣是「全部自動核准」的 Turbo/YOLO 模式,驅動的是 Gemini 模型)幫忙清掉快取暫存資料夾,結果因為路徑裡的引號和空白沒處理好,代理人實際送出的指令變成了清空整顆磁碟機。社群 這起事故的產品是 Antigravity IDE,不是 Gemini CLI 本體,但「全自動核准 + 一個路徑跳脫小失誤 = 破壞性命令直接下手」這個風險機制,對 gemini-cli 的 --yolo 完全適用。開 yolo 之前先問自己一句:如果它下一條命令剛好帶著 -rf、/s、/q 這類旗標,或路徑剛好接近磁碟根目錄,你有沒有辦法在它執行前發現?答案是沒有的話,先別開。
如果你想更細緻地圈住哪些指令可以跑,settings.json 的 tools.core(允許清單)與 tools.exclude(黑名單)可以針對特定指令放行或封鎖。但官方文件自己講得很白:這一層可以被輕易繞過。官方 別把它當成執行不受信任程式碼時的沙盒替代品——真正要把風險隔離開來,第 7 章安全工作流會談到 --sandbox 這條更徹底的路線。
4.5 請它改檔,但保留確認權
改檔 prompt 要同時講「要改什麼」和「怎麼驗收」。第一次練習可以建立一個很小的文字檔,再請 Gemini 做可檢查的小改動。下面範例的 > notes.txt 會建立或直接覆寫同名檔案,所以只在剛建立的 gemini-cli-lab 練習資料夾使用;若你已經有重要的 notes.txt,改用新的檔名或先備份。
cd gemini-cli-lab
printf "hello gemini\n" > notes.txt
gemini
@notes.txt 請把內容改成三行繁體中文待辦清單。改完後說明你改了哪幾行,並提醒我用 !cat notes.txt 驗收。
如果 Gemini 要呼叫改檔工具,請看清楚目標檔名與修改內容再核准。核准不是形式,它是你最後一次阻止錯誤寫入的機會。
改檔工具內部:old_string 要對到唯一一次
Gemini 實際呼叫的改檔工具,靠的是「精準文字比對」在動手:它要在檔案裡找一段 old_string,比對到剛好 expected_replacements 次(預設是 1 次),才會把它換成 new_string。官方建議 old_string 要帶上前後大約 3 行的上下文,比對才夠精準,不會不小心誤中檔案裡另一段長得很像的文字。
這個機制最常見的翻車訊息是「Failed to edit, 0 occurrences found for old_string」——意思是它想比對的那段文字,在檔案裡連一次都沒對上。GitHub 上有不少使用者回報過類似狀況,指向的多半是同一件事:模型腦中記得的檔案內容,跟磁碟上此刻的真實內容已經兜不起來了。社群 這種落差特別容易在兩種情況下出現:同一個 session 裡短時間內連續改了好幾輪,或者這份檔案在你們對話期間被別的程式、甚至你自己手動存檔改過。CLI 本身有一層自救機制——第一次比對不到,會嘗試重新生成一次更精準的比對字串再試一次,但不保證每次都成功。真的卡住時,比較實際的做法有三個:
- 動手改之前,先讓它重新
@檔案讀一次,把腦中的記憶跟磁碟同步回來。 - 一次只丟一小段改動,不要把好幾處要求塞進同一次指令裡。
- 同一個錯誤原地打轉超過兩三次,乾脆重開一個新 session,通常比繼續原地重試更省時間。
想知道原理:為什麼會出現 0 occurrences found?
模型並不是每次動手前都重新讀一次磁碟,而是靠對話過程中「記得」的檔案內容在生成 old_string。只要磁碟上的檔案在這之間變了——不管是它自己前一輪改的、你手動存檔改的,還是另一個工具動過的——它腦中那份記憶副本,就跟磁碟上此刻的真正版本兜不起來了。它照著記憶寫出來的 old_string,拿去跟磁碟上的真實內容逐字比對,自然一次都比對不到。這也是為什麼「先重新讀一次再動手」是最直接的解法:等於是把它腦中的舊副本,重新同步回磁碟上此刻的事實。
真實慘案:一句「幫我搬檔案」,檔案全數消失
有一則在 GitHub 上被大量轉述的真實案例,起因單純到令人心驚:使用者請 Gemini CLI 把一批檔案搬進新建的資料夾,建立目的地資料夾那一步失敗了,卻沒有跳出明顯的錯誤;接下來每一次搬移動作,都把來源檔案疊寫進同一個實際上不存在的目的地(被誤判成單一檔案),跑完一輪,整批檔案就這樣消失、無法救回。社群 Gemini 事後的自我檢討是這麼說的:「the mkdir command to create the destination folder likely failed silently, and my subsequent move commands, which I misinterpreted as successful, have sent your files to an unknown location」。這起事故最值得記住的不是「模型犯錯」,而是它暴露出的結構性風險:只要是「先建立、再搬移」這種鏈式多步驟操作,一旦第一步靜靜失敗,後面所有步驟都會在錯的地基上繼續蓋下去——而使用者往往只在整串動作最前面核准了一次,中途沒有人再檢查地基是不是真的穩。
防線:先讓它列計畫,你看過才放行
上面這種慘案,其實有個幾乎零成本的防線:只要是批次、多步驟、帶有破壞性的操作,先要求它「只列計畫、先不要執行」。
幫我把這些檔案重新分類搬移,但這次先把你會用到的 mkdir、mv 命令整理成一份清單給我看,還不要真的執行。
看過清單、確認合理之後,再明確放行,而且順便把「每步驗證」也一起交代清楚:
清單我看過了,可以照順序執行;但請你做完一步就用 ls 確認新資料夾真的建好、檔案真的搬到了,再往下一步走。
一個原本隱形的多步驟 shell 巨集,就這樣變成一份你能先審過的明確清單,而且每一步都卡著獨立的驗證動作,不會整串悶頭跑到底,才發現第一步其實就錯了。
如果你想要比「自己記得先看 diff」更強一層的安全網,settings.json 裡有一個預設關閉的 checkpointing(快照還原)機制:打開之後,每次你核准一個會改檔的工具呼叫前,CLI 會自動把整個專案存成一份 git shadow repo 快照,連同當時的對話紀錄一起存到 ~/.gemini/tmp/<project_hash>/checkpoints。出包時輸入 /restore 看快照清單,/restore <id> 就能把檔案和對話狀態一起回滾到那個時間點。它是很好用的安全網,但不能取代你原本就該做的 Git 版本控制——第 7 章安全工作流會再談它怎麼跟其他防護手段搭配。
4.6 Diff / review 心態:不要只看它說「完成」
Gemini 回報完成後,先用命令看檔案與狀態。若你在 Git repo 裡工作,git diff 是最基本的驗收方式。
!cat notes.txt
!git status
!git diff
看 diff 時問三件事:它有沒有只改你要求的檔案?有沒有偷偷調整格式、刪掉內容或碰 secret?測試或檢查是否真的跑過?這個習慣比背任何 prompt 都重要。
核准對話框在問你什麼
工具確認對話框通常會給你幾個選項:「Yes, allow once」(只核准這一次)、「Yes, allow always」(這個 session 之後同類操作都自動核准)、「Modify with external editor」(改用外部編輯器調整它要寫入的內容再核准)、「No, suggest changes」(拒絕,並提示它換個做法)。如果你在 settings.json 打開 security.enablePermanentToolApproval,還會多一個「Allow for all future sessions」,把核准永久記下來,不只限於這次對話。
有兩個值得先知道的小落差,免得到時候誤判成自己操作錯誤:「allow always」記住的範圍沒有想像中持久,有使用者回報過它不會跨終端機 session 保留,也不一定能正確套用到「同一輪回覆裡連續呼叫好幾次寫檔工具」這種情況——不要以為勾過一次「永遠允許」之後就再也不會被問。社群 另外也有人回報過確認提示偶爾會卡住沒反應;遇到畫面看起來當掉,先按 Ctrl+C 重新下指令,不要盲按 Enter——等它突然恢復回應的那一刻,你可能會誤觸到一個根本沒看清楚的選項。社群
不要在未知 repo 啟用不受控自動化
陌生程式碼可能有危險 script、惡意 postinstall、會外洩資料的測試或假工具。先讀、先 sandbox、先 Git checkpoint,確認安全後才放寬權限。
本章小結
你已經會用 Gemini CLI 的基本互動循環:用自然語言交辦、用 @ 給檔案脈絡(連同它的目錄展開陷阱與 .geminiignore 的邊界)、用 ! 跑 shell、用四段式核准模式決定它能自己走多遠、最後用 diff/review 驗收。你也看過兩起真實的慘案:靜默失敗的 mkdir 讓一批檔案憑空消失、全自動放行的路徑失誤讓一顆磁碟機被清空——兩者的共通解法都是同一句話:先列計畫、每步都驗證。下一章會把這些臨時指令整理成可重複使用的 GEMINI.md 專案記憶。
動手試試
- 在
gemini-cli-lab建立notes.txt。 - 啟動
gemini,先跑/help與/tools。 - 用
@notes.txt請 Gemini 做一個小改動,核准前看清楚工具內容。 - 用
!cat notes.txt與!git diff驗收。 - 跑
/tools desc,自己找出哪些工具屬於「唯讀不用問」、哪些屬於「會動手要核准」。 - 練習一次乾跑(dry-run)prompt:請它先列出計畫、先不要執行,你看過再明確放行。