antony@notes:~/misc$ cat "Gemini-CLI-init-異常延遲重現步驟.md"
Gemini CLI `/init` 異常延遲重現步驟
Gemini CLI /init 異常延遲重現步驟
背景
原始 session 中,執行 /init 後 Gemini CLI 花了約 1 小時 25 分鐘才完成 GEMINI.md 的產出。
從 log 抽出的 tool call 時間戳顯示有兩個明顯卡點:
- 卡點 1:
/init送出 → 第一個 tool call,等了 約 45 分鐘 - 卡點 2:list 根目錄 → list
openspec/specs子目錄,等了 約 31 分鐘
本文件目的是讓問題可被重現,以利後續判斷成因或回報 bug。
環境前置條件
重現前需準備與原情境一致的環境:
- Gemini CLI 版本:0.40.1(stable,2026 年 4 月底發布)
- OpenSpec 版本:1.3.1(2026 年 4 月下旬發布,latest 為當下最新)
- Node.js / npm 已安裝(
openspec需要 Node.js 20.19.0 或更新) - OS:Linux
- 使用者 preference:永遠使用繁體中文回應
若要重新驗證版本:
- Gemini CLI:
gemini /about或gemini --version- OpenSpec:
openspec --version若要強制升級到當下最新 stable:
- Gemini CLI:
npm install -g @google/gemini-cli@latest- OpenSpec:
npm install -g @fission-ai/openspec@latest
一鍵建立 workspace
mkdir -p ~/k8s/workload/graceful-shutdown
sudo npm install -g @fission-ai/openspec
cd ~/k8s/workload/graceful-shutdown
openspec init --tools geminiopenspec init --tools gemini 會自動產出以下結構,內含 .gemini/commands/opsx/ 的 4 個 toml 指令、.gemini/skills/openspec-*/ 的 4 個 SKILL.md,以及 openspec/changes/archive/ 與 openspec/specs/ 兩個空目錄:
graceful-shutdown/
├── .gemini/
│ ├── commands/opsx/
│ │ ├── apply.toml
│ │ ├── archive.toml
│ │ ├── explore.toml
│ │ └── propose.toml
│ └── skills/
│ ├── openspec-apply-change/SKILL.md
│ ├── openspec-archive-change/SKILL.md
│ ├── openspec-explore/SKILL.md
│ └── openspec-propose/SKILL.md
└── openspec/
├── changes/archive/
└── specs/啟動 CLI(建議開啟 debug log + YOLO 模式)
cd ~/k8s/workload/graceful-shutdown
script -q /tmp/gemini-repro.log -c 'gemini --debug --yolo'--debug 在卡住時可以從 log 看出是 retry、thinking、還是在等 API。
--yolo 會自動同意所有 tool 呼叫的確認對話,避免重現過程被 plan / write_file / shell 的確認 prompt 打斷,確保延遲現象來自 Gemini 本身而非「等使用者按 yes」。
script 指令會保留 TTY 讓互動模式正常運作,同時把整個 terminal session 錄到指定檔案。結束時按 Ctrl+D 或輸入 exit。
替代方案:若不需要 log 檔,直接
gemini --debug --yolo即可。互動模式的 log 也會自動寫到~/.gemini/底下,可在 CLI 內輸入/about或/bug查詢確切路徑。
重現步驟
Step 1 — 完整需求
輸入:
/plan 我想搭配 openspec 的流程開發一套 go 語言寫的 http server,這網站要能夠接住 sigint 和 sigterm 的訊號,並執行 graceful shutdown,這網站最終要部署在 K8s 上,並且 CNI 是 cilium 還有啟用 kubeproxy replacement,pod 狀態為 Terminating 的時候,要執行 prestop hook sleep 2s,不要寫在 source code 裡面預期行為:Gemini 進入 Plan Mode,使用
openspec-proposeskill 並輸出計畫摘要。

