Community程式設計與開發github.com

EugineKosenko/majordom

在即時 Emacs 中透過 headless emacsclient 管理 claude-code-ide.el 工作階段 — 啟動/繼續/恢復,無需阻塞式提示,安全停止,切換許可權模式與 auto-accept,以及在互動式選取器中導航。

majordom 是什麼?

此技能提供了一組專門的 `emacsclient --eval` 配方,用於從統稱為「管家」(Majordom)的外部 Emacs 工作階段管理 `claude-code-ide.el` 工作階段。它解決了直接呼叫 `claude-code-ide-continue` 或 `claude-code-ide-resume` 所產生的關鍵凍結問題,這些函數在 headless 環境中會發出一段阻塞式的 `read-string` 提示。唯一的萬用安全入口是 `claude-code-ide-start`,它接受用於新交談、繼續或恢復的選用參數,且永不要求互動式輸入。該技能詳細說明如何在啟動前檢查現有工作階段、如何使用基於緩衝區的搜尋驗證遙控模式運作、如何在停止程序前先行停用 `query-on-exit` 標記以避免懸掛的程序,以及如何透過 `process-send-string` 發送 ANSI 轉義序列來導航 terminal 內部的選取器(例如恢復清單與權限提示)。它還區分了 permission-mode 的循環(Shift+Tab)與獨立的 `claude-code-ide-toggle-auto-accept` Emacs 函數,後者僅影響 MCP 的 `openDiff` 行為,不影響 terminal 的狀態列。該技能適用於任何需要在 Emacs 頭部伺服器上自動化或遙控 Claude Code 工作階段的情境,包括那些由另一個 Emacs 實例或 AI 代理所控制的。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/EugineKosenko/majordom/tree/HEAD/skills/cc-sessions

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

cc-sessions

針對從「管家」(或任何能存取同一 Emacs 伺服器的工作階段)管理 claude-code-ide.el 工作階段的具體 emacsclient --eval 配方。原理詳見 majordom.md;此處僅收錄現成可用的呼叫。

關鍵:唯一安全的啟動指令是 claude-code-ide-start

claude-code-ide-continue、claude-code-ide-resume 以及舊的 claude-code-ide(均不帶參數)— 切勿在 headless 環境中直接呼叫。當目錄已有啟用中工作階段時,它們都會觸發阻塞的 (read-string "Instance name (empty for auto): "),在沒有使用者於鍵盤前的情況下會永久凍結(已在三者上經實證確認)。唯一的例外是使用者直接在互動式 M-x 中執行。

claude-code-ide-start(簽章為 (&optional instance-name continue resume))能以單一呼叫涵蓋所有三種情況,且永遠不會互動式詢問名稱:

;; 正常啟動新對話
(let ((default-directory "/home/eugine/job/<project>/")
      (claude-code-ide-cli-extra-flags "--remote-control <project>"))
  (claude-code-ide-start "<name-or-nil>"))

;; 替代 claude-code-ide-continue
(claude-code-ide-start "<name-or-nil>" t nil)

;; 替代 claude-code-ide-resume(在 claude 終端機內部開啟互動式選取器,
;; 而非透過 Emacs 迷你快取 — 呼叫本身不會阻塞 emacsclient)
(claude-code-ide-start "<name-or-nil>" nil t)

instance-name(第一個參數)若為 nil ⇒ 自動編號(vedmid-2、vedmid-3...)。僅在使用者已為新副本指定名稱/目標時才明確設定 — 若不確定,請詢問使用者,不要自行編造。

啟動前:檢查現有狀態

(mapcar (lambda (b) (list (buffer-name b) (and (get-buffer-process b) (process-status (get-buffer-process b)))))
        (seq-filter (lambda (b) (string-match-p "claude-code\[<project>" (buffer-name b))) (buffer-list)))
  • 無啟用中工作階段 → (claude-code-ide-start nil t nil)(將承接專案的最後一段對話,如同 continue)。
  • 有啟用中工作階段 → 切勿為了「重新啟動」而將其停止。使用相同的 claude-code-ide-start 啟動額外的副本(若目標是選取特定舊對話則使用 resume=t,否則建立並行新對話)。

啟動後:透過在緩衝區中實際搜尋來確認遙控模式

沒有凍結並不證明 --remote-control 已生效(曾有案例:忘記了旗標 — 工作階段乾淨地啟動了,但未處於遙控模式)。

(with-current-buffer "*claude-code[<project>]*"
  (save-excursion (goto-char (point-min))
    (if (search-forward "remote-control" nil t) "FOUND" "NOT FOUND")))

若為 NOT FOUND — 不一定是錯誤:檢查緩衝區的完整內容(buffer-substring-no-properties (point-min) (point-max)),該行可能出現在已渲染範圍之外,或者(對於大型工作階段)在 eat 的可見滾動區之外 — 終端機本身僅保留近期歷史,而非整個對話。

停止工作階段:先停用 query-on-exit,再停止

claude-code-ide-stop 本身是安全的,且不取決於工作階段是否具有 remote-control。但正常的 Emacs 提示 Buffer "..." has a running process; kill it? 會非同步地彈出(在 process-sentinel 中,已在 claude-code-ide-stop 返回之後)— 因此圍繞呼叫本身的 let 包裝無濟於事。請預先以單獨呼叫停用進程上的標記:

(let ((proc (get-buffer-process "*claude-code[<project>]*")))
  (when proc (set-process-query-on-exit-flag proc nil)))
