Open-source project
editor-code-assistant/eca-emacs avatar
editor-code-assistant/eca-emacs

ECA Emacs puts an AI pair programming client inside Emacs

Editor Code Assistant (ECA) integration for Emacs

519 stars56 forksEmacs LispApache-2.0

At a glance

What is it?
The eca-emacs package is the Emacs front end for Editor Code Assistant, a server-driven AI client that follows the JSONRPC pattern lsp-mode established, so chat, code suggestions and context handling all arrive over one protocol. Installing it is a MELPA command, and the server binary is downloaded and cached for you.
Who is it for?
Adopt eca-emacs if you live in Emacs and want the AI assistant to be a native part of the editor rather than a separate chat window in a browser, and if you are comfortable with a client that depends on an external server process. Do not adopt it if you need the assistant to run without a background process, since the whole design is that eca-emacs talks to an eca server, and note that the server binary is fetched by the client unless you set `eca-custom-command`.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Emacs Lisp, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A client, not the model

ECA Emacs is described as an AI-powered pair-programming client for Emacs, and the key architectural detail is in the next sentence. Inspired by lsp-mode's JSONRPC handling, it connects to an external `eca` server process to provide interactive chat, code suggestions, context management and more.

So the Emacs Lisp in this repository is a front end. The intelligence lives in the server, and the two talk JSONRPC, the same shape lsp-mode uses to talk to a language server. That comparison is the design brief, and it carries the consequences of the pattern.

The benefits are the ones lsp-mode gave the Emacs community. The client is a thin, editor-native layer, the server is a normal process that can be shared, upgraded and configured independently of the editor, and the protocol is structured rather than being a pile of hooks into the editor's internals. It also means the same server can back other editors, and the README states the goal plainly: everything automatic and smooth as UX and re-usability across editors is the main goal of ECA.

The features that fall out of that are listed in the README's commands section and are worth sampling. There is a dedicated chat window, code suggestions, and a context system where you attach files with an `@` completion. There is a workspace dashboard with a live view of chats, their status, elapsed time, cost and model. There are tool calls that the assistant proposes and you accept or reject one at a time, or all at once. There is MCP server support, so the assistant can reach other tools. There is speech input through whisper.el, and an inline prompt mode that streams an answer into a markdown-rendered overlay above point in any buffer.

The project is Emacs Lisp, Apache 2.0 licensed, available from MELPA, with the last push on 2026-10-20 and no published GitHub releases. The topics include editor, emacs, hacktoberfest and tools, so the project has run as a community effort.

Installing it

The requirement is short. Emacs 28.1 or later.

There are two optional pieces. A custom `eca` server binary, which the README says is already automatically downloaded for UX reasons unless you set `eca-custom-command`. And whisper.el for speech-to-text support.

The first note is worth pausing on. The default behaviour is that the package fetches a server binary for you, which is convenient and is a decision about trust that you may want to make differently in a locked-down environment. The `eca-custom-command` variable is the escape hatch for pointing at your own binary.

The installation from MELPA is one command:

code
M-x package-install eca

If you prefer to declare it in your configuration, the use-package form is:

code
(use-package eca
  :vc (:url "https://github.com/editor-code-assistant/eca-emacs" :rev :newest))

and for Doom Emacs, the package! recipe:

elisp
(package! eca :recipe (:host github :repo "editor-code-assistant/eca-emacs" :files ("*.el")))

The `:rev :newest` in the use-package form and the `:files ("*.el")` in the Doom recipe are the kind of detail that matters in practice, because the repository is flat, with the Emacs Lisp files at the top level, so a package system that expects a conventional `src/` layout needs to be told where the files are.

The repository layout confirms the flat structure. The source files sit at the root, with `eca.el` as the entry point and `eca-api.el`, `eca-chat.el`, `eca-chat-compose.el`, `eca-chat-context.el`, `eca-chat-expandable.el`, `eca-chat-image.el`, `eca-chat-inline.el`, `eca-completion.el`, `eca-config.el`, `eca-diff.el`, `eca-doom.el`, `eca-editor.el`, `eca-jobs.el`, `eca-mcp.el`, `eca-process.el`, `eca-providers.el`, `eca-rewrite.el`, `eca-settings.el`, `eca-table.el`, `eca-util.el` and `eca-workspaces.el`. There is a `test/` directory, a `benchmarks/` directory, an `Eask` file for the package build, and `AGENTS.md` and `CHANGELOG.md` at the root.