Step 2 — 確認 plan(第一次)
輸入:
好執行結果:
✦ I have drafted the detailed implementation plan. Please review it below:
1 # Implementation Plan: Graceful Shutdown Go HTTP Server
2
3 ## Background & Motivation
4 The objective is to build a Go-based HTTP server capable of performing a graceful shutdown when receiving `SIGINT` or `SIGTERM` signals. The application
will be deployed on a Kubernetes cluster utilizing the Cilium CNI with kube-proxy replacement. To ensure zero downtime during pod termination, a `preStop`
hook sleeping for 2 seconds must be configured at the deployment level rather than being hardcoded in the application logic. The development process will be
guided by the `openspec` workflow.
5
6 ## Scope & Impact
7 - **Go Application**: Create a basic HTTP server in Go that listens for termination signals and shuts down gracefully using context timeouts.
8 - **Dockerization**: Create a `Dockerfile` to containerize the Go application.
9 - **Kubernetes Manifests**: Create a Deployment and Service manifest. The Deployment must include a `lifecycle.preStop` hook to execute `sleep 2`.
10 - **Process**: Utilize `openspec-propose` to generate standard artifacts (`proposal.md`, `design.md`, `tasks.md`).
11
12 ## Proposed Solution
13 1. **OpenSpec Setup**: Use the `openspec` CLI to scaffold a new change (`graceful-shutdown-go-server`) and generate the required artifacts.
14 2. **Implementation**:
15 - Write `main.go` using `net/http` and `os/signal`.
16 - Create a minimal `Dockerfile` (e.g., multi-stage build starting from `golang:alpine`).
17 - Define `deployment.yaml` with the `preStop` hook (`command: ["/bin/sh", "-c", "sleep 2"]`).
18 3. **Verification**: Confirm the application builds, the Docker image can be created, and the Kubernetes manifests are structurally correct and contain the
requested hooks.
19
20 ## Alternatives Considered
21 - *Hardcoding sleep in Go*: Rejected as per the requirement to handle the delay externally via Kubernetes lifecycle hooks to keep the application code
focused on application-level shutdown logic rather than orchestration-specific workarounds.
22
23 ## Phased Implementation Plan
24 - **Phase 1: OpenSpec Artifacts**: Exit Plan Mode, create the `openspec` change, and let the `openspec-propose` skill generate the documentation artifacts.
25 - **Phase 2: Code Implementation**: Write the Go source code and Dockerfile.
26 - **Phase 3: Kubernetes Manifests**: Write the Deployment and Service configurations, ensuring the `preStop` hook is correctly defined.
27
28 ## Verification
29 - Code review of the Go server to ensure signal handling and context usage.
30 - Verification of the `deployment.yaml` to confirm the presence of the `preStop` hook.
31
32 ## Migration & Rollback
33 - N/A (New deployment).
Does this detailed plan look correct to you? If so, I will proceed to formally submit it for approval so we can begin execution.Step 4 — 要求繁中
請注意永遠必須要使用繁體中文執行結果:
✦ 接下來,我將讀取該變更的狀態,以確定需要產生哪些產出物。
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell openspec status --change "graceful-shutdown-go-server" --json │
│ │
│ ... first 32 lines hidden (Ctrl+O to show) ... │
│ "status": "blocked", │
│ "missingDeps": [ │
│ "design", │
│ "specs" │
│ ] │
│ } │
│ ] │
│ } │
│ Process Group PGID: 5697 │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 根據狀態,我需要先建立 proposal。我會先獲取 proposal 的指令與模板。
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell openspec instructions proposal --change "graceful-shutdown-go-server" --json │
│ │
│ ... first 7 lines hidden (Ctrl+O to show) ... │
│ "instruction": "Create the proposal document that establishes WHY this change is needed.\n\nSections:\n- **Why**: 1-2 sentences on the problem or │
│ opportunity. What problem does this solve? Why now?\n- **What Changes**: Bullet list of changes. Be specific about new capabilities, modifications, or │
│ removals. Mark breaking changes with **BREAKING**.\n- **Capabilities**: Identify which specs will be created or modified:\n - **New Capabilities**: List │
│ capabilities being introduced. Each becomes a new `specs/<name>/spec.md`. Use kebab-case names (e.g., `user-auth`, `data-export`).\n - **Modified │
│ Capabilities**: List existing capabilities whose REQUIREMENTS are changing. Only include if spec-level behavior changes (not just implementation details). │
│ Each needs a delta spec file. Check `openspec/specs/` for existing spec names. Leave empty if no requirement changes.\n- **Impact**: Affected code, APIs, │
│ dependencies, or systems.\n\nIMPORTANT: The Capabilities section is critical. It creates the contract between\nproposal and specs phases. Research │
│ existing specs before filling this in.\nEach capability listed here will need a corresponding spec file.\n\nKeep it concise (1-2 pages). Focus on the │
│ \"why\" not the \"how\" -\nimplementation details belong in design.md.\n\nThis is the foundation - specs, design, and tasks all build on this.\n", │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 我現在來撰寫 proposal.md。
✓ WriteFile proposal.md → Accepted (+24, -0)
1 ## Why
2
3 為了確保部署在 Kubernetes (使用 Cilium CNI 且啟用 kube-proxy replacement) 上的 Go HTTP 伺服器在 Pod 終止過程中不會遺失請求,我們需要實作 Graceful
Shutdown 機制,並搭配 Kubernetes 的 `preStop` hook。這樣可以確保在 Pod 進入 Terminating 狀態後,仍有緩衝時間處理剩餘請求。
4
5 ## What Changes
6
7 - 實作 Go 語言的 HTTP 伺服器,支援監聽 `SIGINT` 與 `SIGTERM` 訊號。
8 - 呼叫 `http.Server.Shutdown()` 方法以優雅地關閉連線。
9 - 提供 `Dockerfile` 用於容器化部署。
10 - 提供 Kubernetes Deployment 與 Service 清單 (Manifests)。
11 - 在 Deployment 中加入 `lifecycle.preStop` hook 執行 `sleep 2`。
12
13 ## Capabilities
14
15 ### New Capabilities
16 - `graceful-shutdown-server`: 提供一個具備訊號監聽與優雅關閉能力的 HTTP 伺服器,並包含 K8s 部署設定。
17
18 ### Modified Capabilities
19 <!-- 無 -->
20
21 ## Impact
22
23 - **應用程式**: 新增 `main.go` 處理伺服器啟動與關閉邏輯。
24 - **基礎設施**: 新增 K8s Deployment 與 Service 設定,影響 Pod 的生命週期管理。
✦ proposal.md 已建立。現在我再次檢查狀態,並獲取 design 的指令。
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell openspec status --change "graceful-shutdown-go-server" --json │
│ │
│ ... first 26 lines hidden (Ctrl+O to show) ... │
│ "status": "blocked", │
│ "missingDeps": [ │
│ "design", │
│ "specs" │
│ ] │
│ } │
│ ] │
│ } │
│ Process Group PGID: 5768 │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 我將先獲取 design 的指令。
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell openspec instructions design --change "graceful-shutdown-go-server" --json │
│ │
│ ... first 13 lines hidden (Ctrl+O to show) ... │
│ "path": "proposal.md", │
│ "description": "Initial proposal document outlining the change" │
│ } │
│ ], │
│ "unlocks": [ │
│ "tasks" │
│ ] │
│ } │
│ Process Group PGID: 5803 │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 現在我來撰寫 design.md。
✓ WriteFile design.md → Accepted (+28, -0)
1 ## Context
2
3 目前需要一個能夠在 Kubernetes 環境中安全退場的 Go 伺服器。由於 Kubernetes 的 Service 負載平衡與 Pod 終止是非同步進行的,若不設定 `preStop` hook 與
Graceful Shutdown,可能會在 Pod 關閉期間漏掉部分請求。
4
5 ## Goals / Non-Goals
6
7 **Goals:**
8 - 實作訊號處理邏輯以支援優雅關閉。
9 - 配置 K8s 生命週期鉤子 (`preStop`)。
10 - 確保程式碼簡潔且符合 Go 最佳實踐。
11
12 **Non-Goals:**
13 - 實作複雜的業務邏輯。
14 - 設定進階的 Cilium 網路政策(僅關注 shutdown 流程)。
15
16 ## Decisions
17
18 - **訊號處理**: 使用 `os/signal` 監聽 `SIGINT` (Ctrl+C) 與 `SIGTERM` (K8s 終止訊號)。
19 - **優雅關閉**: 使用 `http.Server.Shutdown()` 並設定 5-10 秒的超時 context,確保進行中的請求有時間完成。
20 - **Kubernetes 整合**:
21 - 在 Deployment 中加入 `lifecycle.preStop.exec` 執行 `sleep 2`。
22 - 理由:這讓 Cilium CNI 有足夠的時間從 eBPF 表中移除該 Pod 的 IP,避免新的請求進來,而此時應用程式已進入關閉流程。
23 - **容器化**: 使用多階段建置 (multi-stage build) 以縮小映像檔體積並提高安全性。
24
25 ## Risks / Trade-offs
26
27 - **[Risk]**: `preStop` hook 時間過短。 → **Mitigation**: 預設 2 秒符合一般 Cilium 環境下 kube-proxy replacement 的收斂速度。
28 - **[Risk]**: 應用程式關閉時間超過 `terminationGracePeriodSeconds`。 → **Mitigation**: 確保 Go 的 `Shutdown` context timeout 小於 K8s 的預設 30 秒。
✦ design.md 已完成。現在我需要建立 specs。根據 proposal,我定義了一個新能力 graceful-shutdown-server。
我將獲取 specs 的指令。
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell openspec instructions specs --change "graceful-shutdown-go-server" --json │
│ │
│ ... first 13 lines hidden (Ctrl+O to show) ... │
│ "path": "proposal.md", │
│ "description": "Initial proposal document outlining the change" │
│ } │
│ ], │
│ "unlocks": [ │
│ "tasks" │
│ ] │
│ } │
│ Process Group PGID: 5850 │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 我將建立 openspec/changes/graceful-shutdown-go-server/specs/graceful-shutdown-server/spec.md。
✓ WriteFile spec.md → Accepted (+22, -0)
1 ## ADDED Requirements
2
3 ### Requirement: 訊號監聽 (Signal Handling)
4 伺服器必須監聽 `os.Interrupt` (SIGINT) 與 `syscall.SIGTERM` 訊號。
5
6 #### Scenario: 接收到終止訊號
7 - **WHEN** 伺服器接收到 SIGTERM 訊號
8 - **THEN** 伺服器啟動關閉程序並停止接受新請求
9
10 ### Requirement: 優雅關閉 (Graceful Shutdown)
11 伺服器必須在關閉前等待現有連線處理完畢,並設定超時機制。
12
13 #### Scenario: 關閉程序執行
14 - **WHEN** 呼叫 Shutdown 方法
15 - **THEN** 伺服器等待所有作用中請求完成,或直到達到 10 秒超時為止
16
17 ### Requirement: Kubernetes PreStop Hook
18 部署清單必須包含 PreStop 鉤子以延遲應用程式關閉。
19
20 #### Scenario: Pod 進入 Terminating 狀態
21 - **WHEN** Kubernetes 將 Pod 標記為 Terminating
22 - **THEN** PreStop 鉤子執行 `sleep 2`,延遲傳送 SIGTERM 訊號給容器
✦ 現在 proposal, design, specs 都已完成。最後我需要建立 tasks。
我將獲取 tasks 的指令。
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell openspec instructions tasks --change "graceful-shutdown-go-server" --json │
│ │
│ ... first 17 lines hidden (Ctrl+O to show) ... │
│ "id": "design", │
│ "done": true, │
│ "path": "design.md", │
│ "description": "Technical design document with implementation details" │
│ } │
│ ], │
│ "unlocks": [] │
│ } │
│ Process Group PGID: 5894 │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 我將建立 tasks.md。
✓ WriteFile tasks.md → Accepted (+17, -0)
1 ## 1. 專案初始化與 Go 伺服器實作
2
3 - [ ] 1.1 初始化 Go 專案 (`go mod init`)
4 - [ ] 1.2 在 `main.go` 中實作基礎 HTTP 伺服器
5 - [ ] 1.3 實作訊號監聽邏輯 (`SIGINT`, `SIGTERM`)
6 - [ ] 1.4 實作優雅關閉邏輯 (`http.Server.Shutdown`)
7
8 ## 2. 容器化
9
10 - [ ] 2.1 撰寫多階段建置的 `Dockerfile`
11 - [ ] 2.2 測試本地映像檔建置
12
13 ## 3. Kubernetes 部署清單
14
15 - [ ] 3.1 撰寫 Service 清單
16 - [ ] 3.2 撰寫 Deployment 清單,並加入 `lifecycle.preStop` hook 與 `sleep 2`
17 - [ ] 3.3 驗證 Manifests 語法正確性
✦ 所有產出物均已建立。我將檢查最終狀態。
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell openspec status --change "graceful-shutdown-go-server" │
│ │
│ ... first 2 lines hidden (Ctrl+O to show) ... │
│ Progress: 4/4 artifacts complete │
│ │
│ [x] proposal │
│ [x] design │
│ [x] specs │
│ [x] tasks │
│ │
│ All artifacts complete! │
│ Process Group PGID: 5950 │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 所有 OpenSpec 產出物已準備就緒!
- 變更名稱: graceful-shutdown-go-server
- 位置: openspec/changes/graceful-shutdown-go-server/
- 已建立產出物:
- proposal.md: 概述為何需要此變更。
- design.md: 詳述技術決策(訊號處理、K8s Hook、多階段建置)。
- specs/graceful-shutdown-server/spec.md: 定義功能需求與測試情境。
- tasks.md: 實作檢查清單。
準備好開始實作了!
您可以輸入 /opsx:apply 或直接要求我開始執行任務。Step 5 — 觸發 /init(關鍵卡點 1)
這是第一個延遲發生的位置。
在 CLI 輸入:
/initGemini CLI 會將其展開為內建的長 prompt(以「You are an AI agent that brings the power of Gemini directly into the terminal…」開頭),要求模型分析當前目錄並產生 GEMINI.md。
預期觀察:模型可能長時間停留在「Thinking…」狀態而未呼叫任何工具。原 session 此處等了約 45 分鐘。
建議在此設定計時器,若超過 5 分鐘無任何輸出,記錄當下時間。
Step 6 — Tool 執行間卡頓(關鍵卡點 2)
不需輸入任何內容,此為自動發生。
當 Gemini 終於開始動作後,會先 list_directory .,然後嘗試 list_directory openspec/specs。
預期觀察:這兩個 list_directory 呼叫之間可能再次出現長時間靜默。原 session 此處等了約 31 分鐘。
Step 7 — 驗證 CLI 是否還活著
若你想確認 CLI 是否真的卡住而非完成,可在另一個視窗或等到回到 prompt 後輸入:
hello?觀察重點與紀錄
建議用一個簡單表格記錄每次重現的結果:
| 步驟 | 開始時間 | 結束時間 | 耗時 | 備註 |
|---|---|---|---|---|
| Step 1-4(openspec 流程) | ||||
Step 5(/init 送出 → 第一個 tool call) | 卡點 1 | |||
| Step 6(list root → list specs) | 卡點 2 | |||
Step 5-6 總和(/init → 寫完 GEMINI.md) |
對照組建議(強烈建議跑)
為了確認延遲是否與 openspec 流程或累積 context 有關,建議再做以下對照:
對照組 A:空目錄獨立 /init
- 開新空目錄
mkdir /tmp/clean-test && cd /tmp/clean-test - 啟動
gemini --debug - 直接執行
/init - 記錄完成時間
若 A 在數分鐘內完成,而原情境需 1 小時,可確認延遲與「已有檔案的目錄 + 累積 context」相關。
對照組 B:同目錄但全新 session
- 在原本的
graceful-shutdown目錄(已含 openspec 產物) - 開新 session(關閉舊的、重開
gemini) - 直接執行
/init,跳過 Step 1-4 - 記錄完成時間
若 B 比原情境快很多,可確認延遲與「同 session 內累積的 context」相關。
蒐集的資訊(回報 bug 時附上)
執行 /about 取得:
- CLI Version
- Git Commit
- Model(特別注意是不是 Auto / preview 模型)
- Auth Method
- Tier(免費/付費)
並一併附上 /tmp/gemini-repro.log 的 debug log。
啟動 log 已透露的線索
第一次嘗試啟動時,雖然指令寫法錯誤導致 CLI 立即退出,但啟動階段的 debug log 已透露幾個與本案延遲可能相關的訊息,值得在後續分析時納入考量:
Ripgrep is not available. Falling back to GrepTool.此版本未安裝 ripgrep,搜尋將使用較慢的內建 GrepTool。/init需要掃描整個專案目錄,這雖不至於造成小時級延遲,但會放大整體耗時。 v0.40 開始已將 ripgrep bundle 進 SEA 版本,以 npm 安裝可能未包含,可考慮另外安裝ripgrep套件。Experiment flag
45773134 = 300、45773135 = 600數值單位推測為秒,對應 5 分鐘和 10 分鐘,符合常見的 timeout / retry backoff 閾值。若後續 debug log 出現的延遲區間是 5/10 分鐘的倍數,很可能就是這兩個 flag 控制的 retry 行為。Experiment flag
45740200的官方公告 原文(節錄):「We are adding more robust detection of policy-violating use cases and changing how we prioritize traffic. This may result in higher capacity-related errors during periods of high traffic.」 說明 Google 近期正在調整 traffic 優先順序,確實可能讓 capacity-related error 增加。這與「卡點期間其實是 backend 排隊或被節流」的推測相符。 公告連結:https://goo.gle/geminicli-updates
已知相關 issues(供參考)
以下三個 issue 與本案症狀高度相符,截至 v0.40.1(本文件撰寫時的最新 stable)仍為 open,在 v0.39 ~ v0.40 的 changelog 中均未見對應 fix:
- google-gemini/gemini-cli#22141 — Gemini CLI becomes extremely slow (1+ HOURS) / stuck during small code-edit tasks
- google-gemini/gemini-cli#17442 — CLI Agent Intermittent Long Loading Times/Hangs During Tool Execution
- google-gemini/gemini-cli#26126 — Stuck at “Thinking”
另一個與 /init 直接相關但症狀不同的 issue(僅供參考):
- google-gemini/gemini-cli#6984 —
/initcommand hangs at “Concluding the Process”