Emacs for AI Development: Workflows That Scale

Emacs for AI Development: Workflows That Scale

Modern IDEs optimize for mouse-driven workflows and language-specific features. Emacs optimizes for text manipulation and extensibility. AI development requires working across multiple languages, formats, and tools simultaneously. Emacs handles this naturally.

Python for training scripts. YAML for Kubernetes configs. SQL for feature queries. Markdown for documentation. JSON for API responses. Terraform for infrastructure. Shell scripts for automation. Emacs treats all of them as text to be manipulated efficiently.

Why Emacs in 2025#

Text-first paradigm:

Everything is a buffer. Buffers are text. Text operations apply universally. Search, replace, navigate, transform - same commands work across all file types.

Language agnostic:

No switching between “Python mode IDE” and “Go mode IDE” and “YAML mode IDE”. One editor. All languages. Same keybindings. Muscle memory compounds.

Extensibility:

Write Emacs Lisp to automate workflows. Integration with external tools via elisp. No waiting for IDE vendor to add features.

Terminal integration:

SSH to remote servers. Run commands in embedded terminal. Execute shell scripts without leaving editor. All in one window.

Long-term investment:

Emacs keybindings from 1985 still work in 2025. Will work in 2045. Other editors come and go. Emacs remains.

Magit: Git Interface#

Magit makes git operations faster than command-line:

Status view (magit-status):

On branch feature/new-api
Your branch is up to date with 'origin/feature/new-api'.

Unstaged changes
  modified   src/api.py
  modified   tests/test_api.py

Untracked files
  src/utils.py

Recent commits
  a1b2c3d Fix authentication bug
  e4f5g6h Add rate limiting

Press s to stage file under cursor. Press c c to commit. Type message. Press C-c C-c to finish. Press P p to push. Done.

Branching:

Press b c - create branch. Type name. Enter. Press b b - checkout branch. Type name. Enter.

Rebasing:

Press r i - interactive rebase. Mark commits to squash, reword, drop. Press C-c C-c. Done.

Cherry-picking:

Navigate to commit. Press A - cherry-pick. Done.

All without leaving Emacs. Faster than switching to terminal. Visual feedback. Undo with one command.

Projectile: Project Navigation#

Projectile treats each git repo as a project:

Find file in project:

Press C-c p f. Type partial filename. Fuzzy match. Enter.

C-c p f
api[TAB]

Instantly jumps to src/api/endpoints.py even if you’re currently editing tests/test_auth.py.

Search in project:

Press C-c p s g. Type search term. See all matches across project.

Switch between projects:

Press C-c p p. Select project from recent list. All buffers switch to new project.

Run project commands:

Press C-c p !. Runs command in project root (make test, npm run build, etc.).

Org-Mode: Project Management#

Plain text project management:

* Census Frontend Rewrite [3/7]
** DONE Setup React + TypeScript
   CLOSED: [2025-12-10]
** DONE Configure build pipeline
   CLOSED: [2025-12-12]
** DONE Implement authentication
   CLOSED: [2025-12-15]
** TODO Migrate user dashboard
   DEADLINE: <2025-12-20>
** TODO Performance testing
** TODO Accessibility audit
** TODO Production deployment

Press C-c C-t to cycle TODO states. Press C-c C-d to set deadline. Press C-c C-s to schedule.

Agenda view shows all tasks across all org files:

Week agenda:
Monday     20 Dec: TODO Migrate user dashboard (Census Frontend)
Tuesday    21 Dec: TODO Performance testing (Census Frontend)

Tasks as text files in git. Version controlled. No external tool. Searches with grep.

Integration with AI Tools#

Copilot in Emacs:

(use-package copilot
  :hook (prog-mode . copilot-mode))

AI suggestions inline. Tab to accept. Same workflow as VS Code but in Emacs.

ChatGPT/Claude via shell:

(defun ask-ai (prompt)
  (interactive "sPrompt: ")
  (shell-command-to-string
    (format "echo '%s' | llm -m claude-3-5-sonnet" prompt)))

Select region. Run ask-ai. Get response in buffer.

Code generation:

(defun generate-tests ()
  (interactive)
  (let* ((code (buffer-substring-no-properties (point-min) (point-max)))
         (prompt (format "Generate pytest tests for:\n\n%s" code)))
    (insert (ask-ai prompt))))

Open implementation file. Run generate-tests. Tests inserted in buffer. Edit as needed.

Multiple Language Support#

Same editor, different languages:

Python:

  • python-mode for syntax
  • elpy or lsp-mode for completion
  • pytest integration for testing

Go:

  • go-mode for syntax
  • lsp-mode with gopls
  • go-guru for navigation

JavaScript/TypeScript:

  • typescript-mode
  • lsp-mode with ts-server
  • prettier for formatting