How the server is found and started

The quickstart is four steps, and step one carries the whole resolution logic.

Run `M-x eca` to start the eca process and initialize the workspace. The README then spells out what that does: eca-emacs will check for `eca-custom-command`; if not set, it will check for an `eca` on `$PATH`; and if not found, it will download `eca` automatically and cache it.

So there are three sources, tried in order: an explicit command you configured, a binary already on your path, and a download. The third is what makes the package work with no setup at all, and the caching means it happens once.

The order is a sensible design, and it is worth knowing which rung you are on, because the difference matters when something goes wrong. A server you configured and a server on your path are both under your control, while a downloaded one is a binary of a version the package chose for you.

Step two is that the dedicated chat window `<eca-chat>` pops up. Step three is to type your prompt after the `> ` and press RET. Step four is to attach more context, with auto completing after the `@`.

That last step is the one that changes how the tool is used. The `@` completion means context is attached by pointing at files rather than by pasting them or by describing them, so the assistant works on the same code you are looking at. The dedicated window also means the conversation is a separate buffer from your source, which is the conventional shape for this kind of client and keeps the model output from interleaving with your code.

The command surface, and the dashboard

The commands are grouped, and the grouping is the documentation of the feature set.

The server and process group handles the lifecycle: `eca` starts the server and session and opens the chat, `eca-stop` stops it, and `eca-restart` restarts it. `eca-settings` opens the centralized settings panel, which the README says covers MCP servers and more in the future. `eca-mcp-toggle-server` filters MCP servers and can start, stop or connect one. `eca-open-global-config` opens the ECA global config file.

`eca-workspaces` is the feature that goes furthest beyond a chat box. It is described as a live dashboard with all workspaces and chats, refreshed automatically as chats change state. Each chat shows its status, whether it is running, pending approval or waiting for an answer, along with the elapsed time, the cost and the model.

The cost figure deserves attention, because it means the client is tracking token usage per chat. For a tool that can run tool calls and iterate on its own, being able to see what a conversation has cost and which model produced it is the sort of information you want before you leave a loop running.

The dashboard is also a keyboard interface. Press `?` for all actions: open with `RET`, fold with `TAB`, new chat in any workspace with `+`, delete chat or workspace with `d` or `DEL`, rename with `r`, fork with `f`, compact with `C`, model and variant with `m` and `v`, accept or reject tool calls with `a`, `A` and `x`, stop a prompt with `s`, resume a closed chat with `R`, refresh with `g` and quit with `q`. With `eca-buttons-allow-mouse` enabled, clicking the workspace text folds or unfolds it and clicking a chat switches to it.

So the mouse is optional throughout, which is the difference between a tool that respects an Emacs workflow and one that does not.

Chat commands, tool approvals and the details

The chat command list is long, and the parts worth drawing out are the ones that show how the client treats the assistant's actions as something you supervise.

There is `eca-chat-tool-call-accept-all`, `eca-chat-tool-call-accept-all-and-remember` which also remembers for the session, `eca-chat-tool-call-accept-next` and `eca-chat-tool-call-reject-next`. So a tool call is a proposal that you answer, and there is a way to say yes to everything for the rest of the session if you trust the current thread.

There is also attention management. `eca-chat-go-to-next-attention` goes to the next chat waiting on you, whether that is a pending tool call approval or a question, cycling across sessions, and `eca-chat-go-to-next-attention-in-project` does the same but only across the current session's chats. That command exists because the tool can be working in several workspaces at once, and the question of which chat needs you is the real problem in that situation.

The navigation commands are granular. There are commands to move to the previous or next user message from point, to the previous or next expandable block, to toggle an expandable block, and to expand or collapse all blocks in the current chat. `eca-chat-timeline` shows the user prompt history as a timeline, and `eca-chat-load-older-history` loads and prepends the previous page of the chat's history, bound to `C-c C-S-o` and also reachable through the Load older messages link at the top of the chat.

