히스토리

  • [2025-12-28 Sun 16:59] 여러 옵션을 테스트하며 다시 핵심 질문이 무엇인가 되세겨 본다.
  • [2025-12-23 Tue 20:33] 요구사항 정리 후 문서 작성 부탁

이맥스 멀티 오케스트레이션

[2025-12-23 Tue 20:33]

프로젝트 비전

핵심 아이디어

Emacs를 프론트엔드로, Zellij를 백엔드로 하여 Claude Code 에이전트들을 오케스트레이션하는 시스템.

“Claude Code의 풀 기능을 터미널 환경에서 제어하고, Emacs에서 가볍게 조율하는 오케스트레이터”

왜 이 프로젝트인가?

  1. Claude Code가 핵심 - LSP 지원, MCP 통합, 풀 기능 AI 에이전트
  2. tmux는 너무 오래됨 - 레거시 아키텍처, 플러그인 시스템 부재
  3. Zellij가 대안 - WebAssembly 플러그인, 모던 아키텍처
  4. Emacs가 프론트엔드 - 지식 관리(Denote), 코드 편집, 통합 환경

왜 Zellij인가?

tmux vs Zellij 비교

기능tmuxZellij
특정 pane에 텍스트 전송send-keys -twrite_chars_to_pane_id() (Plugin API)
플러그인 시스템없음WebAssembly (WASM)
외부 통신소켓 기반zellij pipe 양방향
pane 출력 읽기capture-paneget_pane_scrollback()
설정 형식자체 문법KDL (모던)
NixOS 지원좋음더 좋음 (Home Manager)

Zellij Plugin API 핵심 기능

// 특정 pane에 명령 전송
write_chars_to_pane_id(chars: &str, pane_id: PaneId)
 
// pane 스크롤백 읽기
get_pane_scrollback(pane_id: PaneId, get_full_scrollback: bool)
 
// 외부 CLI와 양방향 통신
cli_pipe_output(pipe_name: &str, output: &str)
 
// pane 포커스 전환
focus_terminal_pane(terminal_pane_id: u32, ...)

현재 제한사항

  • Issue #3061: CLI에서 --pane-id 옵션 아직 미구현
  • 해결책: Plugin API 사용 또는 CAO 패턴 채용

Claude Code의 중요성

v2.0.74 (2025-12-19) 주요 기능

  1. LSP 지원 (신규!)

    • go-to-definition
    • find-references
    • hover documentation
  2. MCP 통합

    • 외부 도구 연동
    • Context7, GitHub, NixOS 등
  3. 에이전트 기능

    • 백그라운드 태스크
    • 서브에이전트 지원
    • 자율적 도구 사용

Emacs 통합 시나리오

