index rss mastodon twitter github linkedin email
Álvaro Ramírez
sponsor

Álvaro Ramírez

25 September 2025 Introducing Emacs agent-shell (powered by ACP)

Not long ago, I introduced acp.el, an Emacs lisp implementation of ACP (Agent Client Protocol), the agent protocol developed between Zed and Google folks.

While I've been happily accessing LLMs from my beloved text editor via chatgpt-shell (a multi-model package I built), I've been fairly slow on the AI agents uptake. Probably a severe case of old man shouts at cloud sorta thing, but hey I do like well-integrated tools. When I heard of ACP, I knew this was the thing I was waiting for to goof around with agents.

With an early acp.el in place, I set out to build an Emacs-native agent integration, and today I have an initial version of agent-shell I can share.

agent-shell.png

While agent-shell is a native Emacs shell in the comint mode sense (check out Mickey's comint article btw), you don't have to worry about switching between char and line modes to interact with tui utils. agent-shell is a regular Emacs buffer like any other you're used to.

Agent-agnostic

Thanks to ACP, we can now build agent-agnostic experiences by configuring our clients to route traffic to their respective agent. You get multiple agents powering a consistent and familiar experience.

Configuring different agents from agent-shell boils down which agent we want to run in the comms process. Here's an example of Gemini CLI vs Claude Code configuration:

(defun agent-shell-start-gemini-agent ()
  "Start an interactive Gemini CLI agent shell."
  (interactive)
  (agent-shell--start
   :new-session t
   :mode-line-name "Gemini"
   :buffer-name "Gemini"
   :shell-prompt "Gemini> "
   :shell-prompt-regexp "Gemini> "
   :needs-authentication t
   :authenticate-request-maker (lambda ()
                                 (acp-make-authenticate-request :method-id "gemini-api-key"))
   :client-maker (lambda ()
                   (acp-make-client :command "gemini"
                                    :command-params '("--experimental-acp")
                                    :environment-variables (list (format "GEMINI_API_KEY=%s" (agent-shell-google-key)))))))
(defun agent-shell-start-claude-code-agent ()
  "Start an interactive Claude Code agent shell."
  (interactive)
  (agent-shell--start
   :new-session t
   :mode-line-name "Claude Code"
   :buffer-name "Claude Code"
   :shell-prompt "Claude Code> "
   :shell-prompt-regexp "Claude Code> "
   :client-maker (lambda ()
                   (acp-make-client :command "claude-code-acp"
                                    :environment-variables (list (format "ANTHROPIC_API_KEY=%s" (agent-shell-anthropic-key)))))))

I've yet to try other agents. If you get another one running, I'd love to hear about it. Maybe submit a pull request?

Traffic

While I now have an early ACP client available, I'm still fairly new to the protocol. I often inspect traffic in both directions to see what's going on. After staring at json for far too long, I figured I may as well build some tooling around acp.el to make my life easier, so I added a traffic buffer for that. From agent-shell, you can invoke it via M-x agent-shell-view-traffic.

traffic.gif

Fake agents

Developing agent-shell against paid agents got expensive quickly. Not only expensive, but my edit-compile-run cycle also became boringly slow waiting for agents. While I knew I wanted some sort of fake agent to work against, I fought the urge to go down that route. Ok not really, I was lazy, but I did work out a good compromise. Remember that traffic buffer I showed ya? I can save that traffic to disk and then replay it later. This enabled me to run problematic sessions once and quickly replay multiple times to fix bugs. While re-playing has its quirks and limitations, it's done the job for now.

You can see a Claude Code session below, followed by its replayed counterpart via fake infrastructure.

claude.png

fake.png

What next

Took quite a bit of work to get here. Having said that, it's only a start. I myself need to get more familiar with agent usage and evolve the package UX however it feels most natural within its new habitat. Lately, I've been experimenting with a quick diff buffer, driven by n/p keys, shown along with the permission dialog to apply changes.

diff.png

While I've implemented enough parts of the Agent Client Protocol Schema to make the package useful, it's hardly complete. I've yet to fully familiarize myself with all the features.

Take them for a spin

Both of my newest Emacs packages, agent-shell and acp.el, are now available on GitHub. As an end-user, go straight to agent-shell. If you're a package author and would like to build a different ACP experience, then give acp.el a try. Both packages are brand new and may have rough edges. Be sure to file bugs or feature requests as needed.

Paying for LLM tokens? How about sponsoring your Emacs tools?

I've been heads down working on these packages for some time. If you're using cloud LLM services, you're likely already paying for tokens. If you find my work useful, consider routing some of those coins to fund the work. Maybe my tools make you more productive at work? Get your employer to fund the work. These packages take time and effort, but also cost me money. Help fund the work.