(with-current-buffer "*claude-code[<project>]*" (claude-code-ide-stop))

若目錄有多個副本(vedmid、vedmid:2、vedmid:masazh...)— 在該緩衝區的背景下使用 with-current-buffer(而非透過 default-directory)呼叫 claude-code-ide-stop:確認訊息將指出已停止的是哪一個("Stopping Claude Code vedmid:masazh...")。

若提示仍舊逃脫並掛起(ps aux | grep emacsclient 顯示卡住的進程)— 切勿自行嘗試解除封鎖(無重複的 --eval、無訊號送至 emacs)— 請要求使用者在即時 Emacs 中回應。風險的完整背景請參閱 emacs.md。

在互動式選取器中導航(恢復清單、權限提示)

工作階段清單(resume)和權限確認選單是在終端機內部渲染的(非透過 Emacs 迷你快取)— 它們透過原始的 process-send-string 以標準 ANSI 序列控制,而非透過 emacsclient --eval 的 Elisp 呼叫:

(process-send-string (get-buffer-process "*claude-code[<project>]*") "\e[B")   ; 向下箭頭
(process-send-string (get-buffer-process "*claude-code[<project>]*") "\e[A")   ; 向上箭頭
(process-send-string (get-buffer-process "*claude-code[<project>]*") "\e[6~")  ; Page Down
(process-send-string (get-buffer-process "*claude-code[<project>]*") "\r")     ; Enter(確認)

每次發送按鍵後,先重新讀取緩衝區內容(buffer-substring-no-properties)以查看新的游標位置(❯)和標題 (N of M),然後再繼續移動或確認 — 不要未經檢查就盲目移動數步。直接選擇確認選單項目的數字鍵(如 "3")未經實證為可靠 — 使用箭頭導航 + Enter 更穩妥。

切換 permission-mode(Shift+Tab)— 與 auto-accept 不同

終端機狀態列(⏸ manual mode on、⏵⏵ accept edits on、⏸ plan mode on、⏵⏵ auto mode on)完全由 claude 二進位檔本身控制 — Emacs 對此一無所知。循環(Shift+Tab,四個狀態):manual → accept edits → plan → auto → manual。

(process-send-string (get-buffer-process "*claude-code[<project>]*") "\e[Z")

切換偶爾會觸發中繼的工具確認提示(Do you want to proceed?)— 若目標是返回 auto 模式,請透過箭頭導航(非數字)選擇 "Yes, and switch to auto mode" 選項,然後按 Enter。

claude-code-ide-toggle-auto-accept — 獨立的 Emacs 函數,非相同的狀態

不要與上述的 permission-mode 循環混淆。此函數僅切換工作階段結構上的 Elisp 標記,且僅影響 MCP 工具 openDiff(在儲存檔案前提出 ediff 審視建議):ON → 不顯示 ediff,檔案立即儲存(FILE_SAVED);OFF → 正常的 ediff。終端機狀態列不會因此呼叫而改變。

(with-current-buffer "*claude-code[<project>]*" (claude-code-ide-toggle-auto-accept))

向使用者顯示緩衝區內容,「如同他們正在觀看」

(with-current-buffer "*claude-code[<project>]*" (buffer-substring-no-properties (point-min) (point-max)))

對於大型工作階段,請進行截斷((max (point-min) (- (point-max) N)) (point-max))— 完整內容可能達數 MB,儘管 eat 的可見滾動區始終有限(實際渲染的部分不會無限增長)。

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

EugineKosenko/majordom

Analyse a Figma .fig file kept in a project's spcfctn/ui/draft. Unpacks and decodes it offline (kiwi), breaks it into sections, screens, text rows and rasters, writes the analysis to spcfctn/ui/*.md, then fetches the author's comments through the figma MCP by link, binds them to screens by geometry, checks that the comments agree with the content of the file and asks the user to clarify what does not. Use when the user asks to analyse, decode or re-read a .fig file or Figma wireframes, or to refresh spcfctn/ui after a new export.

EugineKosenko/majordom

Scaffold a new component/command/crate in this user's literate org-babel Rust style (modeled on ads-back's crates/api and crates/cli patterns — one org file per command with a :tangle skeleton block, Декларації-before-Визначення/Дії noweb blocks, one heading per concern). Use whenever the user asks to add a new component, command, procedure, CLI subcommand, Yew component, module, or crate in an org-babel-literate Rust project (ads-back, ads-front, or similar), including wiring a brand-new crate's config.org/env.org/main.org into the workspace's federated config.org.

EugineKosenko/majordom

Bootstrap a new project in this user's standard layout — .claude-root, .dir-locals.el (root: org-link abbreviation), code/, spcfctn/code/ (with its own git repository) and a .claude/ directory with its own git repository and a CLAUDE.md that fixes the project's prose language and its short two-letter project code (chosen by the user from options the agent proposes) — and translate any files already present into that language. Use whenever the user asks to create, start, set up, initialise or "оформити" a new project (or to bring an existing bare directory to the standard layout).

EugineKosenko/majordom

Check org/md prose in this user's projects against the prose-formatting conventions in ~/.claude/rules/org-babel.md (~...~ vs =...= markup, acronym casing, /.../ glossary terms, real org-links vs italics/plain text, spaces around / between two markups, trailing newline, fill-column). Use proactively right after editing prose paragraphs in an .org or .md file (in place of manually re-deriving each rule from memory), and whenever the user explicitly asks to check/lint org rules or compares the request to running clippy.

相關技能