emacs

ericdallo 2026-02-11T14:30:30.642669Z

Anyone knows a good elisp mcp server/skill/etc ? I want to let LLM change my running emacs instance and eval elisp there

ag 2026-02-14T18:26:11.168639Z

No, no, I didn't mean to sound like: "you gave me the wrong thing", sorry, mate. Your tool does work, it just forces the model to fail first and then re-adjust immediately, but it succeeds eventually. Without your shared idea I wouldn't even know what I was missing, so you have my gratitude, thank you! This mcp also does another thing differently - instead of just trying to read the result of the execution from stderr, it gets *Messages* buffer output and checks other special buffers.

ag 2026-02-14T18:30:22.697959Z

Your thinking also made me want to dig for more, and since I'm on a Mac most of the time I baked jxa-browser-server that uses JXA/Applescript that does stuff like listing browser tabs, finding stuff in the opened tabs, getting currently selected text, getting the content of the active tab, etc. very cool. I'll keep playing with this, maybe will share once I test it out

Ovi Stoica 2026-02-15T04:03:04.489529Z

Heh that's interesting! The mcp you shared is very cool and I might take it up. It also shows me how to create simple mpcs with babashka which is very valuable

ericdallo 2026-02-16T10:37:35.600299Z

Not really, I suck at elisp tests, never managed to have a project with good tests like for clojure... But I know some elisp, so when I can't make it work LLM usually finds the reason behind it

bozhidar 2026-02-16T10:39:41.223239Z

Most of my Elisp projects have a lot of tests - buttercup is a pretty library for doing specs, and LLMs handle it pretty well. They are also great to backfill libraries without tests to begin with, although for this they definitely need a bit of guidances to do something meaningful.

bozhidar 2026-02-16T10:40:37.346319Z

Given that neither Clojure not Elisp are tier 1 languages in any LLM, the results are quite good and I guess they'll only get better.

ericdallo 2026-02-16T11:04:18.939129Z

Yeah that sounds like a great idea, I will try to backfill tests

ag 2026-02-13T23:19:02.122809Z

@ovidiu.stoica1094 this thing seems to be struggling a lot, trying to collapse some complex elisp into a string, properly parsing quotes, etc. I tortured it and made it spit out a nice little, functional MCP - bb script.

ag 2026-02-13T23:19:37.811629Z

| Test                                         | Result                             |
|----------------------------------------------|------------------------------------|
| Basic arithmetic                             | ✓                                 |
| Emacs version query                          | ✓ Emacs 30.2, aarch64 macOS       |
| Recursive  cl-labels  (factorial)            | ✓                                 |
| Higher-order functions (compose)             | ✓ returned 42                     |
| Hash tables                                  | ✓                                 |
|  cl-loop  FizzBuzz                           | ✓                                 |
| State persistence across calls               | ✓ variable survived between evals |
| Regex parsing                                | ✓ extracted date, user, env       |
| Buffer creation/manipulation                 | ✓                                 |
| Emacs introspection (pid, buffers, features) | ✓ 59 buffers, 1286 features       |
|  defmacro  + timing                          | ✓                                 |
|  cl-defstruct                                | ✓                                 |
|  pcase  pattern matching                     | ✓ all types classified correctly  |
| Real buffer mode census                      | ✓ top mode: fundamental-mode (25) |
| Shell command from Emacs                     | ✓ round-tripped through shell     |
|  cl-loop  destructuring + multi-accumulators | ✓                                 |
| Cleanup ( makunbound / fmakunbound )         | ✓                                 |
17/17 passed. The MCP server is rock solid - handles lambdas, macros, structs, regex, buffer ops, shell calls, state persistence, introspection, and cleanup without a hitch.

Ovi Stoica 2026-02-14T06:48:30.553939Z

That's very nice! Maybe I didn't stress test it enough but it worked quite well for my needs. What model did you use? I use it with sonnet-4.5 & opus-4.6