All with consistent keybindings. M-x compile runs tests regardless of language. C-c C-c sends code to REPL regardless of language.

Terminal Integration#

Multi-term or vterm:

Embedded terminal in Emacs. Run commands without switching windows:

Terminal 1: npm run dev
Terminal 2: pytest --watch
Terminal 3: kubectl logs -f pod/app

All visible simultaneously. Copy output to other buffers. Run commands with text from buffers.

Remote Development#

TRAMP mode:

Edit files on remote servers directly:

C-x C-f /ssh:server:/path/to/file.py

Feels local. Actually remote. Magit works. File saves write to server. Grep searches remote files.

Deploy to server:

(defun deploy-to-server ()
  (interactive)
  (save-some-buffers)
  (shell-command "rsync -avz . server:/app/ && ssh server 'cd /app && make restart'"))

Press key. Code syncs. Service restarts. Done.

Window Management#

Split windows for multi-file editing:

┌─────────────────────────────────┬─────────────────────┐
│ src/api/endpoints.py            │ tests/test_api.py   │
│                                 │                     │
│ def authenticate(user, pass):  │ def test_auth():    │
│     if validate(user, pass):   │     result = auth() │
│         return create_session() │     assert result   │
│                                 │                     │
├─────────────────────────────────┴─────────────────────┤
│ Terminal                                              │
│ $ pytest tests/test_api.py                            │
│ ✓ test_auth passed                                    │
└───────────────────────────────────────────────────────┘

See implementation, tests, and test output simultaneously. No window switching.

Dired: File Management#

Dired is file manager in Emacs:

  • C-x d - open directory
  • Navigate with arrow keys
  • Press m to mark files
  • Press C to copy marked files
  • Press R to rename
  • Press ! to run shell command on marked files

Search files with C-s. Narrow to matches with / /. Operate on filtered results.

Accessibility: Emacspeak Integration#

Emacs is the only editor with complete screen reader support via Emacspeak. Audio desktop for blind developers.

SwiftMac provides speech synthesis. Emacs sends text. SwiftMac speaks. Complete audio feedback:

  • Character echo while typing
  • Line read when Enter pressed
  • Audio icons for different modes
  • Tones for navigation

Benefits for sighted users:

Audio feedback while eyes focus on other screen. Navigate with sound cues. Multitask effectively.

Why Not VS Code?#

VS Code strengths:

  • Better default experience
  • Easier to learn
  • Better language-specific features
  • Integrated debugger
  • More plugins

Emacs strengths:

  • Faster text manipulation (keyboard-only)
  • Better for multiple languages simultaneously
  • Deeper customization
  • Terminal integration
  • Org-mode
  • Accessibility (Emacspeak)
  • Long-term stability

For AI development across multiple languages, formats, and tools, Emacs’s text-first paradigm wins.

Example Workflow: ML Pipeline Development#

Morning:

Open org file. Review tasks for today. Mark current task in-progress.

Development:

Open project with projectile. Edit Python training script. Split window. Open corresponding test file. Make changes to both. Run pytest in terminal buffer. See failures. Fix. Rerun. Green.

Deployment:

Open Terraform files. Review changes with magit. See diff. Stage changes. Commit. Push.

Documentation:

Open Markdown README. Update with new configuration. Spell-check. Commit with magit.

Code review:

Magit shows incoming PR. Check out branch. Review changes in magit. Add comments. Push review.

All without leaving Emacs. No context switching. No mouse. Keyboard-only workflow.

Learning Curve Reality#

Emacs is hard to learn. Initial productivity drop for 2-4 weeks. Then productivity gains compound over years.

Month 1: Slower than old editor. Learning basic navigation.

Month 3: Approaching old productivity. Discovering new workflows.

Month 6: Faster than old editor. Customizing for needs.

Year 1: Significantly faster. Building automation.

Year 5: Workflows impossible in other editors.

The question: invest time upfront for long-term gains, or optimize for immediate productivity?

For 20+ year careers, the investment pays off.

Configuration#

Minimal starting config:

;; package management
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-initialize)

;; must-have packages
(use-package magit)           ; git interface
(use-package projectile)      ; project management
(use-package company)         ; completion
(use-package flycheck)        ; syntax checking
(use-package which-key)       ; discover commands

;; language modes
(use-package python-mode)
(use-package go-mode)
(use-package markdown-mode)
(use-package yaml-mode)

;; org-mode (built-in)
(global-set-key (kbd "C-c a") 'org-agenda)

200 lines gets you productive. Expand over time.

The Text Editor for Text Work#

Software development is text manipulation. Emacs is a text manipulation tool. Everything else follows from this.

AI generates text (code). Humans review text. Emacs makes text manipulation efficient. For AI-assisted development across multiple languages and tools, efficiency compounds.