A few more details are notable. `eca-chat-add-context-to-system-prompt` and the user prompt variant add files or directories with multiple modes and range support, and the user prompt variant jumps to the chat window while keeping point where it was with a prefix argument. `eca-chat-toggle-image-thumbnail` toggles a thumbnail for a screenshot pasted in the prompt, an image file added as context, or an image mentioned in a sent message. `eca-table-open` opens the markdown table at point in a dedicated `*eca-table*` buffer where horizontal scrolling keeps the header aligned with the body, and the binding is scoped to the table so it overrides `o` only there and works under evil and Doom.

And `eca-chat-talk` uses whisper.el to send a prompt by voice.

The inline prompt mode is the one that changes the interaction model. `eca-chat-inline-prompt` asks ECA from any buffer, streaming the answer into a markdown-rendered overlay above point, and when the buffer has no inline chat yet it asks which chat to use.

Where this fits, and the difference it makes

The obvious alternative is to use the assistant in a separate application, a browser tab pointed at a chat service, and copy things across. The difference in approach is that the client runs inside the editor, so it knows about the buffer, the point, the file and the project, and the answers arrive rendered where you are working.

The `@` context completion is the clearest expression of that. Attaching a file is a completion against the project's files rather than a path you type or a paste from another window, and the inline prompt mode means you can ask about the code at point without switching buffers.

The second alternative is another editor's client for the same server. That is the point of the JSONRPC design: the server is the product, the clients are thin, and the README's stated goal is re-usability across editors. The trade is that you accept the server's model of what a chat, a workspace and a tool call are, rather than working in the editor's own idiom.

The limitations come from the same place. The client needs a server process, and the server is a separate thing with its own version, its own configuration and its own idea of what an MCP server is. The workspace dashboard, the cost tracking and the approval flow are all evidence of a fairly opinionated design, which is convenient when it matches how you work and something to learn when it does not.

And the download behaviour is the thing to decide deliberately. Downloading a server binary on first use is a good default for a trial and a poor default for a machine where you want to know what executes. The `eca-custom-command` setting is there for that, and setting it is the first thing to do if this is going on a workstation rather than a scratch environment.

Editorial conclusion

Adopt eca-emacs if you live in Emacs and want the AI assistant to be a native part of the editor rather than a separate chat window in a browser, and if you are comfortable with a client that depends on an external server process. Do not adopt it if you need the assistant to run without a background process, since the whole design is that eca-emacs talks to an eca server, and note that the server binary is fetched by the client unless you set `eca-custom-command`. Verify first that you are on Emacs 28.1 or later, that the server resolution order gives you the binary you want, whether a downloaded one, one on `$PATH` or your own via `eca-custom-command`, and that the tool call approval flow suits how you work, since the chat can pause for your answer.

Frequently asked questions

What is ECA Emacs?

It is an AI-powered pair-programming client for Emacs. Inspired by lsp-mode's JSONRPC handling, it connects to an external eca server process to provide interactive chat, code suggestions and context management.

How do I install eca-emacs?

With `M-x package-install eca` from MELPA, or by declaring it with use-package pointing at the repository with `:rev :newest`, or with a Doom Emacs `package!` recipe. The package requires Emacs 28.1 or later.

Where does eca-emacs get the eca server binary?

It checks for `eca-custom-command` first, then for an eca on $PATH, and if it finds neither it downloads eca automatically and caches it. The server is also automatically downloaded by default for UX reasons unless you set eca-custom-command.

How do I attach context to a prompt in eca-emacs?

Type your prompt after the `> ` in the chat window and press RET, and attach more context with the `@` completion, which auto completes after the at sign. There are also commands to add files or directories to the system prompt or the user prompt with multiple modes and range support.

Does eca-emacs let me approve what the assistant does?

Yes. There are commands to accept the next pending tool call, reject the next one, accept all pending tool calls, and accept all of them and remember for the session, and the workspace dashboard shows which chats are pending approval or waiting on an answer.

Official sources

  1. editor-code-assistant/eca-emacs on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/editor-code-assistant-eca-emacs.svg)](https://hysenlabs.com/projects/editor-code-assistant-eca-emacs)

Was this useful?