;; LSP 정보와 함께 Claude Code에 요청
(defun emacs-claude-with-lsp-context ()
  "Send current symbol with LSP context to Claude Code."
  (interactive)
  (let* ((symbol (thing-at-point 'symbol))
         (definition (lsp-find-definition))
         (references (lsp-find-references)))
    (zellij-claude-send "claude-main"
      (format "Analyze %s\n\nDefinition:\n%s\n\nReferences:\n%s"
              symbol definition references))))

AWS CAO 컨셉 채용

CLI Agent Orchestrator (CAO) 핵심 패턴

AWS의 cli-agent-orchestrator 에서 가져올 컨셉:

  1. HTTP REST API (port 9889)

    • 언어 독립적
    • Emacs url.el 로 즉시 호출 가능
  2. MCP 도구

    • handoff : 동기 실행
    • assign : 비동기 스폰
    • send_message : 에이전트 간 통신
  3. 터미널 ID 환경변수

    • CAO_TERMINAL_ID 로 각 세션 식별
  4. 계층적 조정

    • Supervisor → Worker 패턴
    • 세션 격리로 컨텍스트 오염 방지

claude_code_agent_farm 패턴

claude_code_agent_farm 에서 가져올 컨셉:

  1. Lock 기반 파일 클레이밍

    • 협업 시 파일 충돌 방지
    • 2시간 이상 stale lock 감지
  2. Heartbeat 모니터링

    • 정체된 에이전트 감지
    • 자동 재시작
  3. 적응형 리소스 관리

    • 작업 패턴에 따른 에이전트 수 조정
    • 최대 50개 에이전트 병렬 실행

아키텍처 설계

전체 구조

┌─────────────────────────────────────────────────────────────────┐
│                         Emacs                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  zellij-claude.el (orchestrator client)                 │   │
│  │  - HTTP POST to localhost:9889                          │   │
│  │  - bd 태스크 상태 연동                                   │   │
│  │  - Denote 지식 컨텍스트 제공                             │   │
│  └─────────────────────────────────────────────────────────┘   │
│                           │                                     │
│                           │ HTTP REST API                       │
└───────────────────────────┼─────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│              Orchestrator Server (Python/Rust)                  │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │  - MCP 도구 노출 (handoff/assign/send_message)           │  │
│  │  - Zellij 세션 관리                                      │  │
│  │  - 에이전트 Heartbeat 모니터링                           │  │
│  │  - bd 상태 동기화                                        │  │
│  └──────────────────────────────────────────────────────────┘  │
│                           │                                     │
│                           │ zellij pipe / Plugin API            │
└───────────────────────────┼─────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                    Zellij Session                               │
│     ┌─────────────────────┬─────────────────────┐              │
│     ▼                     ▼                     ▼              │
│  ┌───────┐          ┌──────────┐          ┌───────────┐       │
│  │ Pane1 │          │ Pane2    │          │ Pane3     │       │
│  │ shell │          │ Claude   │          │ Claude    │       │
│  │       │          │ Code #1  │          │ Code #2   │       │
│  │ (dev) │          │ (main)   │          │ (sub)     │       │
│  └───────┘          └──────────┘          └───────────┘       │
└─────────────────────────────────────────────────────────────────┘

Emacs 최소 구현 (~50줄)

;;; zellij-claude.el --- Claude Code orchestrator client -*- lexical-binding: t; -*-
 
(defvar zellij-claude-api-url "http://localhost:9889"
  "Orchestrator server URL.")
 
(defvar zellij-claude-default-terminal "claude-main"
  "Default Claude Code terminal ID.")
 
(defun zellij-claude-send (terminal-id message)
  "Send MESSAGE to Claude Code in TERMINAL-ID."
  (let ((url-request-method "POST")
        (url-request-extra-headers '(("Content-Type" . "application/json")))
        (url-request-data
         (encode-coding-string
          (json-encode `((terminal_id . ,terminal-id)
                         (message . ,message)))
          'utf-8)))
    (url-retrieve-synchronously
     (format "%s/send_message" zellij-claude-api-url))))
 
(defun zellij-claude-region-or-buffer ()
  "Send current region or buffer to Claude Code."
  (interactive)
  (let ((text (if (use-region-p)
                  (buffer-substring-no-properties (region-beginning) (region-end))
                (buffer-string))))
    (zellij-claude-send zellij-claude-default-terminal text)))
 
(defun zellij-claude-prompt (prompt)
  "Send PROMPT to Claude Code."
  (interactive "sPrompt: ")
  (zellij-claude-send zellij-claude-default-terminal prompt))
 
(provide 'zellij-claude)
;;; zellij-claude.el ends here

bd 태스크 관리 통합

컨셉: bd + Orchestrator

bd (beads)를 에이전트 태스크 관리에 활용:

┌─────────────────────────────────────────────────────────────────┐
│                    bd 이슈 상태                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ beads-abc: "API 엔드포인트 구현" [in_progress]          │   │
│  │   └─ assigned_to: claude-pane-2                         │   │
│  │   └─ heartbeat: 2025-12-23T20:30:00                    │   │
│  │   └─ context: docs/api-spec.org                        │   │
│  │                                                         │   │
│  │ beads-xyz: "테스트 작성" [blocked by beads-abc]        │   │
│  │   └─ waiting_for: beads-abc                            │   │
│  └─────────────────────────────────────────────────────────┘   │
│                           │                                     │
│                           │ 자동 동기화                         │
│                           ▼                                     │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ Orchestrator                                            │   │
│  │   - bd ready → 다음 작업할 이슈 조회                    │   │
│  │   - bd update --status in_progress → 에이전트 할당     │   │
│  │   - bd close → 완료 시 자동 닫기                        │   │
│  │   - heartbeat 실패 시 bd update --status open          │   │
│  └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

bd 확장 필드 제안

{
  "id": "beads-abc",
  "title": "API 엔드포인트 구현",
  "status": "in_progress",
  "type": "task",
  "priority": 2,
  "extended": {
    "assigned_agent": "claude-pane-2",
    "last_heartbeat": "2025-12-23T20:30:00",
    "context_files": ["docs/api-spec.org", "src/api/"],
    "auto_close_on_commit": true
  }
}

Emacs-bd-Orchestrator 워크플로우

(defun zellij-claude-work-on-issue (issue-id)
  "Assign Claude Code to work on bd ISSUE-ID."
  (interactive
   (list (completing-read "Issue: "
           (zellij-claude--get-ready-issues))))
  ;; 1. bd에서 이슈 정보 가져오기
  (let* ((issue (zellij-claude--bd-show issue-id))
         (context-files (plist-get issue :context_files)))
    ;; 2. 이슈 상태 업데이트
    (shell-command (format "bd update %s --status in_progress" issue-id))
    ;; 3. 컨텍스트 파일 읽기
    (let ((context (mapconcat #'zellij-claude--read-file context-files "\n\n")))
      ;; 4. Claude Code에 작업 요청
      (zellij-claude-send "claude-main"
        (format "Work on: %s\n\nDescription: %s\n\nContext:\n%s"
                (plist-get issue :title)
                (plist-get issue :description)
                context)))))

구현 로드맵

Phase 1: 기반 구축 (1-2주)

  • Zellij 설치 및 기본 설정 (NixOS Home Manager)
  • CAO 포크 또는 유사 서버 구현
  • zellij-claude.el 최소 구현

Phase 2: 통합 (2-3주)

  • bd 확장 필드 설계 및 구현
  • Heartbeat 모니터링
  • Emacs 키바인딩 설정

Phase 3: 고급 기능 (4주+)

  • 멀티 에이전트 조율 (supervisor/worker)
  • 파일 Lock 시스템
  • Denote 지식 자동 주입

참고 자료

로컬 링크