claude-code.el

repository·main·Indexed 20 days ago

https://github.com/stevemolitor/claude-code.el

An Emacs interface for the Claude Code CLI that integrates Emacs buffers with Claude AI for coding assistance. It supports multiple terminal backends (eat, vterm, ghostel), image pasting on Emacs 29+, and a hook system via a wrapper script to intercept tool requests using the Emacs minibuffer. Features include commands for sending regions and files to Claude, error fixing via flymake/flycheck, and optional IDE integration with Monet.

Tokens
11.3K
Snippets
21
Records
33
Agent score
71%

What's inside claude-code.el

  1. Configure the ghostel (libghostty) backend

    main

    When using the ghostel backend, claude-code.el automatically applies several configurations to Claude buffers:

    • Disables ghostel-kill-buffer-on-exit (managed by claude-code.el).
    • Sets ghostel-set-title-function to nil to prevent OSC title sequences from renaming the buffer.
    • Routes terminal bell events through claude-code-notification-function.

    For general ghostel settings like keybindings or colors, refer to the official ghostel documentation.

  2. How the Claude Code hook wrapper works

    main

    The claude-code-hook-wrapper script is a necessary intermediary when using emacsclient --eval to return JSON to Claude Code.

    Because emacsclient wraps output in quotes (e.g., "{\"json\": \"data\"}"), Claude Code would fail to parse it. The wrapper script:

    1. Calls emacsclient with the requested hook.
    2. Detects if the response is a quoted JSON string.
    3. Strips outer quotes and unescapes inner quotes.
    4. Returns clean, valid JSON to Claude Code.
  3. How multiple Claude instances work

    main

    claude-code.el allows running multiple Claude instances simultaneously, each associated with a specific directory (project root, file directory, or current directory). This enables separate conversations for different workflows (e.g., one instance for 'tests' and another for 'refactor') within the same project.

    Key Concepts

    • Instance Naming: The first instance in a directory is the "default". Subsequent instances require a custom name.
    • Buffer Naming: Buffers follow the pattern *claude:/path/to/directory:instance-name*.
    • Instance Selection: If multiple instances exist for a project, commands like claude-send-command or claude-code-kill will prompt you to select the target instance.
    • Cross-Project Usage: You can select an instance running in a different project to analyze dependent files or sibling directories.
    • Persistence: The package remembers which buffers are associated with which instances to minimize repetitive prompts.
    ## Instance Management
    - When you start Claude with `claude-code`, it creates an instance for the current directory
    - If a Claude instance already exists for the directory, you'll be prompted to name the new instance (e.g., "tests", "docs")
    - You can also use `claude-code-new-instance` to explicitly create a new instance with a custom name
  4. Manage Claude windows and modes

    main

    Control how the Claude interface is displayed and how you interact with it:

    • Visibility:
      • claude-code-toggle (C-c c t): Shows or hides the Claude window.
      • claude-code-switch-to-buffer (C-c c b): Jumps to the Claude buffer (opens it if hidden).
    • Read-Only Mode:
      • claude-code-toggle-read-only-mode (C-c c z): Toggles read-only mode in the Claude buffer. In this mode, you can use normal Emacs commands to select and copy text. Invoke it again to exit.
    • Mode Cycling:
      • Use claude-code-cycle-mode (often bound to C-c M or via a repeat map) to quickly switch between default, auto-accept edits, and plan modes.
  5. Start, stop, and manage Claude sessions

    main

    Use these commands to manage the lifecycle of your Claude instances:

    • claude-code (C-c c c): Starts a new Claude instance in the root project directory (via project.el) or the current directory.
    • claude-code-start-in-directory (C-c c d): Starts Claude in a specific directory prompted by the user.
    • claude-code-continue: Continues the previous conversation.
    • claude-code-resume: Lets you pick from a list of previous sessions.
    • claude-code-kill (C-c c k): Kills the Claude process and closes its window.
  6. Install claude-code.el using straight.el

    main

    For users of straight.el, use the following configuration. This setup includes the necessary dependencies and terminal backends. It uses :depth 1 for the claude-code installation to reduce download size.

    ;; install required inheritenv dependency:
    (use-package inheritenv
      :straight (:type git :host github :repo "purcell/inheritenv"))
    
    ;; for eat terminal backend:
    (use-package eat
      :straight (:type git
                       :host codeberg
                       :repo "akib/emacs-eat"
                       :files ("*.el" ("term" "term/*.el") "*.texi"
                               "*.ti" ("terminfo/e" "terminfo/e/*")
                               ("terminfo/65" "terminfo/65/*")
                               ("integration" "integration/*")
                               (:exclude ".dir-locals.el" "*-tests.el"))))
    
    ;; for vterm terminal backend:
    (use-package vterm :straight t)
    
    ;; for ghostel terminal backend (libghostty):
    (use-package ghostel
      :straight (:type git :host github :repo "dakra/ghostel"))
    
    ;; install claude-code.el, using :depth 1 to reduce download size:
    (use-package claude-code
      :straight (:type git :host github :repo "stevemolitor/claude-code.el" :branch "main" :depth 1
                       :files ("*.el" (:exclude "images/*")
                       ))
      :bind-keymap
      ("C-c c" . claude-code-command-map) ;; or your preferred key
      ;; Optionally define a repeat map so that "M" will cycle thru Claude auto-accept/plan/confirm modes after invoking claude-code-cycle-mode / C-c M.
      :bind
      (:repeat-map my-claude-code-map ("M" . claude-code-cycle-mode))
      :config
      ;; optional IDE integration with Monet
      (add-hook 'claude-code-process-environment-functions #'monet-start-server-function)
      (monet-mode 1)
    
      (claude-code-mode))
  7. Manage Claude instances across directories

    main

    Use these commands to navigate and manage multiple Claude sessions across different projects:

    • claude-code-select-buffer (C-c c B): Dedicated command to show and select from all running Claude instances across all projects and directories.
    • C-u claude-code-switch-to-buffer: Shows all Claude instances across all directories (not just the current one).
    • claude-code-kill-all (C-c c K): Terminates all running Claude instances across all directories.
  8. Integrate with Monet for IDE features

    main

    For advanced IDE integration, use Monet. This allows Claude to see your current selection, show diffs in Emacs, use Monet tools to open files, and access diagnostics.

    To enable, add the following to your configuration:

    (add-hook 'claude-code-process-environment-functions #'monet-start-server-function)
    (monet-mode 1)
  9. Customize Claude Code window display

    main

    You can control how the Claude Code buffer is displayed using two primary methods:

    1. Using claude-code-display-window-fn

    Provide a function that accepts the buffer as an argument. This allows for custom logic, such as using popwin or specific display-buffer parameters.

    2. Using display-buffer-alist

    Use standard Emacs display-buffer-alist entries to target Claude buffers (which typically match the regex ^\*claude). This is useful for forcing Claude into persistent side windows.

    ;; Method 1: Custom display function
    (defun my-claude-display-right (buffer)
      "Display Claude buffer in right side window."
      (display-buffer buffer '((display-buffer-in-side-window)
                               (side . right)
                               (window-width . 90))))
    (setq claude-code-display-window-fn #'my-claude-display-right
    
    ;; Method 2: display-buffer-alist
    (add-to-list 'display-buffer-alist
                  '(^\*claude
                    (display-buffer-in-side-window)
                    (side . right)
                    (window-width . 90)))
  10. Install claude-code.el using use-package (Emacs 30+)

    main

    To install claude-code.el on Emacs 30+, you must first ensure the inheritenv dependency is installed via :vc. You should also install a terminal backend package (eat, vterm, or ghostel) depending on your preference.

    Note: If you are not using a :vc install for eat, you must add the NonGNU ELPA archive to your configuration.

    ;; add melpa to package archives (vterm and ghostel are on melpa):
    (require 'package)
    (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
    (package-initialize)
    
    ;; install required inheritenv dependency:
    (use-package inheritenv
      :vc (:url "https://github.com/purcell/inheritenv" :rev :newest))
    
    ;; for eat terminal backend:
    (use-package eat :ensure t)
    
    ;; for vterm terminal backend:
    (use-package vterm :ensure t)
    
    ;; for ghostel terminal backend (libghostty):
    (use-package ghostel
      :vc (:url "https://github.com/dakra/ghostel" :rev :newest))
    
    ;; install claude-code.el
    (use-package claude-code :ensure t
      :vc (:url "https://github.com/stevemolitor/claude-code.el" :rev :newest)
      :config
      ;; optional IDE integration with Monet
      (add-hook 'claude-code-process-environment-functions #'monet-start-server-function)
      (monet-mode 1)
    
      (claude-code-mode)
      :bind-keymap ("C-c c" . claude-code-command-map)
    
      ;; Optionally define a repeat map so that "M" will cycle thru Claude auto-accept/plan/confirm modes after invoking claude-code-cycle-mode / C-c M.
      :bind
      (:repeat-map my-claude-code-map ("M" . claude-code-cycle-mode)))
  11. Use Quick Responses to answer Claude without switching buffers

    main

    You can answer Claude's queries directly from your current editing buffer using these commands:

    • claude-code-send-return (C-c c y): Sends <return> (e.g., to say "Yes").
    • claude-code-send-escape (C-c c n): Sends <escape> (e.g., to say "No" or cancel).
    • claude-code-send-1 (C-c c 1): Sends "1".
    • claude-code-send-2 (C-c c 2): Sends "2".
    • claude-code-send-3 (C-c c 3): Sends "3".
  12. Configure fonts for Unicode support

    main

    Claude Code uses many special Unicode characters. If these do not render correctly, you should configure font fallbacks or a specific face for the REPL.

    Option 1: Fontset Fallbacks

    Set use-default-font-for-symbols to nil and use set-fontset-font to provide fallback fonts for the symbol or unicode ranges. This allows your primary font to handle ASCII while specialized fonts handle symbols.

    Option 2: Dedicated REPL Face

    Apply a specific font only to the Claude Code REPL by customizing the claude-code-repl-face.

    ;; Option 1: Using JuliaMono as a Unicode fallback
    (setq use-default-font-for-symbols nil)
    (set-fontset-font t 'unicode (font-spec :family "JuliaMono"))
    (set-fontset-font t 'symbol "Maple Mono" nil 'prepend)
    
    ;; Option 2: Using a specific font for the REPL face
    (custom-set-faces
       '(claude-code-repl-face ((t (:family "JuliaMono")))))