My Modern Emacs Configuration

Introduction

This article explores my carefully crafted Emacs configuration that emphasizes minimalism, productivity, and seamless AI integration. Built around modern completion systems and enhanced with Claude Code integration, this setup represents a balance between Emacs' power and contemporary development workflows.

Core Philosophy

The configuration follows three key principles:

  1. Minimalism: Clean interface with essential features only
  2. Modern Tooling: Leveraging contemporary packages like Vertico, Consult, and Treesitter
  3. AI-First Development: Deep integration with Claude Code and multiple AI backends

Architecture Overview

Package Management Strategy

The configuration uses use-package with automatic installation via :ensure t. This approach ensures packages are installed on first run while maintaining declarative configuration.

Directory Structure

~/.emacs.d/
├── init.el                 # Main configuration
├── early-init.el          # Early UI and backup setup
├── custom.el              # Auto-generated customizations
├── CLAUDE.md              # AI assistant instructions
├── lisp/                  # Custom packages
│   └── claude-code.el/    # Claude Code integration
├── backups/               # Organized backup system
└── elpa/                  # Package installation

Key Features

Completion Ecosystem

The configuration implements a modern completion stack:

This combination provides intelligent, fast completion across all Emacs interfaces.

AI Integration

Claude Code Integration

The centerpiece of AI integration is Claude Code, bound to C-c c:

(use-package claude-code
  :load-path "lisp/claude-code.el"
  :config
  (claude-code-mode)
  
  ;; Auto-switch to claude-code buffer when it starts
  (defun claude-code-auto-switch-focus (&optional arg)
    "Switch to claude-code buffer and focus on it."
    (when-let* ((buffer (get-buffer "*claude*")))
      (let ((window (get-buffer-window buffer)))
        (if window
            (select-window window)
          (switch-to-buffer-other-window buffer)))))

  (advice-add 'claude-code :after 'claude-code-auto-switch-focus)
  :bind-keymap ("C-c c" . claude-code-command-map))

Multi-Backend AI Support

GPTel provides access to multiple AI providers with easy switching:

;; Configure DeepSeek backend
(setq gptel-backend-deepseek
      (gptel-make-openai "DeepSeek"
        :host "api.deepseek.com"
        :endpoint "/chat/completions"
        :stream t
        :key (lambda () (getenv "DEEPSEEK_API_KEY"))
        :models '("deepseek-chat")))

;; Configure Gemini backend (default)
(setq gptel-backend-gemini
      (gptel-make-gemini "Gemini"
        :key (lambda () (getenv "GEMINI_API_KEY"))
        :stream t))

Development Environment

Language Server Protocol

Automatic LSP activation for major languages:

(use-package eglot
  :ensure t
  :hook ((python-mode js-mode typescript-mode go-mode rust-mode) . eglot-ensure))

Treesitter Integration

Enhanced syntax highlighting via treesitter:

(use-package treesit-auto
  :ensure t
  :config
  (treesit-auto-add-to-auto-mode-alist 'all)
  (global-treesit-auto-mode))

Theme Management

Intelligent theme switching based on system appearance:

(defun auto-switch-theme ()
  "Switch between standard-light and standard-dark themes based on system appearance."
  (let ((dark-mode-p
         (string-match-p
          "Dark"
          (shell-command-to-string
           "defaults read -g AppleInterfaceStyle 2>/dev/null || echo Light"))))
    (if dark-mode-p
        (progn
          (load-theme 'standard-dark t)
          (setq current-theme-dark t))
      (progn
        (load-theme 'standard-light t)
        (setq current-theme-dark nil)))))

;; Check every 60 seconds
(run-with-timer 0 60 'auto-switch-theme)

Note-Taking with Denote

Structured note-taking system integrated with the org/ workspace:

(use-package denote
  :ensure t
  :custom
  (denote-directory (expand-file-name "~/workspaces/org/"))
  (denote-known-keywords '("emacs" "programming" "electronics" "article" "project" "journal"))
  (denote-infer-keywords t)
  (denote-sort-keywords t)
  :bind
  (("C-c n n" . denote)
   ("C-c n i" . denote-link)
   ("C-c n b" . denote-backlinks)))

Key Bindings Philosophy

The key binding scheme prioritizes:

  1. Consistency: Related functions grouped under common prefixes
  2. Discoverability: which-key provides context-sensitive help
  3. Muscle Memory: Common operations on easily accessible keys

Primary Key Maps

Enhanced Navigation

Backup and Safety Features

Organized Backup System

Configured in early-init.el to keep backups organized:

(let ((backup-dir (expand-file-name "backups/backups/" user-emacs-directory))
      (auto-save-dir (expand-file-name "backups/auto-saves/" user-emacs-directory)))
  (setq backup-directory-alist `((".*" . ,backup-dir))
        auto-save-file-name-transforms `((".*" ,auto-save-dir t))))

Smart Auto-Formatting

JSON files are automatically formatted on save (limited to files < 50KB):

(add-hook 'json-mode-hook
  (lambda ()
    (when (< (buffer-size) 50000)
      (add-hook 'before-save-hook 'json-pretty-print-buffer nil t))))

Performance Considerations

Lazy Loading

Most packages use :defer t or mode-specific hooks to avoid startup delays:

(use-package markdown-mode
  :ensure t
  :defer t
  :mode ("\\.md\\'" . markdown-mode))

Completion Tuning

Corfu auto-completion is tuned for responsiveness:

(use-package corfu
  :ensure t
  :init (global-corfu-mode)
  :custom
  (corfu-auto t)
  (corfu-auto-delay 0.2))  ; Fast but not intrusive

Environment Integration

Shell Environment Import

API keys and paths are imported from shell:

(use-package exec-path-from-shell
  :ensure t
  :init
  (when (memq window-system '(mac ns x))
    (exec-path-from-shell-copy-envs
     '("OPENAI_API_KEY" "GEMINI_API_KEY" "DEEPSEEK_API_KEY"))
    (exec-path-from-shell-initialize)))

Server Mode

Emacs server starts automatically for external connections:

(require 'server)
(unless (server-running-p)
  (server-start))

Workflow Integration

Project-Centric Development

The configuration integrates seamlessly with the ~/workspaces/ structure:

Git Workflow

Magit provides full git interface with C-x g, supporting:

Custom Packages

Claude Code Enhancement

The configuration includes custom advice for better Claude Code integration:

(defun claude-code-auto-switch-focus (&optional arg)
  "Switch to claude-code buffer and focus on it."
  (when-let* ((buffer (get-buffer "*claude*")))
    (let ((window (get-buffer-window buffer)))
      (if window
          (select-window window)
        (switch-to-buffer-other-window buffer)))))

(advice-add 'claude-code :after 'claude-code-auto-switch-focus)

Conclusion

This Emacs configuration represents a modern approach to text editing that embraces AI assistance while maintaining Emacs' core strengths. By focusing on completion, project awareness, and seamless AI integration, it creates a development environment that enhances productivity without sacrificing flexibility.

The configuration demonstrates how traditional Emacs can be enhanced with contemporary tools while preserving the editor's fundamental philosophy of extensibility and user control. The result is a setup that feels both familiar to Emacs veterans and approachable to newcomers seeking modern development tools.

Installation and Setup

  1. Clone configuration to ~/.emacs.d/
  2. Set environment variables for AI services
  3. Start Emacs - packages auto-install
  4. Create ~/workspaces/org/ for note-taking
  5. Install language servers as needed

The configuration is designed to work out of the box while remaining easily customizable for individual preferences and workflows.