ericdallo 2026-02-11T14:31:22.718089Z

Found https://github.com/rhblind/emacs-mcp-server but seems complex to setup

vemv 2026-02-11T14:33:52.438089Z

https://github.com/steveyegge/efrit ? haven't tried

xificurC 2026-02-11T14:35:05.150759Z

why does one need an mcp for this sort of thing? Doesn't the LLM already know how to evaluate in a running emacs instance?

ericdallo 2026-02-11T14:36:20.033379Z

I'm trying to fix a nasty eca-emacs bug and give LLM a way to eval to my current eca session would be great, right now it knows only to launch a new emacs and run elisp from there but it's not as powerful

xificurC 2026-02-11T14:39:00.051599Z

one should be able to evaluate in the running session with emacsclient, provided one's running emacs in server mode, which most frameworks nowadays do

ericdallo 2026-02-11T14:39:16.453769Z

yeah that would work, I don't use emacsClient tho

xificurC 2026-02-11T14:39:36.300549Z

you don't have to, your LLM would 🙂

ericdallo 2026-02-11T14:39:47.343529Z

it only caused problems in my NixOS + doom so I just gave it a way

ericdallo 2026-02-11T14:41:13.607599Z

probably a skill or something to teach LLM how to do that would be nice

xificurC 2026-02-11T14:42:41.247579Z

I don't get it, surely the nix package comes with the emacsclient binary?

ericdallo 2026-02-11T14:43:04.168219Z

ah yeah just confirmed I have it and works hehe

ericdallo 2026-02-11T14:43:08.723669Z

will give it a try, let's see

ag 2026-02-11T15:00:44.111839Z

I've been thinking the other day if Karthik's introspector agent can be used with eca https://github.com/karthink/gptel-agent/blob/master/agents/introspector.md

ericdallo 2026-02-11T15:14:58.562839Z

I'm shipping subagents for ECA so that will be better :)

ericdallo 2026-02-11T15:15:11.812379Z

@xifi it worked like a charm with emacsclient, thank you!

👍 1
ericdallo 2026-02-11T15:15:31.543059Z

certainly a skill is deserved for that to teach LLM that emacsclient is avaiable and good to test on the running emacs instance

xificurC 2026-02-11T15:27:55.091939Z

did you find your bug?

ericdallo 2026-02-11T15:28:06.811999Z

yep, that was the only way LLM managed to fix it!

ericdallo 2026-02-11T15:28:49.898909Z

it was awesome to see things poping up in my running emacs, because eca was running emacsclient -e to eval things and test things :)

Ovi Stoica 2026-02-11T18:36:42.976539Z

I confirm I'm using emacsclient eval with eca and it works quite well. I'm very happy. Here's my setup: config.json

"customTools": {
    "elisp-eval": {
      "description": "${file:tools/elisp-eval.md}",
      "command": "emacsclient --eval '{{code}}'",
      "schema": {
        "properties": {
          "code": {
            "type": "string",
            "description": "A string of Emacs Lisp code to evaluate in the running Emacs server. Single quotes in strings must be escaped as '\\'' for shell. Example: (message \"Hello\") or (progn (setq x 10) (+ x 20))"
          }
        },
        "required": ["code"]
      }
    }
  },
eca/tools/elisp-eval.md
Evaluate Emacs Lisp code in the running Emacs server. Returns the result of evaluation.

Usage:
    - `code` parameter accepts Emacs Lisp expressions as a string
    - State persists between calls (defined functions/variables remain available)
    - Requires a running Emacs server (start with `emacs --daemon` or `M-x server-start`)

Important Notes:
    - Only the return value of the last expression is captured
    - Output from `message`, `print`, or `princ` goes to the Emacs *Messages* buffer, not stdout
    - Errors are reported via stderr with exit code 1

