
用 cli-anything-iterm2 管理 iTerm2 Profiles 與 Preferences從配色預設到 tmux 偏好的一體化配置實踐【免費下載鏈接】CLI-AnythingCLI-Anything: Making ALL Software Agent-Native -- CLI-Hub: https://clianything.cc/項目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything本文聚焦 CLI-Anything 生態(tài)中 cli-anything-iterm2 的配置管理能力講解如何用profile與pref兩組命令對正在運行的 iTerm2 實例進行外觀Profile / 配色預設與全局偏好PreferenceKey / 主題 / tmux 相關(guān)開關(guān)的編程化讀寫。讀完本文你將能復刻本文全部命令完成「查看全部 Profile → 按 GUID 取詳情 → 套用 Solarized Dark 配色 → 調(diào)整 tmux 窗口打開方式與 dashboard 上限 → 檢測當前主題」的完整自動化流程并理解每個命令在底層 iTerm2 Python API 與 CLI 之間是如何落地的。文中所有結(jié)論均可在 profile-pref.md 與對應源碼模塊中得到驗證。一、先分清兩組概念Profiles 與 Preferences在 iTerm2 中profile配置文件與preference全局偏好是兩層不同的設置概念作用對象典型內(nèi)容cli-anything-iterm2 入口Profile單個會話/窗口的外觀與行為模板字體、顏色、badge 文本、按鍵映射profile命令組PreferenceiTerm2 應用級全局開關(guān)打開 tmux 窗口的方式、dashboard 條目數(shù)、自動隱藏客戶端等pref命令組這一區(qū)分直接映射到 CLI 的兩組子命令結(jié)構(gòu)上見 iterm2_ctl_cli.pyprofile組與 iterm2_ctl_cli.pypref組。二、運行前提一條命令能觸達 iTerm2 的三個必要條件所有profile/pref命令最終都經(jīng)由 iterm2_backend.py 中的run_iterm2()同步包裝器驅(qū)動 iTerm2 Python API 通過 WebSocket 連接正在運行的 iTerm2.app。因此執(zhí)行前需滿足iTerm2 正在運行macOSbrew install --cask iterm2已啟用 Python APIiTerm2 → Preferences → General → Magic → Enable Python API該提示同時出現(xiàn)在 CLI 的幫助文本與后端錯誤信息中Python 側(cè)依賴就緒安裝cli-anything-iterm2或pip install -e .底層會import iterm2見 iterm2_backend.py 的require_iterm2_running()。命令統(tǒng)一形態(tài)為cli-anything-iterm2 [--json] group command [OPTIONS] [ARGS]其中--json會以結(jié)構(gòu)化 JSON 輸出結(jié)果便于 Agent 解析profile組還遵守 CLI 的「會話上下文」機制——apply-preset未顯式傳--session-id時會回退到此前通過app current/app set-context保存的上下文 session見 iterm2_ctl_cli.py。三、Profile 命令查列表、取詳情、套配色參考文檔 profile-pref.md 給出的 Profile 命令全集cli-anything-iterm2 profile list [--filter NAME] cli-anything-iterm2 profile get guid # detailed settings cli-anything-iterm2 profile color-presets cli-anything-iterm2 profile apply-preset Solarized Dark [--session-id ID]3.1profile list枚舉可用 Profile列出 iTerm2 中全部 Profile 的名稱 GUID對。--filter NAME支持按名稱子串過濾不區(qū)分大小寫。其底層實現(xiàn)位于 core/profile.py 的list_profiles()通過iterm2.PartialProfile.async_query(connection)拉取所有 Profile過濾時使用name_filter.lower() not in name.lower()空名以(unnamed)兜底。# 全量列表 cli-anything-iterm2 profile list # 只看名稱含 dark 的 Profile cli-anything-iterm2 profile list --filter dark3.2profile get guid按 GUID 取詳情get需要你在profile list中拿到的 GUID返回該 Profile 的關(guān)鍵字段。需要如實說明當前的「詳情」是精選子集——從 core/profile.py 看get_profile_detail()先按 GUID 匹配PartialProfile再調(diào)用async_get_full_profile()取全量 Profile但僅導出三個字段return { name: full.name, guid: full.guid, badge_text: full.badge_text, }CLI 層iterm2_ctl_cli.py據(jù)此逐行打印name、guid、badge_text。若 GUID 不存在get_profile_detail()會拋出ValueError: Profile with GUID ... not found.由 CLI 統(tǒng)一格式化為Error: ...并退出見 handle_iterm2_error。cli-anything-iterm2 profile list # 先找 GUID cli-anything-iterm2 profile get guid # 再取詳情3.3profile color-presets枚舉可用配色預設列出 iTerm2 內(nèi)置的全部顏色預設名返回經(jīng)過排序的字符串列表。實現(xiàn)為 core/profile.py 的list_color_presets()即iterm2.ColorPreset.async_get_list(connection)后sorted()。執(zhí)行cli-anything-iterm2 profile color-presets3.4profile apply-preset給指定會話套用配色把命名配色預設應用到某個會話的 Profile 上例如經(jīng)典深色方案Solarized Darkcli-anything-iterm2 profile apply-preset Solarized Dark cli-anything-iterm2 profile apply-preset Solarized Dark --session-id w0t0p0需要特別說明其作用范圍apply_color_preset()core/profile.py并非修改磁盤上的 Profile 定義而是取當前會話的 Profile 對象 →ColorPreset.async_get(connection, preset_name)拿到預設 →profile.async_set_color_preset(preset)→ 再session.async_set_profile(profile)寫回會話本質(zhì)是對該會話生效的即時配色切換。底層流程可概括為async_find_session(connection, session_id)定位目標會話見 iterm2_backend.pyColorPreset.async_get()按名取預設把預設套到會話 Profile 并回寫會話。成功返回{session_id, preset_applied}若預設名不存在iTerm2 API 側(cè)會拋錯并由 CLI 統(tǒng)一呈現(xiàn)。四、Pref 命令全局偏好的發(fā)現(xiàn)、讀取與寫入pref組的核心價值在于「以代碼方式讀寫任意 iTerm2 全局偏好」參考文檔給出的完整命令集cli-anything-iterm2 pref list-keys # all valid PreferenceKey names cli-anything-iterm2 pref list-keys --filter tmux # filter by substring cli-anything-iterm2 pref get OPEN_TMUX_WINDOWS_IN cli-anything-iterm2 pref set OPEN_TMUX_WINDOWS_IN 2 cli-anything-iterm2 pref theme # current theme tags is_dark bool4.1pref list-keys發(fā)現(xiàn)所有合法鍵名不必記憶偏好鍵先讓 CLI 告訴你全部合法鍵名cli-anything-iterm2 pref list-keys cli-anything-iterm2 pref list-keys --filter tmux # 只看與 tmux 相關(guān)的 cli-anything-iterm2 pref list-keys --filter font # 只看字體相關(guān)其實現(xiàn)iterm2_ctl_cli.py直接遍歷iterm2.preferences.PreferenceKey枚舉把所有成員的枚舉名形如OPEN_TMUX_WINDOWS_IN按字典序排序輸出--filter為不區(qū)分大小寫的子串過濾結(jié)果中同時給出count。4.2pref get/pref set鍵名解析與值類型歸一化cli-anything-iterm2 pref get OPEN_TMUX_WINDOWS_IN cli-anything-iterm2 pref set OPEN_TMUX_WINDOWS_IN 2這兩個命令背后是 core/pref.py 的get_preference()與set_preference()。有兩個值得展開的實現(xiàn)細節(jié)雙通道鍵名解析入?yún)ey會先嘗試當作iterm2.PreferenceKey的枚舉成員名解析如OPEN_TMUX_WINDOWS_IN失敗則原樣回退為原始偏好鍵字符串如OpenTmuxWindowsIn所以兩種寫法都可用。字符串值自動類型化_parse_value()core/pref.py會把 CLI 傳入的字符串轉(zhuǎn)成合適類型規(guī)則如下輸入字符串示例解析結(jié)果說明true/false任意大小寫True/False布爾值2int2整數(shù)字符串優(yōu)先轉(zhuǎn) int1.5float1.5非整數(shù)的數(shù)字串轉(zhuǎn) floatSolarized Dark等保持字符串其它一律原樣保留因此pref set OPEN_TMUX_WINDOWS_IN 2實際寫入的是整數(shù)2而pref set AUTO_HIDE_TMUX_CLIENT_SESSION true寫入的是布爾True無需在命令行區(qū)分類型。set_preference最終調(diào)用iterm2.async_set_preference(connection, pref_key, parsed)并返回{key, value, set: True}。4.3pref theme讀取當前主題標簽cli-anything-iterm2 pref theme返回當前 iTerm2 主題的標簽列表與is_dark布爾值。實現(xiàn)見get_theme()core/pref.py先iterm2.async_get_app(connection)再調(diào)用app.async_get_theme()得到一組標簽例如[dark]、[light]或[dark, highContrast]is_dark dark in tags。這對 Agent 判斷「當前是深色還是淺色外觀、是否高對比度」非常有用例如據(jù)此決定要向終端發(fā)送什么顏色的 ANSI 輸出。五、tmux 偏好速記命令四個高頻開關(guān)一步到位參考文檔為 tmux 相關(guān)偏好專門提供了速記層cli-anything-iterm2 pref tmux-get # all tmux prefs at once cli-anything-iterm2 pref tmux-set open_in 2 # 0native_windows 1new_window 2tabs_in_existing cli-anything-iterm2 pref tmux-set auto_hide_client true cli-anything-iterm2 pref tmux-set use_profile true cli-anything-iterm2 pref tmux-set dashboard_limit 105.1pref tmux-get一次性讀全get_tmux_preferences()core/pref.py一次性并發(fā)讀取 4 個 PreferenceKey并附帶一個人類可讀的標簽映射返回字段對應 PreferenceKey說明open_tmux_windows_inOPEN_TMUX_WINDOWS_IN0native_windows1new_window2tabs_in_existinglabel 隨附在返回結(jié)果中tmux_dashboard_limitTMUX_DASHBOARD_LIMITtmux dashboard 顯示的最大條目數(shù)auto_hide_tmux_client_sessionAUTO_HIDE_TMUX_CLIENT_SESSION是否自動隱藏 tmux 客戶端會話use_tmux_profileUSE_TMUX_PROFILE新建窗口時是否使用 tmux profileCLI 層iterm2_ctl_cli.py除輸出完整字典外還會附帶一行把open_in的數(shù)值還原為文字標簽例如open_in: 2 (tabs_in_existing)。5.2pref tmux-set按易記名設置set_tmux_preference()core/pref.py只接受四個人類可讀設置名通過內(nèi)部setting_map映射到 PreferenceKey如果傳了未知設置名會拋出ValueError并提示合法集合setting_map { open_in: iterm2.PreferenceKey.OPEN_TMUX_WINDOWS_IN, dashboard_limit: iterm2.PreferenceKey.TMUX_DASHBOARD_LIMIT, auto_hide_client: iterm2.PreferenceKey.AUTO_HIDE_TMUX_CLIENT_SESSION, use_profile: iterm2.PreferenceKey.USE_TMUX_PROFILE, }tmux-set設置名合法取值含義open_in0/1/2tmux 新窗口的呈現(xiàn)方式原生窗口 / 新 iTerm2 窗口 / 并入現(xiàn)有窗口的標簽頁dashboard_limit整數(shù)dashboard 最大條目數(shù)auto_hide_clienttrue/false是否自動隱藏 tmux 客戶端會話use_profiletrue/false新窗口是否使用 tmux Profile例如把 tmux 窗口默認作為現(xiàn)有窗口中的標簽頁打開2并讓 dashboard 最多顯示 10 個條目cli-anything-iterm2 pref tmux-set open_in 2 cli-anything-iterm2 pref tmux-set dashboard_limit 10結(jié)合 iTerm2 的 tmux 集成core/tmux.py可以理解這些偏好的意義iTerm2 中每個 tmux 窗口會以 iTerm2 標簽頁形式出現(xiàn)list_tmux_tabs()只返回tmux_window_id非空的標簽頁見 core/tmux.py因此「新 tmux 窗口出現(xiàn)在哪里原生窗口/新窗口/現(xiàn)有窗口標簽頁」由OPEN_TMUX_WINDOWS_IN決定AUTO_HIDE_TMUX_CLIENT_SESSION與USE_TMUX_PROFILE則分別控制客戶端會話的顯隱與新建窗口所用 Profile。這些偏好與 CLI 的tmux create-window、tmux set-visible、tmux bootstrap等命令配合可實現(xiàn)完整的 tmux -CC 工作流完整流程見 tmux-guide.md。六、從命令到 Python API 的調(diào)用鏈理解整條鏈路有助于排查問題profile與pref命令并非直接操作 plist 或 AppleScript而是統(tǒng)一的「Click 命令 → 同步橋 → 異步協(xié)程 → iTerm2 Python API」結(jié)構(gòu)Click 層iterm2_ctl_cli.py定義profile、pref兩組命令負責參數(shù)解析、--json格式化與錯誤兜底同步橋iterm2_backend.py 的run_iterm2(coro_fn, ...)用iterm2.run_until_complete()把異步協(xié)程包成同步調(diào)用并捕獲 WebSocket 連接失敗等異常給出「iTerm2 是否在運行 / Python API 是否啟用」的排查提示協(xié)程實現(xiàn)core/profile.py與core/pref.py中每個函數(shù)都簽名為async def ...(connection, ...)內(nèi)部直接調(diào)用iterm2.PartialProfile、iterm2.ColorPreset、iterm2.async_get_preference、iterm2.async_set_preference、app.async_get_theme等官方 Python API 對象。因此所有配置操作的實時生效性都來自 iTerm2 自身 APICLI 只是把「需要在 Python REPL 里手寫的 async 代碼」壓縮成了可腳本化、可被 Agent 調(diào)用的單行命令。七、測試覆蓋與驗證方式該功能模塊在倉庫內(nèi)配有明確測試清單見 tests/TEST.md 與測試源碼test_core.py中的test_profile_helptest_core.py等用例驗證profile --help的子命令結(jié)構(gòu)與 CLI 骨架E2E 用例TestProfileOperations覆蓋profile list至少返回 1 個 Profile與profile color-presets返回字符串列表等這些用例依賴正在運行的 iTerm2見 test_full_e2e.py子進程級測試如test_json_profile_list確認安裝后的命令行入口在--json下也能正常輸出涉及pref/tmux的測試會按環(huán)境跳過TEST.md 明確記錄TestTmuxOperations一類的用例在沒有活動tmux -CC會話時會跳過啟動方式在 iTerm2 終端內(nèi)執(zhí)行tmux -CC。對讀者而言最快的本地驗證路徑是先cli-anything-iterm2 profile color-presets再cli-anything-iterm2 profile apply-preset Solarized Dark隨后cli-anything-iterm2 pref tmux-get觀察 tmux 四項偏好最后cli-anything-iterm2 pref theme確認主題標簽——整個過程均可在一次終端會話內(nèi)完成且每條命令都能加--json換成結(jié)構(gòu)化輸出。八、常見問題速查現(xiàn)象原因與排查Error: Profile with GUID ... not found.profile get的 GUID 非法先用profile list取真實 GUIDError: No session ID specified...apply-preset等會話級命令未傳--session-id且未設置上下文先執(zhí)行app current/app set-contextError: Unknown tmux setting ...tmux-set只接受open_in/dashboard_limit/auto_hide_client/use_profile四個名字命令報無法連接 iTerm2 / WebSocket refused未啟動 iTerm2或 Preferences → General → Magic → Enable Python API 未勾選啟用后需重啟 iTerm2數(shù)字以字符串形式寫入而非數(shù)值只有當值是字符串時_parse_value才會自動轉(zhuǎn)換如需精確布爾或數(shù)值直接傳true/2形態(tài)即可以上行為均可在 profile.py、pref.py 與 iterm2_backend.py 中逐行核驗。掌握profile與pref兩組命令后iTerm2 的外觀與行為配置就不再依賴手工點擊菜單而可以沉淀為可復現(xiàn)的腳本與 Agent 工作流中的標準步驟?!久赓M下載鏈接】CLI-AnythingCLI-Anything: Making ALL Software Agent-Native -- CLI-Hub: https://clianything.cc/項目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考