![]() |
| 選擇手動使用 VSIX 安裝延伸套件 |
![]() |
| 建議選擇之前的版本為主版本 (用可能會需要DBG的最早的版本為優) |
![]() |
| 右下角會顯示進度 ETA 是剩多久 但由於中間有大量跳過的檔案 也有大型文字檔 所以並不準確 一般大概就是 7-10分鐘 左右 |
![]() |
| 4x% 附近會卡一下 要有耐心 |
![]() |
| 多次嘗試 大概都是七分多左右會好 (以Cathaya 專案為例 不同專案當然不同結果) |
Search 標記的文字 Ctrl-Alt-S
專案簡介
VSsearch 是一個專為大型 Git 倉庫(特別是 UEFI / BIOS / 韌體專案)設計的 離線全文搜尋引擎。它將每個倉庫索引成三個獨立的 SQLite 檔案 —— meta.db(路徑與雜湊)、text.db(FTS5 trigram 文字倒排索引)、 bin.db(FTS5 over hex,選配)—— 並在內容讀取之前就透過 副檔名路由、內容嗅探、中段 Shannon 熵值三層閘門決定該檔走 text、bin、both 還是跳過。
設計目標是讓一台沒有伺服器、沒有網路的開發機, 在不到一秒內跨越上萬個檔案查到任意關鍵字,同時仍能跟上 Git 的分支與 commit 變動。
--as-text / --as-binary 強制覆寫。--git > 環境變數 VSS_GIT > vss.config.json > PortableGit 預設 > PATH。技術選擇與設計理由
每個關鍵設計決策背後都有具體理由。以下是 VSsearch 的選擇及被淘汰的替代方案。
1. SQLite FTS5 + Trigram tokenizer
| 選項 | 評估 |
|---|---|
| SQLite FTS5 + trigram ← 採用 | 單檔、零伺服器、Python 內建、trigram 模式下任意子字串查詢都可走倒排索引。WAL 模式讓並行讀寫不衝突。 |
| Elasticsearch / OpenSearch | 需 JVM、記憶體佔用 1–2 GB、需維運 cluster。每個倉庫額外起一個伺服器不現實。 |
| Whoosh / Tantivy | Whoosh 寫入慢;Tantivy 需 Rust toolchain,Python binding 非原生,且不內建 trigram。 |
| Lucene (PyLucene) | 需 JVM,安裝複雜;查詢快但部署門檻過高。 |
| 直接用 ripgrep | 每次查詢都掃整個 disk。30k 檔 / 2 GB 純文字一般要 5–8 秒,無法快取。 |
EFI_STATUS、gBS->LocateProtocol 這種包含底線、箭頭、大小寫混雜的形式。詞彙 tokenizer 會把它們切成 EFI+STATUS,導致查不到原串。Trigram(3 字元滑動窗)能讓任意長度 ≥ 3 的子字串都走索引。2. 三檔分離 (meta / text / bin)
- 關注點分離:不同資料的生命週期不同。meta 幾乎不變;text 隨原始碼變;bin 只在 firmware 重新編譯時變。分開可以只重建需要的那個。
- 按需部署:只要文字查詢?只需釋出
meta + text,二進位備份可獨立排除。 - 並行寫入:FTS5 trigram 寫入成本高。拆成兩個不同 DB 並行寫入避免 BUSY 鎖定。
- ATTACH 重組:SQLite 原生支援
ATTACH DATABASE,查詢時能把 Main + Minor 的三檔同時掛起來走 SQL UNION,不需手動合併。
3. 中段 Shannon 熵值過濾
| 選項 | 評估 |
|---|---|
| Mid-sample Shannon (1–3 KiB) ← chosen | 微量讀取(1 次 seek + 1 KiB read)就能辨別壓縮/加密/韌體 blob。原始碼熵值 < 5,壓縮接近 8.0,門檻 7.2 安全切割。 |
| 只看副檔名 | 適用一般專案,但 EDK2 裡許多 .bin 是小 ASCII 表;.dat 也雙面性。單靠副檔名會誤判。 |
| 全檔讀取統計 | 準確但慢。50 MB 全讀需 200–500 ms。中段抽樣誤判率 < 0.5%,但快 50×。 |
| 首 8 KiB 嗅探 | 頭部會說謊。許多 firmware blob 前 4 KiB 是結構化 header;中段抽樣才看到真正 payload。 |
4. Git blob SHA 作為變更訊號
- 零讀檔 skip:git 已為每個追蹤檔案算了 SHA-1 (或 SHA-256)。
git ls-tree一句搞定。與上次 SHA 一致則內容未變、可跳過所有讀取與雜湊。 - 比 mtime 可靠:mtime 在
git checkout、git stash pop、雲端同步後都會變,但內容用 SHA 識別才是準的。mtime 僅作為 SHA 不可用時的 fallback。 - 比 BLAKE2b 快:BLAKE2b 7–8 GB/s 已經很快,但仍需讀全檔;SHA-skip 是「根本不讀」。零 IO 永遠贏快 IO。
5. ThreadPoolExecutor + 單一 writer thread
- SQLite 寫入是序列化的。多個 connection 同時寫入會 BUSY。並行讀檔 + 序列寫入是唯一能同時遮掩 IO 並避免鎖競爭的架構。
- 為什麼不用 multiprocessing?Python GIL 在 IO 與 SQLite C-extension 中都會釋放,讀檔 + decode + hash 實際上能並行。multiprocessing 反而要 pickle 每個 byte buffer,會是淨退步。
6. PyInstaller --onefile 單 EXE 部署
- 現場零依賴:封閉網路、公司 build server 不一定有 Python。單 EXE 是唯一能 copy 即用的形式。
- git 不被打包是有意為之:git 自身是個生態(credential helper / hooks / submodule),固定一份反而脆弱。預設偵測 PortableGit + 5 級覆寫更穩健。
優點與限制
主要優點
- 零伺服器、零網路:查詢 100% 本機;企業防火牆內可用。
- 狀態可攜帶:
.vssearch/可隨 ZIP 帶走、可被 patch。 - Git-aware 增量:SHA-skip 讓「重建」在無變動時為數秒達成。
- Trigram 子字串:詞彙 tokenizer 查不到的
EFI_、->Pcd、__attribute__都能命中。 - 能查 binary:HEX 模式能在韌體 image 裡查 byte sequence。
- 分支差異儲存:Minor 只記 diff;100 個分支不會 100× 儲存。
- 可設定的 git 路徑:5 層解析適合多 git 安裝環境(PortableGit / Cygwin / msys)。
已知限制
- 不是即時 watcher:變更要跑
vss-build minor才進索引。可用 git hooks 自動化,但不是 inotify。 - 查詢長度 < 3 無法走 trigram:FTS5 trigram 最小單位 3 字元。「if」「At」這類查詢退為慢的 LIKE 掃描。
- FTS5 文字索引體積大:~2 GB 原始碼產 ~1.4 GB 的 text.db,約原始碼 70%。
- 需要 git:SHA-skip 與分支意識依賴 git。非 Git 倉庫需手動 main 快照模式。
- 僅 Windows EXE:本倉隱含 PyInstaller 設定為 Windows;Linux/macOS 用戶請直接跑 Python 原始碼。
工具比較
在 ~30k 檔 / ~2 GB 原始碼倉庫上,每個工具的實際型態:
| 工具 | 建立成本 | 查詢時間 | 適合場景 | 不適合場景 |
|---|---|---|---|---|
| VSsearch | ~390 s 首次 < 5 s 增量 | 200–900 ms | 重複查詢同倉庫、跨分支、binary HEX | 只查一次的場景 |
ripgrep (rg) | 0 | 5–8 s | 一次性、未知倉庫、regex | 緊密查詢、binary、無分支概念 |
| git grep | 0 | 2–6 s | 指定 commit 查詢 | 跨 commit、binary、不能跨倉庫 |
| VS Code 全文搜尋 | 0 (背景 ripgrep) | 5–10 s | 編輯時隨手查 | 含二進位的 firmware repo 會凍死、不能腳本化 |
| ctags / cscope | 1–3 min | < 50 ms | 定義 / 引用跳轉 | 只能查符號,不能查任意子串、跨 commit 弱 |
| Elasticsearch / OpenSearch | 1–3 hr 含部署 | 50–150 ms | 多人共用、多倉庫、需 ranking | 個人機、離線、企業防火牆 |
| Sourcegraph | 需 Docker / k8s | 50–200 ms | 多倉庫、code intelligence | 離線個人機、無企業部署 |
| Hound (etsy) | ~5 min | 100–300 ms | 多倉庫 regex | 無分支、無 binary、無增量 |
| Zoekt | ~10 min | < 100 ms | 多倉庫 trigram、高 QPS | 使用門檻高、無 binary、需 Go runtime |
系統架構
三層架構:CLI 介面層 → 核心引擎層(vss/) → SQLite 儲存層(三檔分離)。
模組職責
| 模組 | 職責 |
|---|---|
vss/indexer.py | 主建立流程:列舉 → 分發 → 處理 → 寫入。包含 build_main / build_minor / build_minor_for_ref 與 BuildStats。 |
vss/routing.py | 決定每個檔案要走 text、bin、both 還是 skip。包含 RoutingConfig、Router、預設副檔名表。 |
vss/entropy.py | 中段樣本 + Shannon 熵值;用於識別韌體 blob 或壓縮檔。 |
vss/gitinfo.py | git wrapper:head_sha、ls_tree_at、diff_name_only、CatFileBatch。可設定 git 執行檔路徑。 |
vss/db.py | SQLite schema、ATTACH 配置、FTS5 trigram 虛擬表、checkpoint。 |
vss/search.py | 查詢入口:8 種模式、後置篩選器、Main+Minor 合併。 |
vss/extract.py | 解碼文字內容、產生 HEX 字串。 |
vss/config.py | JSON 設定載入;定義 Config 與預設值。 |
vss/hooks.py | git hook 安裝(post-checkout / post-merge 自動重建 Minor)。 |
cli/vss_build.py | 建立 CLI:main / minor / clean / chain / promote / install-hooks。 |
cli/vss_search.py | 查詢 CLI:模式、篩選、JSON 輸出。 |
索引演算法
建立流程分為四個階段:列舉、預過濾、處理、寫入。多個 worker 並行讀檔與雜湊,單一 writer thread 序列化寫入 SQLite,避免鎖競爭。
git ls-tree(main)或 git diff(minor)取得檔案清單與 blob SHA。skipped_unchanged,零次讀檔。max_index_mb 即跳過。檔案路由
每個檔案會被路由到下列四種目的之一:
| Route | 含義 | 儲存 |
|---|---|---|
| text | 純文字內容 | *_text.db (FTS5) |
| bin | 二進位 / HEX 索引 | *_bin.db (FTS5 over hex) |
| both | 同時索引文字與 HEX | 兩邊 |
| skip | 完全不索引 | — |
Decision order
- 手動 glob 覆寫:
--as-text/--as-binary - 副檔名白名單:
text_exts/binary_exts/both_exts - 內容嗅探:讀取首 8 KiB;含 NUL 或 < 85% 文字位元組則視為 binary
- 預設:text
.fd / .fv / .efi / .rom / .bin 直接走 bin 路由;--no-bin 進一步把 bin 路由改成 skip,得到「只有文字」的 DB。熵值過濾器
對 1 MB 以上檔案,從中段抽樣計算 Shannon 熵值;高熵內容(壓縮 / 加密 / 韌體 blob)通常 > 7.95,原始碼 < 5。預設門檻 7.2。
| 檔案大小 | 樣本大小 |
|---|---|
| ≤ 1 MB | 不檢查(首 8 KiB 嗅探已夠) |
| 1 MB < size ≤ 10 MB | 1024 bytes |
| 10 MB < size ≤ 20 MB | 2048 bytes |
| > 20 MB | 3072 bytes |
Skip reasons
size:NMB— 檔案大小超過max_index_mb(預設 50)entropy:X.XX— 中段熵值高於門檻mid-binary— 中段樣本含 NUL byte(二進位)routed:skip— 路由決定跳過(如--no-bin下的二進位副檔名)
分層索引
使用 Main + Minor 兩層架構:Main 是完整 release 快照,Minor 只儲存與 Main 的差異。查詢時兩者合併,Minor 優先。
files# <repo>/.vssearch/ main_manual_af0ec2c_af0ec2c_meta.db # paths, hashes, route main_manual_af0ec2c_af0ec2c_text.db # FTS5 trigram (text) main_manual_af0ec2c_af0ec2c_bin.db # FTS5 over hex (omitted with --no-bin) minor_dev_7dcdc85_meta.db # delta vs MainDB (current branch) minor_dev_7dcdc85_text.db minor_dev_7dcdc85_bin.db
查詢時 search 模組將 Main 與當前分支的 Minor 透過 ATTACH DATABASE 同時開啟,在 SQL 層做 UNION 與 dedup(Minor 優先)。
建立流程
搜尋流程
基本用法
vss-build <subcommand> [options] / vss-search QUERY [options]vss-build subcommands
| cmd | 用途 |
|---|---|
main | 建立完整 MainDB(指定 release commit) |
minor | 為當前分支建立 MinorDB(與 Main 的差異) |
chain | 為所有本地分支建立 MinorDB |
promote | 把 MinorDB 合併進新的 MainDB 快照 |
clean | 刪除舊的 MinorDB(保留最近 N 個) |
install-hooks | 安裝 git hook 自動重建 MinorDB |
vss-search modes
| --mode | 說明 |
|---|---|
exact | 完全比對(預設) |
prefix | 前綴比對 foo* |
substr | 子字串(trigram 加速) |
fuzzy | 編輯距離模糊比對 |
fuzzysub | 子字串 + 模糊 |
glob | SQL GLOB 萬用字元 |
hex | HEX byte 序列(查 bin DB) |
ext | 列出特定副檔名的檔案 |
參數列表
vss-build
| flag | 類型 | 說明 |
|---|---|---|
--repo | path | 倉庫根目錄(預設:cwd) |
--release | str | main 用,指定 release commit SHA 或 ref |
--config | path | vss.config.json |
--db-dir | path | DB 輸出目錄(覆寫 config) |
--workers | int | worker 執行緒數(0 = auto) |
--no-bin | flag | 不建立 bin DB |
--ext-text .X | list | 追加 text 路由副檔名 |
--ext-binary .X | list | 追加 binary 路由副檔名 |
--as-text GLOB | list | 強制 glob 走 text |
--as-binary GLOB | list | 強制 glob 走 binary |
--max-index-mb N | int | 硬性大小上限(預設 50;0 取消) |
--entropy-threshold X | float | 熵值門檻(預設 7.2) |
--no-entropy-check | flag | 關閉熵值/中段過濾 |
--list-skipped | flag | 列印所有跳過的檔案路徑 |
--profile NAME | str | 套用副檔名 profile(如 c, py) |
--git PATH | str | 覆寫 git 執行檔路徑 |
--quiet | flag | 關閉進度輸出 |
vss-search
| flag | 類型 | 說明 |
|---|---|---|
QUERY | str | 搜尋字串(--mode ext 可省略) |
--mode | enum | exact / prefix / substr / fuzzy / fuzzysub / glob / hex / ext |
--ext .c .h | list | 副檔名篩選 |
--path GLOB | str | 路徑 glob 篩選 |
--exclude GLOB | str | 排除 glob |
--limit N | int | 最多回傳筆數(預設 500) |
--max-dist 0~3 | int | fuzzy 最大編輯距離 |
--case-sensitive | flag | 區分大小寫 |
--branch NAME | str | 指定分支(覆寫當前分支) |
--json | flag | 輸出 JSON |
--git PATH | str | 覆寫 git 執行檔路徑 |
使用範例
建立 MainDB(純文字)
PowerShell$REPO = "e:\Git\Cathaya\Cathaya_GC" $BUILD = "e:\Git\repository\VSsearchExtension\dist\vss-build.exe" $H = (& 'E:\Git\PortableGit\bin\git.exe' -C $REPO rev-parse HEAD).Trim() & $BUILD main --repo $REPO --release $H --no-bin --list-skipped
建立完整索引(text + bin)
cmdvss-build.exe main --repo e:\Git\Cathaya\Cathaya_GC --release 7dcdc854b分支 MinorDB
PowerShell& $BUILD minor --repo $REPO & $BUILD chain --repo $REPO # every local branch
查詢(多種模式)
PowerShell$SEARCH = "e:\Git\repository\VSsearchExtension\dist\vss-search.exe" # Exact (default) & $SEARCH EFI_STATUS --repo $REPO --limit 5 # Substring & $SEARCH "gBS->LocateProtocol" --mode substr --repo $REPO # Fuzzy with edit distance 1, restrict to .c / .h & $SEARCH "PcdMximumLinkedListLength" --mode fuzzy --max-dist 1 --ext .c .h --repo $REPO # HEX byte sequence (queries bin DB) & $SEARCH "55 AA" --mode hex --repo $REPO # Glob & $SEARCH "Init*Pcd*" --mode glob --repo $REPO # Path filter + exclude & $SEARCH EFI_STATUS --path "AmiNetworkPkg/**" --exclude "**/test/**" --repo $REPO # Tighter entropy / smaller cap & $BUILD main --repo $REPO --release $H --max-index-mb 20 --entropy-threshold 6.5
真實效能
| 指標 | 數值(Cathaya_GC) |
|---|---|
| total_seen | 29,567 |
| indexed | 29,075 |
| routed-skip (binary ext) | 492 |
| entropy / size / mid-binary skips | 0 (--no-bin already filters) |
| wall time (text only) | ~390 s (Python) / ~530 s (EXE) |
| text.db size | 1,365 MB |
| meta.db size | 8.4 MB |
| EFI_STATUS substr | 350 ms (py) / 905 ms (exe) |
| PcdMaximumLinkedListLength substr | 215 ms (py) / 710 ms (exe) |
設定檔
vss.config.json 放在倉庫根目錄;可選。
vss.config.json{ "db_dir": ".vssearch", "workers": 0, "git_executable": "E:\\Git\\PortableGit\\bin\\git.exe", "release_regex": "^release\\s+\\w{5}(?:\\d{2}[AB]|\\d{3})$", "branch_pins": { "dev": "main" }, "routing": { "text_exts": [".c", ".h", ".inf", ".dec", ".dsc"], "binary_exts": [".fd", ".fv", ".efi"], "max_index_mb": 50, "entropy_threshold": 7.2, "entropy_check_enabled": true }, "extension_profiles": { "c": [".c", ".h", ".cpp", ".hpp"], "py": [".py", ".pyi"] } }
git path resolution order
--git PATHCLI 旗標VSS_GIT環境變數vss.config.json:git_executableE:\Git\PortableGit\bin\git.exe(若存在)git(PATH 查找)
VS Code 擴充套件
vscode-extension/ 將 VSsearch 整合進 VS Code 側邊面板,提供搜尋表單、結果樹、資料庫管理檢視,並支援切換分支時自動建立 MinorDB。 擴充套件本身用 TypeScript 撰寫,後端則透過 JSON-RPC over stdio 與一個 長駐的 Python sidecar(vss-server.exe)溝通。
| 元件 | 職責 |
|---|---|
extension.ts | 啟用、命令註冊、Webview / Tree 註冊 |
server.ts | spawn sidecar、JSON-RPC client、pending-id Map、自動重啟 |
searchProvider.ts | 查詢分派 + 結果快取 |
resultsTree.ts | TreeDataProvider(File→Hit 或扁平) |
indexer.ts | build/clean/delete + DB 列表 |
gitWatcher.ts | 監看 .git/HEAD、debounced 自動建 MinorDB |
cli/vss_server.py | JSON-RPC 主迴圈、進度通知 |
JSON-RPC 長駐伺服器
每個工作區資料夾啟動一個 vss-server.exe 子行程,透過 stdin/stdout 傳輸 line-delimited JSON-RPC。一筆請求 {"id":N,"method":"search","params":{...}},回應 {"id":N,"result":...};長時間操作(buildMain / buildMinor)以 {"id":N,"progress":{...}} 推送進度。
為何採用「長駐」而非「一次一進程」
| 成本 | 一次一進程 | 長駐 sidecar |
|---|---|---|
| EXE 解壓 (PyInstaller --onefile) | ~400 ms / call | 啟動一次 |
| Python interpreter 啟動 | ~150 ms / call | 一次 |
| SQLite open + FTS5 mmap | ~80 ms / call | 保持開啟 |
| git cat-file 子行程 | 每次重啟 | --batch 常駐 |
| 查詢快取 (LRU) | 無 | 命中重複查詢 |
實測:第二次查詢同一字串可從 ~700 ms 降至 <30 ms。切換分支後的增量重建因為 git cat-file 已就緒,省下每檔 ~10 ms 的 fork 成本,在 29k 檔倉庫累積為數百毫秒。
RPC 方法總覽
| method | 說明 |
|---|---|
init | 設定 repo 路徑、回傳 git 資訊 |
search | 主要查詢(mode / ext / max_hits …) |
build_main / build_minor | 建立索引(含 progress) |
list_dbs | 列出 main / minor / branch 各層 |
delete_tier / clean_minors / clear_cache | 維護操作 |
git_info | 驗證 git 可用 |
shutdown | 乾淨關閉 |
演算法流程
- 啟動:擴充套件 activate → 找到工作區根目錄 → spawn
vss-server.exe→ 等待{"id":0,"ready":true}。 - 初始化:呼叫
init,sidecar 載入vss.ini、解析 PortableGit、開啟現有 DBs。 - 查詢:使用者按
Ctrl+Alt+F→ webview 送search→searchProvider合併預設選項 → sidecar FTS5 查詢 → 串流回 hits →resultsTree建立 File→Hit 樹。 - 跳轉:點擊 hit →
vscode.open打開檔案至指定行;或在 Search Editor 模式下,使用 VS Code 內建 search-result 語法做原生點擊。 - 分支切換:
FileSystemWatcher偵測.git/HEAD變動 → debounce 300 ms → 靜默呼叫build_minor→ 進度只寫到 OutputChannel,不打擾使用者。 - 關閉:deactivate → 送
shutdown→ 等 sidecar 結束 → 若 5 秒未結束則 kill。
檔案結構
擴充套件原始碼
treeVSsearchExtension/ ├─ cli/ │ ├─ vss_build.py # build CLI │ ├─ vss_search.py # search CLI │ ├─ vss_gui.py # Tk GUI front-end │ └─ vss_server.py # JSON-RPC sidecar (NEW) ├─ vss/ # core engine package ├─ vscode-extension/ │ ├─ src/ │ │ ├─ extension.ts # activate, commands, webviews │ │ ├─ server.ts # spawn sidecar, JSON-RPC client │ │ ├─ searchProvider.ts │ │ ├─ resultsTree.ts │ │ ├─ searchEditor.ts │ │ ├─ indexer.ts │ │ ├─ gitWatcher.ts │ │ ├─ config.ts │ │ └─ types.ts │ ├─ bin/ │ │ └─ vss-server.exe # bundled by _packExt.bat │ ├─ out/ # tsc output (generated) │ ├─ package.json # manifest, commands, settings │ ├─ tsconfig.json │ ├─ INSTALL.md # EN install guide │ ├─ INSTALL_tw.md # 中文安裝指南 │ └─ README.md ├─ dist/ │ ├─ vss-build.exe │ ├─ vss-search.exe │ ├─ vss-server.exe │ └─ vssearch-0.2.0.vsix # final extension package ├─ _pack.bat # PyInstaller build (CLIs + sidecar) └─ _packExt.bat # copy EXE + tsc + vsce package
資料庫位置(重要)
<repo-root>\.vssearch\,不可改放他處。每個工作區資料夾擁有獨立的 sidecar 與獨立的 .vssearch。tree<repo-root>/.vssearch/ ├─ main/ # full-history tier per release commit ├─ minor/ # incremental tiers on top of main ├─ branch/ # per-branch tiers (auto-built on branch switch) └─ cache/ # transient query cache
記得加進 .gitignore:
.gitignore/.vssearch/安裝說明
需求
- VS Code ≥ 1.85.0
- Git(PATH 或
vss.ini中的 PortableGit 路徑) - Windows x64(內建 sidecar 為 EXE;Linux/macOS 改用
vssearch.pythonPath)
安裝預先建置的 .vsix
pwshcode --install-extension dist\vssearch-0.2.0.vsix從原始碼建置
pwshcd e:\Git\repository\VSsearchExtension _pack.bat # dist\vss-build.exe / vss-search.exe / vss-server.exe _packExt.bat # copy EXE -> bin\, tsc -p ., vsce package -> dist\vssearch-*.vsix
首次使用
- 開啟一個 Git 工作目錄
- 點擊活動列的 VSsearch 圖示(Search / Results / Databases 三檢視)
- 執行
VSsearch: Build Main DB(必要的一次性步驟) - 按
Ctrl+Alt+F搜尋
命令一覽(v0.2.0)
| 命令 | 用途 |
|---|---|
VSsearch: Search | 開啟搜尋面板(Ctrl+Alt+F) |
VSsearch: Search Selection | 以編輯器選取文字搜尋(Ctrl+Alt+S) |
VSsearch: Build Main / Minor DB | 建立完整或增量索引 |
VSsearch: Clean Old Minors... | 保留最新 N 個 minor,清除其餘 |
VSsearch: Delete Tier | 刪除單一層級(在 Databases 視圖右鍵) |
VSsearch: Refresh Databases | 重新列出 Databases 視圖 |
VSsearch: Open Last Result in Editor | 以 Search Editor 顯示最近一次結果 |
VSsearch: Clear Query Cache | 清除 sidecar 的查詢快取 |
VSsearch: Show Git Info | 將 branch / HEAD / git 路徑印至 Output |
VSsearch: Reveal Database Folder | 在系統檔案總管開啟 <repo>\.vssearch\ |
VSsearch: Export Last Results... | 將目前結果匯出為 .json / .csv |
VSsearch: Dump Diagnostics | 開啟 JSON 文件,含版本、設定、DB 列表 |
VSsearch: Reset First-Run Prompt | 重新啟用首次「立即建置?」提示 |
VSsearch: Restart Server | 重新啟動 Python sidecar |
VSsearch: Wipe Local Index (.vssearch) | 停止 sidecar、刪除 <repo>\.vssearch\、重新啟動 |
VSsearch: Uninstall (Wipe Index + Remove Extension) | 清除索引並執行 uninstallExtension kvh.vssearch |
常見問題
| 症狀 | 解法 |
|---|---|
| "git executable not found" | 設定 VSS_GIT 或在 vss.ini 設 PortableGit;詳見下方「Git 找不到」食譜 |
| 結果為空且無錯誤 | 先執行 Build Main DB |
| sidecar 持續重啟 | 看 Output → VSsearch 的 stderr |
| 分支切換後結果過時 | 執行 Build Minor DB 或等待 watcher |
| 想完全清除索引 | 刪除 <repo>\.vssearch\ |
「Git 找不到」食譜
sidecar 每次建索引 / 搜尋都會呼叫 git。解析順序(先中先贏):
- VS Code 設定
vssearch.gitExecutable - 環境變數
$VSS_GIT vss.ini→[git] executable(硬覆寫)vss.ini→[git] portable_default(僅當檔案存在時採用)git從PATH
A. 針對單一工作區 — VS Code 設定(最簡單)
.vscode/settings.json{ "vssearch.gitExecutable": "E:\\Git\\PortableGit\\bin\\git.exe" }
然後執行 VSsearch: Restart Server.
B. 機器全域 — 在 sidecar 旁邊放 vss.ini
內建 sidecar 位於 %USERPROFILE%\.vscode\extensions\kvh.vssearch-<ver>\bin\,在同一資料夾內新增 vss.ini:
vss.ini[git] executable = E:\Git\PortableGit\bin\git.exe ; or: only used as fallback when 'executable' is empty AND the file exists portable_default = E:\Git\PortableGit\bin\git.exe
C. 使用者層環境變數
pwsh[Environment]::SetEnvironmentVariable('VSS_GIT', 'E:\Git\PortableGit\bin\git.exe', 'User')關閉並重新開啟 VS Code,讓它重新繼承環境。
D. 將 Git 加入 PATH
PortableGit 在 <PortableGit>\bin\ 與 <PortableGit>\cmd\ 下都有 git.exe,任選一個加入 PATH 後重新開啟 VS Code。
VSsearch: Restart ServerVSsearch: Show Git Info— 提示顯示 branch / HEAD;Output 頻道記錄git_exeVSsearch: Dump Diagnostics— JSON 內含gitInfo.git_exe與settings.gitExecutable
解除安裝
最簡單的做法是內建命令:Ctrl+Shift+P → VSsearch: Uninstall (Wipe Index + Remove Extension)。它會停止 sidecar、刪除目前工作區的 <repo>\.vssearch\,再執行 workbench.extensions.uninstallExtension kvh.vssearch。
若只想清除索引但保留擴充套件,請改用 VSsearch: Wipe Local Index (.vssearch)。
pwsh# Manual / scripted uninstall code --list-extensions | Select-String vssearch code --uninstall-extension kvh.vssearch # 0.2.0+ code --uninstall-extension undefined_publisher.vssearch # legacy 0.1.x # Optional: per indexed repo Remove-Item -Recurse -Force <repo>\.vssearch
<repo>\.vssearch\ 之外寫入任何資料,僅有一個工作區 globalState 旗標 (vssearch.firstRunHandled),VS Code 在移除擴充套件時會自動清除。完整文件: INSTALL.md / INSTALL_tw.md
EXE 封裝
使用 PyInstaller --onefile 模式封裝為單一 EXE,需要 pyinstaller(pip install pyinstaller)。
cmdcd e:\Git\repository\VSsearchExtension _pack.bat REM Output: REM dist\vss-build.exe (~12 MB) REM dist\vss-search.exe (~12 MB)
_pack.bat 會:
- 對每個 CLI 呼叫
..\_gen_version_info.py產生version_info.txt。 - 執行 PyInstaller,使用
..\Rewolf.ico圖示與--collect-submodules vss。
E:\Git\PortableGit\bin\git.exe。效能
| 情境 | 時間 | 說明 |
|---|---|---|
| 29k 檔 / 純文字 / Python 直接呼叫 | 390 s | — |
| 29k 檔 / 純文字 / EXE | 530 s | --onefile 解壓開銷 |
| 純文字查詢(trigram) | 200~900 ms | 取決於匹配數 |
| SHA-skip 增量重建 | < 5 s | 無變更檔案 |
總結
VSsearch 的每個選擇都是「被使用者現場的限制」逆向推導出來的: SHA-first 增量 避免冗餘讀取、 Trigram 倒排 讓任意子字串走索引、 三檔分離 讓不同生命週期的資料可獨立重建、 中段熵值過濾 避免韌體 blob 污染文字索引、 並行讀 + 序列寫 讓 SQLite 完全不碰 BUSY。 它不是要取代 ripgrep 或 Elasticsearch,而是填補「個人開發者每天反覆查同一個大倉庫」這個被忽視的中間地帶。
- 把
vss.config.json放進 repo 設定git_executable與routing預設。 - 執行
vss-build install-hooks讓分支切換時自動重建 MinorDB。 - 大型分支用
chain一次跑完所有分支。







