CommunityCoding & Developmentgithub.com

EugineKosenko/majordom

Керування сесіями claude-code-ide.el у живому Emacs через emacsclient headless — старт/continue/resume без блокуючих запитів, безпечна зупинка, перемикання permission-mode і auto-accept, навігація в інтерактивних picker'ах. Використовуй, коли сесія "Мажордом" має підняти, продовжити, зупинити чи інспектувати сесію claude-code-ide для іншого проєкту.

What is majordom?

majordom is a Claude Code agent skill that керування сесіями claude-code-ide.el у живому Emacs через emacsclient headless — старт/continue/resume без блокуючих запитів, безпечна зупинка, перемикання permission-mode і auto-accept, навігація в інтерактивних picker'ах. Використовуй, коли сесія "Мажордом" має підняти, продовжити, зупинити чи інспектувати сесію claude-code-ide для іншого проєкту.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/EugineKosenko/majordom/tree/HEAD/skills/cc-sessions

Installed? Explore more Coding & Development skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

cc-sessions

Довідник конкретних emacsclient --eval рецептів для керування сесіями claude-code-ide.el з "Мажордома" (чи будь-якої іншої сесії з доступом до цього самого Emacs-сервера). Принципи (чому саме так) — у 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/<проект>/")
      (claude-code-ide-cli-extra-flags "--remote-control <проект>"))
  (claude-code-ide-start "<ім'я-або-nil>"))

;; замість claude-code-ide-continue
(claude-code-ide-start "<ім'я-або-nil>" t nil)

;; замість claude-code-ide-resume (відкриває інтерактивний picker УСЕРЕДИНІ термінала claude,
;; не через Emacs-мінібуфер — сам виклик не блокує emacsclient)
(claude-code-ide-start "<ім'я-або-nil>" nil t)

instance-name (1-й аргумент) 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\\[<проект>" (buffer-name b))) (buffer-list)))
  • Немає активної сесії → (claude-code-ide-start nil t nil) (підхопить останню розмову проєкту, як continue).
  • Є активна сесія → НІКОЛИ не зупиняй її "для перезапуску". Піднімай ДОДАТКОВУ копію тим самим claude-code-ide-start (з resume=t, якщо мета — обрати конкретну стару розмову, чи без — нова розмова поруч).

Після старту: підтверди remote-control реальним пошуком у буфері

Відсутність зависання ще НЕ доводить, що --remote-control подіяв (епізод: забула прапорець — сесія піднялась чисто, але лишилась не-remote).

(with-current-buffer "*claude-code[<проект>]*"
  (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, тоді stop

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[<проект>]*")))
  (when proc (set-process-query-on-exit-flag proc nil)))
(with-current-buffer "*claude-code[<проект>]*" (claude-code-ide-stop))

Якщо для каталогу кілька копій (vedmid, vedmid:2, vedmid:masazh...) — виклич claude-code-ide-stop у контексті САМЕ того буфера (with-current-buffer), не через default-directory: повідомлення підтвердить, яку саме зупинила ("Stopping Claude Code vedmid:masazh...").

Якщо запит усе ж проскочив і завис (ps aux | grep emacsclient показує застряглий процес) — НІКОЛИ не намагайся розблокувати сама (жодних повторних --eval, жодних сигналів до emacs) — проси користувача відповісти в живому Emacs. Див. emacs.md для повного контексту цієї небезпеки.

Навігація в інтерактивних picker'ах (resume-список, permission-запити)

Список сесій (resume) і меню підтвердження дозволів рендеряться ВСЕРЕДИНІ термінала (не через Emacs-мінібуфер) — керуються звичайними ANSI-послідовностями через сирий process-send-string, не через emacsclient --eval елісп-виклики:

(process-send-string (get-buffer-process "*claude-code[<проект>]*") "\e[B")   ; стрілка вниз
(process-send-string (get-buffer-process "*claude-code[<проект>]*") "\e[A")   ; стрілка вгору
(process-send-string (get-buffer-process "*claude-code[<проект>]*") "\e[6~")  ; Page Down
(process-send-string (get-buffer-process "*claude-code[<проект>]*") "\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[<проект>]*") "\e[Z")

Перемикання ІНОДІ саме викликає проміжний запит підтвердження інструмента (Do you want to proceed?) — обирай пункт "Yes, and switch to auto mode" через навігацію стрілками (не цифрою) + Enter, якщо мета — саме повернутись в auto.

claude-code-ide-toggle-auto-accept — окрема Emacs-функція, не той самий стан

Не плутати з циклом permission-mode вище. Ця функція перемикає лише елісп-прапорець на структурі сесії й впливає ЛИШЕ на MCP-інструмент openDiff (пропозиція ediff-перегляду перед збереженням файлу): ON → ediff не показується, файл зберігається одразу (FILE_SAVED); OFF → звичайний ediff. Статус-рядок термінала НЕ змінюється цим викликом.

(with-current-buffer "*claude-code[<проект>]*" (claude-code-ide-toggle-auto-accept))

Показати вміст буфера користувачу "ніби він дивиться"

(with-current-buffer "*claude-code[<проект>]*" (buffer-substring-no-properties (point-min) (point-max)))

Для великих сесій обрізай ((max (point-min) (- (point-max) N)) (point-max)) — повний вміст може бути мегабайтним, хоча видимий скролбек 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.

Related Skills