Escaping Rules:
    - The code is passed to emacsclient via shell, so escaping follows shell rules
    - Single quotes in elisp strings: Escape as '\''
      Example: (message "It'\''s working")
    
    - Double quotes: Use normally within the elisp code
      Example: (message "Hello World")
    
    - Backslashes: Use \\\\ for literal backslash
      Example: (insert "path\\\\to\\\\file")
    
    - Multi-line code: Use literal newlines or combine with progn
      Example: (progn (setq x 10) (+ x 20))

Examples:
    - Simple: (+ 1 2 3)
      Returns: 6
    
    - Define function: (defun greet (name) (format "Hello, %s!" name))
      Returns: greet
    
    - Call function: (greet "World")
      Returns: "Hello, World!"
    
    - Require package: (progn (require 'dash) (dash-version))
      Returns: "2.19.1" (or current version)
    
    - Multi-step: (progn (setq my-var 42) (message "Set to %d" my-var) (* my-var 2))
      Returns: 84
    
    - Get buffer info: (buffer-name)
      Returns: "*scratch*" (or current buffer name)
    
    - List buffers: (mapcar #'buffer-name (buffer-list))
      Returns: ("*scratch*" "*Messages*" ...)

Common Use Cases:
    - Test Emacs configuration changes interactively
    - Develop and debug elisp functions
    - Query Emacs state (buffers, variables, modes)
    - Prototype package behavior before adding to init.el
    - Inspect and modify Emacs internals

Limitations:
    - Requires Emacs server to be running
    - Cannot capture intermediate output (only return values)
    - No interactive input (cannot use `read-string` etc.)
    - Evaluation happens in the server context, not in a specific buffer

🖖 1
Ovi Stoica 2026-02-11T18:37:30.393879Z

For emacs server I just have:

;; Start Emacs server for emacsclient
(use-package server
  :commands server-running-p
  :defer 2
  :config (unless (server-running-p)
            (message "Starting emacs server...")
            (server-start)))

ericdallo 2026-02-11T18:40:54.934219Z

oh that custom tool is awesome, I may add to https://eca.dev/examples, a skill would be nice putting it together as well, thanks @ovidiu.stoica1094!

Ovi Stoica 2026-02-11T18:43:00.502259Z

Sure! Please go ahead!

bozhidar 2026-02-16T06:16:46.049499Z

@ericdallo Out of curiosity - wouldn’t you do this by having the AI agent look for the solution against some test showcasing it? That’s what I usually do with Claude when using for it Elisp and it works pretty well, even for some tricky issues (but admittedly it takes a bit of time until it sorts out everything involved).

bozhidar 2026-02-16T06:17:53.922599Z

In my experience MCPs don’t add that much value, if they have some alternative (e.g. directly running some tool) and some of them are brutal on the token usage.

Ovi Stoica 2026-02-19T14:07:36.785199Z

I thought this was semi relevant to the convo, given it is about eca & elisp_eval : Sometimes eca doesnt' believe the LSP diagnostics changed so it would use elisp_eval to revert buffer

The LSP cache is stale. Let me trigger a re-index by touching the db file:

Called tool: eca__elisp-eval ✅ 0.04 s

Tool: elisp-eval
Server: eca
Arguments: 
  code: "(progn
  (let ((buf (find-buffer-visiting \"/path/to/db.cljs\")))
    (when buf
      (with-current-buffer buf
        (revert-buffer t t))))
  \"db.cljs reverted\")"

Output: Stdout:
"db.cljs reverted"

ericdallo 2026-02-19T14:11:19.698909Z

Actually this might be a emacs/flycheck/flymake issue, since some times emacs updates the diagnostics if you visit the buffer or something, maybe we can improve eca-emacs to force that update

Ovi Stoica 2026-02-19T14:12:57.466689Z

Yes. I'm not sure diagnostics change if eca edits a file and I don't directly visit that file in emacs. Could be good. Happy to move this in a #eca thread

ericdallo 2026-02-19T14:13:11.987859Z

yeah let's do it