[[file:./ai-code-interface.png]]
- AI Code Interface
[[https://melpa.org/#/ai-code][https://melpa.org/packages/ai-code-badge.svg]] [[https://stable.melpa.org/#/ai-code][https://stable.melpa.org/packages/ai-code-badge.svg]] [[https://github.com/tninja/ai-code-interface.el/graphs/contributors][https://img.shields.io/github/contributors/tninja/ai-code-interface.el.svg]] [[https://github.com/RoggeOhta/awesome-codex-cli][https://awesome.re/mentioned-badge.svg]]
An Emacs interface for AI-assisted software development. The purpose is to provide a uniform interface and experience for different AI backends, with context-aware AI coding actions, and integrating seamlessly with AI-driven agile development workflows.
-
Currently it supports these AI coding CLIs:
- [[https://github.com/openai/codex][OpenAI Codex]]
- [[https://pi.dev/][Pi]]
- [[https://antigravity.google/product/antigravity-cli][Antigravity CLI]]
- [[https://opencode.ai/][Opencode]]
- [[https://github.com/anthropics/claude-code][Claude Code]]
- [[https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-cli][GitHub Copilot CLI]]
- [[https://kilo.ai/][Kilo]]
- [[https://grokcli.io/][Grok CLI]]
- [[https://docs.cursor.com/en/cli][Cursor CLI]]
- [[https://github.com/openinterpreter/openinterpreter][Open Interpreter CLI]] (Codex-compatible)
- [[https://kiro.dev/cli/][Kiro CLI]]
- [[https://cnb.cool/codebuddy/codebuddy-code][CodeBuddy Code CLI]]
- [[https://github.com/google-gemini/gemini-cli][Gemini CLI]]
- [[https://aider.chat/][Aider CLI]]
-
It also supports external backend packages:
- [[https://eca.dev/][ECA (Editor Code Assistant)]] (
[[./ai-code-eca.el][ai-code-eca.el]]) - [[https://github.com/xenodium/agent-shell][agent-shell]] ([[https://github.com/xenodium/acp.el][acp.el]])
- [[https://github.com/manzaltu/claude-code-ide.el][claude-code-ide.el]]
- [[https://github.com/stevemolitor/claude-code.el][claude-code.el]]
- [[https://eca.dev/][ECA (Editor Code Assistant)]] (
-
I switch between different CLI-based AI tools in Emacs: Claude Code / OpenAI Codex / Gemini CLI / etc. If you also use different AI tools inside Emacs, but want to keep the same user interface and experience, this package is for you.
-
If you are choosing between the main AI coding packages in Emacs, ask one question first: do you want the deepest integration for one specific agent runtime, or do you want one Emacs workflow that stays stable even when you change AI tools?
-
ai-code-interface.el is built for the second case. Its real advantage is not just backend coverage. Its main advantage is workflow portability: the same menu, context gathering, prompt flow, refactoring commands, TDD helpers, review workflow, prompt files, and Emacs MCP tools continue to work while the backend changes underneath.
-
Screenshot
[[./transient_menu.png]]
** New User Quick Start
If you are new to this package, follow this order:
- Read this section
- Run the setup in Installation
- Try one workflow in Typical Workflows Example
- Configure backend details in AI coding CLI backend
Minimal setup:
#+begin_src emacs-lisp (use-package ai-code :config (ai-code-set-backend 'codex) ;; Optional: use a narrower transient menu on smaller frames ;; (setq ai-code-menu-layout 'two-columns) (global-set-key (kbd "C-c a") #'ai-code-menu)) #+end_src
First 60 seconds:
C-c a a: Start the currently selected AI CLI sessionC-c a c: Ask AI to change current function/regionC-c a q: Ask question only (no code change)C-c a z: Jump back to AI session buffer
The first time you open C-c a, AI Code also shows a small quickstart buffer
with these core actions. You can reopen it later from C-c a h
(Help / Quick Start).
** Installation
Enable installation of packages from MELPA by adding an entry to package-archives after (require 'package) and before the call to package-initialize in your init.el or .emacs file:
#+begin_src emacs-lisp (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize) #+end_src
- Use =M-x package-refresh-contents= or =M-x package-list-packages= to ensure that Emacs has fetched the MELPA package list
- Use =M-x package-install= to install =ai-code= package
- Import and configure =ai-code= in your init.el or .emacs file:
#+begin_src emacs-lisp (use-package ai-code ;; :straight (:host github :repo "tninja/ai-code-interface.el") ;; if you want to use straight to install, no need to have MELPA setting above :config ;; use codex as backend, other options are 'pi, 'claude-code, 'gemini, 'github-copilot-cli, 'open-interpreter, 'opencode, 'kilo, 'grok, 'cursor, 'kiro, 'codebuddy, 'aider, 'eca, 'agent-shell, 'claude-code-ide, 'claude-code-el (ai-code-set-backend 'codex) ;; Optional: default menu stays unchanged; use a narrower 2-column layout on smaller frames ;; (setq ai-code-menu-layout 'two-columns) ;; Enable global keybinding for the main menu (global-set-key (kbd "C-c a") #'ai-code-menu) ;; Optional: Use eat if you prefer, by default it is vterm ;; (setq ai-code-backends-infra-terminal-backend 'eat) ;; config for native CLI backends. for external backends such as agent-shell, claude-code-ide.el and claude-code.el, please check their own config ;; Optional: Try ghostel as an backend infra ;; (setq ai-code-backends-infra-terminal-backend 'ghostel) ;; Optional: Disable @ file completion in comments and AI sessions ;; (ai-code-prompt-filepath-completion-mode -1) ;; Optional: Ask AI to run test after code changes, for a tighter build-test loop (setq ai-code-auto-test-type 'ask-me) ;; Optional: Disable numbered next steps for discussion prompts at send time ;; (enabled by default) ;; (setq ai-code-discussion-auto-follow-up-enabled nil) ;; Optional: In AI session buffers, SPC in Evil normal state triggers the prompt-enter UI (with-eval-after-load 'evil (ai-code-backends-infra-evil-setup)) ;; Optional: Turn on auto-revert buffer, so that the AI code change automatically appears in the buffer (global-auto-revert-mode 1) (setq auto-revert-interval 1) ;; set to 1 second for faster update ;; Optional: Set up Magit integration for AI commands in Magit popups (with-eval-after-load 'magit (ai-code-magit-setup-transients))) #+end_src
** Dependencies
*** Required Dependencies
- Emacs 29.1 or later
org: Org-mode supportmagit: Git integrationtransient: For the menu system- One of vterm (default), eat, or [[https://github.com/dakra/ghostel][ghostel]] needs to be installed to support native AI coding CLI backends, depending on
ai-code-backends-infra-terminal-backend. - [[https://github.com/dakra/ghostel][ghostel]] is a newly supported native backend infra option.
- Ghostel is an Emacs terminal emulator powered by libghostty-vt, the VT engine from Ghostty.
- AI Code enables Ghostel image support for AI sessions:
- terminal programs can use Ghostel's Kitty graphics protocol;
- local image paths printed by an AI CLI (for example =screenshot.png=) are previewed inline in the session buffer while the source path remains visible and clickable.
- tall local previews can use the optional =ultra-scroll= integration described below.
- [[https://github.com/dakra/ghostel][ghostel]] is under active development, please install the latest version.
- To try it:
#+begin_src emacs-lisp (setq ai-code-backends-infra-terminal-backend 'ghostel) #+end_src
*** Optional Dependencies
- [[https://github.com/jdtsmith/ultra-scroll][ultra-scroll]]: Recommended for partial-pixel scrolling past tall local image previews in Ghostel. AI Code loads and dispatches it only while such a preview is visible, without enabling its global mode. Set =ai-code-ghostel-image-preview-prefer-ultra-scroll= to =nil= to opt out.
helm: For an enhanced auto-completion experience (ai-code-input.el).whisper: For speech-to-text input viaai-code-speech-to-text-input. Record audio, pressRETto stop, then choose whether to insert the transcription into the current buffer, send it to the active AI coding session with editable initial input, or copy it to the clipboard.gptel: For intelligent, AI-generated content headlines in the prompt file.- ai-code-task-use-gptel-filename: When non-nil, file name created by
ai-code-create-or-open-task-fileorai-code-create-file-or-dirwill have auto-generated filenames created by GPTel - ai-code-use-gptel-headline: When non-nil, prompts sent to the AI will have auto-generated headlines created by GPTel, providing better organization and readability in the prompt file
- ai-code-use-gptel-classify-prompt: When non-nil, and
ai-code-auto-test-typeorai-code-discussion-auto-follow-up-enabledis non-nil, classify whether the current prompt is about code changes so test prompts or discussion follow-up suggestions are only added when relevant
- ai-code-task-use-gptel-filename: When non-nil, file name created by
flycheck: To enable theai-code-flycheck-fix-errors-in-scopecommand.yasnippet: For snippet support in the prompt file. A library of snippets is included.- (emacs built-in) abbrev + skeleton is also a good way to expand prompt. [[./etc/prompt_expand_with_abbrev_skeleton.el][example abbrev to solve / iterate leetcode problem with tdd (need to set ai-code-auto-test-type with tdd)]], [[./examples/leetcode][example problem resolved]]
projectile: For project root initialization.helm-gtags: For tags creation and symbol navigation fallback from clickable session symbols.
*** Optional Screenshot Capture
The Insert submenu's =Screenshot= commands rely on an external program to capture an image. Install or configure the option for your platform:
| Platform | Screenshot capture | Setup | |-----------------+-----------------------------------+--------------------------------------------| | macOS | =screencapture= | Preinstalled; used by default with =-i=. | | Linux (Wayland) | =grim= | Install =grim=; selected when =WAYLAND_DISPLAY= is set. | | Linux (X11) | =import= from ImageMagick | Install the ImageMagick package. | | Windows | No compatible tool is bundled | Configure a capture program as shown below. |
Customize =ai-code-send-screenshot-command= when the default is unavailable. The command is a list containing the program followed by its arguments; AI Code appends the destination PNG path when invoking it:
#+begin_src emacs-lisp (setopt ai-code-send-screenshot-command '("my-screenshot-program" "--interactive")) #+end_src
** Key Features
- Transient-Driven Hub (
C-c a): One keystroke opens a contextual transient menu that groups every capability (CLI control, code actions, agile workflows, utilities) so you never need to memorize scattered keybindings.- If the default wide layout does not fit your frame well, set
ai-code-menu-layouttotwo-columnsfor a narrower menu with the same commands.
- If the default wide layout does not fit your frame well, set
- AI CLI Session Management: Start (
a), resume (R), or jump back into (z) the active AI CLI buffer, instantly swap backends (s), upgrade them (u), install backend skills (S), edit backend configs (g), open backend agent file (G), and run prompts against the current file (|). It supports multiple sessions per project. TheSentry is especially useful for installing shared skill packs such as [[https://github.com/obra/superpowers][obra/superpowers]].jopens the AI session dashboard, where you can inspect active sessions, refresh the list, visit a session buffer, kill a session, or open the repository's Magit status.Psends a session checkpoint prompt that asks the AI to summarize the goal, files changed, current hypothesis, tests/build result, blockers, and next action.- When resuming, selecting a UUID in the region appends that UUID automatically so you can continue a specific session.
- In AI session side windows,
C-.grows andC-,shrinks the panel immediately. On left/right side windows it adjusts width; on top/bottom side windows it adjusts height.
- AI CLI Editor Viewport: Managed terminal TUI sessions support editing in a native Emacs viewport.
- Within managed AI CLI sessions, general
EDITOR/VISUALrequests auto-submit by default (ai-code-editor-viewport-auto-submitist). Set it tonilto make those requests save-only, includingkubectl editorcrontab -elaunched inside the session; Git editor requests are always save-only.
- Within managed AI CLI sessions, general
- Clickable Session Links: In AI session buffers, supported in-repo file references, nearby code symbols, and
http/httpsURLs are underlined and clickable. File links such assrc/foo.el:42,src/foo.el:42:7,src/foo.el:L42-L60, orsrc/foo.el#L42-L60jump directly to the right location, nearby symbols such assetq-local,ai-code-session-link-enabled, orUserService.processRequest()trigger code navigation in the associated file, and web links open in your browser. Symbol navigation first triesxref, thenhelm-gtagswhen available, and finally falls back to searching in the opened file buffer. Setai-code-session-link-enabledtonilif you want to disable this link rendering. [[./clickable_link_ai_session.png]] - Context-Aware Code Actions: The menu exposes dedicated entries for changing code (
c), implementing TODOs (i), asking questions (q), explaining code (x), sending free-form commands (<SPC>), and refreshing AI context (@). Each command automatically captures the surrounding function, region, or clipboard contents (viaC-u) to keep prompts precise.- When a visible AI session buffer already exists, prompts can be routed to that session directly instead of opening a new one.
- Insert into AI Sessions: Open the configurable
ai-code-menuprefix (C-c ain the configuration examples), then pressIto open the Insert submenu for files, Dired selections, regions, diagnostics-aware DWIM, screenshots, and clipboard images. TheIentry always remains available. If no session is running, pressing it reports that state; if only sessions for other projects are running, it opens the submenu with just theto...entries for choosing one explicitly. An editor viewport associated with the destination session receives the insertion when present; otherwise AI Code inserts into that session's TUI input without submitting it. Screenshot capture may require the [[*Optional Screenshot Capture][platform-specific utility described above]].- Inserted TUI content is always preceded and followed by two newline characters.[fn:insert-tui-spacing] In a viewport, AI Code omits the leading two newlines when the viewport is empty, keeps them when it already contains content, and always appends two newlines. Viewport attachments follow the same spacing rule.
- Agile Development Workflows: Use the refactoring navigator (
r), the guided TDD cycle (t), and the pull/review diff helper (v) to keep AI-assisted work aligned with agile best practices. Prompt authoring is first-class through quick access to the prompt file (p), build/test helper (b), and AI-assisted shell/file execution (!). In prompt files, send the current block withC-c C-c. - Productivity & Debugging Utilities: Initialize project navigation assets (
.), investigate exceptions (e), debug Emacs runtime issues (d), auto-fix Flycheck issues in scope (f), copy file paths formatted for prompts (k), open prompt history (p), capture session notes straight into Org (n), search notes with AI (/), and dictate prompts with speech-to-text (:). - Architecture Document Generation: Derive practical architecture documents for the current repository with
C-c a A(ai-code-derive-architecture-document). The command can generate architecture guardrails, a C4 PlantUML overview, a lightweight DDD context, or a test context document under.ai.code.files/architecture/so future AI coding sessions can reuse module boundaries, dependency rules, runtime flows, and validation expectations. See [[./docs/architecture/c4-overview.org][the C4 architecture overview for this repository]] for an example C4 diagram guide. - Seamless Prompt Management: Open the prompt file via
ai-code-open-prompt-file(stored under.ai.code.files/.ai.code.prompt.orgby default), send regions withai-code-prompt-send-block, and reuse prompt snippets viayasnippetto keep conversations organized. - Interactive Chat & Context Tools: Dedicated buffers hold long-running chats, automatically enriched with file paths, diffs, and history from Magit or Git commands for richer AI responses.
- AI-Assisted Bash Commands: From Dired, shell, eshell, or vterm, run
C-c a !and type natural-language commands prefixed with:(e.g.,:count lines of python code recursively); the tool generates the shell command for review and executes it in a compile buffer.
[fn:insert-tui-spacing] Managed TUI sessions expose rendered terminal contents, not a backend-independent logical input value. AI Code therefore cannot reliably determine whether a TUI input is empty and conservatively keeps the leading separator.
*** Typical Workflows Example
- Changing Code: Position the cursor on a function or select a region of code. Press
C-c a, thenc(ai-code-code-change). Describe the change you want to make in the prompt. The AI will receive the context of the function or region and your instruction. - Implementing a TODO: Write a comment in your code, like
;; TODO: Implement caching for this function. Place your cursor on that line and pressC-c a, theni(ai-code-implement-todo). The AI will generate the implementation based on the comment.- Relevant packages for TODO: [[https://github.com/tarsius/hl-todo][hl-todo]], [[https://github.com/alphapapa/magit-todos][magit-todos]]
- Asking a Question: Place your cursor within a function, press
C-c a, thenq(ai-code-ask-question), type your question, and press Enter. The question, along with context, will be sent to the AI. - Discussion follow-up suggestions:
ai-code-discussion-auto-follow-up-enabledis enabled by default. Set(setq ai-code-discussion-auto-follow-up-enabled nil)to turn it off. Then ask a question withC-c a qor useC-c a <SPC>for a design discussion. When enabled, AI Code asks at send time whether to append 2-3 numbered next-step suggestions, and the transient toggle onC-c a Flets you turn the feature on or off from the menu. - Refactoring a Function: With the cursor in a function, press
C-c a, thenr(ai-code-refactor-book-method). Select a refactoring technique from the list, provide any required input (e.g., a new method name), and the prompt will be generated. - Automatically run tests after change: When ai-code-auto-test-type is non-nil, AI will automatically run tests after code changes and follow up on results.
- One-prompt TDD with refactoring: Press
C-c a, thent(ai-code-tdd-cycle) and choose5. Red + Green + Blue (One prompt)to generate tests, implement code, run tests, and then refactor the changed code in one flow. - Reviewing a Pull Request: Press
C-c a, thenv(ai-code-pull-or-review-diff-file). Choose to generate a diff between two branches. The diff will be created in a new buffer, and you'll be prompted to start a review. Setai-code-default-review-sourcetogithub-mcporgh-clito skip the review source prompt and always use that backend; leave itnil(the default) to be prompted each time. - Reviewing the Current Branch with Difftastic: Press
C-c a, thenv, and chooseReview current branch with difftasticto rundifftastic-magit-difffor a structural review of the current branch. If the =difftastic= package is not installed, AI Code will tell you to install it from MELPA or from [[https://github.com/pkryger/difftastic.el][pkryger/difftastic.el]]. - Multiple Sessions Support: Start more AI coding session with C-c a a after launching one. Select active session with C-c a z. Prompt with above command will be sent to the selected session.
- Speech to Text Input: Press
C-c a, then:(ai-code-speech-to-text-input). Speak your prompt, pressRETto stop recording, then choose whether to insert the transcription into the current buffer, send it to the active AI coding session after editing it inai-code-read-string, or copy it to the clipboard. - Agent Handoff: When switching AI backends or pausing work, press
C-c a Hto have the AI write a neutral handoff log into the task file. Later, in a new backend session, runC-u C-c a Hto feed the entire handoff history back to the new agent.
*** Context Engineering
Context engineering is the deliberate practice of selecting, structuring, and delivering the right information to an AI model so the output is specific, accurate, and actionable. For AI-assisted programming, the model cannot read your whole codebase by default, so the quality of the result depends heavily on the clarity and relevance of the provided context (file paths, functions, regions, related files, and repo-level notes). Good context engineering reduces ambiguity, prevents irrelevant suggestions, and keeps changes aligned with the current code.
This package makes context engineering easy by automatically assembling precise context blocks and letting you curate additional context on demand:
- Automatic file and window context: prompts can include the current file and other visible files (
ai-code--get-context-files-string), so the AI sees related code without manual copying. - Function or region scoping: most actions capture the current function or active region, keeping requests focused (e.g.,
ai-code-code-change,ai-code-implement-todo,ai-code-ask-question). - Manual context curation:
C-c a @(ai-code-context-action) stores file paths, function anchors, or region ranges in a repo-scoped list, which is appended to prompts viaai-code--format-repo-context-info. In a Dired buffer,C-c a @(ai-code-context-action) can store the marked files or directories as repo context; if nothing is explicitly marked, it falls back to the file or directory at point. - Optional clipboard context: prefix with
C-uto append clipboard content to prompts for external snippets or logs. - @-triggered filepath completion in comments and AI sessions. Type
@to open a completion list of recent and visible repo files, then select a path to insert. - Dired-aware prompt context: Dired-based actions such as code change, question asking, and explain can use marked entries or the current entry as prompt context, so the AI receives the exact file or directory targets you selected in the directory view.
- Prompt suffix guardrails: set
ai-code-prompt-suffixto append persistent constraints to every prompt (whenai-code-use-prompt-suffixis non-nil). Example:(setq ai-code-prompt-suffix "Only use English in code file, but Reply in Simplified Chinese language").
Example (focused refactor with curated context):
- In a buffer, run
C-c a @to add the current function or selected region to stored repo context. - Open another related file in a window so it is picked up by
ai-code--get-context-files-string. - Place the cursor in the target function and run
C-c a cto request a change. The generated prompt will include the function/region scope, visible file list, and stored repo context entries, giving the AI exactly the surrounding information it needs.
- MCP can provide critical context to AI model. You can use C-c a g to open and add mcp config for corresponding AI coding CLI. Examples MCPs:
- [[https://github.com/github/github-mcp-server][Github MCP]]
- [[https://github.com/sooperset/mcp-atlassian][Atlassian MCP]]
- [[https://github.com/crystaldba/postgres-mcp][Postgresql MCP]] / Sqlite MCP
- [[https://github.com/docker/mcp-gateway][Docker]] / [[https://github.com/containers/kubernetes-mcp-server][Kubernetes]] MCP
**** Built-in Emacs MCP Tools
AI Code includes an Emacs MCP server with these built-in tools:
- =project_info=: summarize the current project, active buffer, and file count
- =editor_state=: inspect the currently selected buffer, point, mode, region, and buffer flags
- =visible_buffers=: list the buffers visible in the selected frame windows
- =buffer_query=: read buffer contents, optionally by line range
- =get_diagnostics=: return Flycheck or Flymake diagnostics for one file or open project buffers
- =get_project_files=: list regular files in the current project
- =get_project_buffers=: list open buffers that belong to the current project
- =imenu_list_symbols=: list useful symbols from a file via imenu
- =xref_find_references=: find references to an identifier in project context
- =xref_find_definitions_at_point=: find definitions at a file location
- =treesit_info=: inspect tree-sitter node information for a file location
Additional debugging tools come from =ai-code-mcp-debug-tools.el= and are enabled by default:
This make emacs runtime debugging possible. With emacs debugging mcp enabled, you can simply ask AI to trouble shooting your emacs lisp related problem (could deep inside some installed package), AI can automatically figure out the problem and suggest how to fix / perform the fix
#+begin_src emacs-lisp (setq ai-code-mcp-debug-tools-enabled t) ;; default ;; (setq ai-code-mcp-debug-tools-enabled nil) ;; disable them #+end_src
These tools add:
- =get_variable_value=: return the printed value of an Emacs variable by name
- =get_variable_binding_info=: inspect current and default bindings for an Emacs variable
- =get_function_info=: inspect function metadata such as kind, aliasing, and advice state
- =get_feature_load_state=: inspect whether an Emacs feature is loaded and where it comes from
- =get_recent_messages=: return the latest lines from =Messages=
- =get_last_error_backtrace=: return the most recently recorded Emacs command error snapshot
- =eval_elisp=: evaluate arbitrary Emacs Lisp with possible side effects in a chosen buffer context when explicitly enabled (no restrictions once enabled)
The old =ai-code-mcp-editor-tools.el= module has been removed. Its live-editor read tools are now built in, while =eval_elisp= remains an explicit opt-in.
To register =eval_elisp=:
#+begin_src emacs-lisp (setq ai-code-mcp-debug-tools-enable-eval-elisp t) #+end_src
Once enabled, =eval_elisp= can evaluate any Emacs Lisp form without restrictions. It takes =code= (a single top-level form), optional =buffer_name= or =file_path= for evaluation context, optional =capture_messages= to collect new =Messages= output, optional =include_backtrace= to include a backtrace on failure, and optional =timeout_ms=. This is useful for letting the AI apply fixes by evaluating modified function definitions directly.
screenshot inside Codex cli:
[[file:./emacs_mcp_tools.png]]
- Emacs mcp use cases
- [[./docs/emacs-package-cleanup-with-ai-agent.org][Unused package clean up]]
***** Use It with an AI CLI
Set the backend to =claude-code=, =codex=, or =github-copilot-cli= and start a session with =C-c a a=. AI Code will:
- start a local Emacs MCP HTTP server
- register the current project/buffer as the MCP session context
- inject a session-scoped MCP config into that agent session automatically
Auto-wiring is currently enabled for =claude-code=, =codex=, and =github-copilot-cli=.
If you disabled it before, enable it again with:
#+begin_src emacs-lisp (setq ai-code-mcp-agent-enabled-backends '(claude-code codex github-copilot-cli)) #+end_src
***** Make Sure It Works
- Start =claude-code=, =codex=, or =github-copilot-cli= with =C-c a a= from the file or project you want to work on.
- Switch to the agent buffer and run =M-x ai-code-mcp-agent-show-buffer-status=.
If it shows =:backend=, =:session-id=, and a local =:server-url=, then Emacs has attached MCP to this session.
- Then ask the agent to use one of the Emacs tools, for example:
- use =project_info= and tell me the current project info
- use =imenu_list_symbols= for the current file
- use =get_diagnostics= and summarize the current file diagnostics
The status command only proves the Emacs side is wired. The real proof is that the agent returns your current project path, buffer context, or current-file symbols from those tools.
***** Add a New MCP Tool
- Define an Emacs Lisp function.
#+begin_src emacs-lisp (defun ai-code-mcp-current-buffer-name () "Return the current buffer name for the active MCP session." (buffer-name (current-buffer))) #+end_src
- Register it as an MCP tool before you start the AI agent session:
#+begin_src emacs-lisp (require 'ai-code-mcp-server)
(ai-code-mcp-make-tool :function #'ai-code-mcp-current-buffer-name :name "current_buffer_name" :description "Return the current Emacs buffer name." :args nil) #+end_src
-
Start =claude-code=, =codex=, or =github-copilot-cli= with =C-c a a=. If the agent session is already running, restart it after registering the new tool.
-
Ask the agent to use the tool, for example:
- use =current_buffer_name= and tell me the current Emacs buffer name
- If you want to verify from Emacs first, run:
#+begin_src emacs-lisp (ai-code-mcp-dispatch "tools/list") #+end_src
If =current_buffer_name= appears in the tool list, Emacs has registered it. If the agent can call it and returns the expected buffer name, the tool is available inside the AI coding session.
***** Use the MCP Core Directly from Elisp
If you want to use the MCP core without an AI CLI, you can still call it directly:
#+begin_src emacs-lisp (require 'ai-code-mcp-server) (ai-code-mcp-builtins-setup) (ai-code-mcp-dispatch "tools/list") #+end_src
To expose your own Emacs function as a tool, use =ai-code-mcp-make-tool=.
- [[https://martinfowler.com/articles/exploring-gen-ai/context-engineering-coding-agents.html][Context Engineering for Coding Agents]], recommended by Martin Fowler.
*** Harness Engineering Practice
Harness engineering is about building a reliable loop around the model, so the AI does not stop at /make a change/ but continues into /verify the change and react to the result/. In this package, the clearest examples are the auto test loop for code changes and the optional next-step loop for discussion prompts.
Instead of manually telling the AI what to do after every code change or discussion turn, you can make follow-up part of the workflow:
ai-code-auto-test-type: choose how code-change prompts should continue after the edit. You can ask the AI to run tests after the change, use TDD Red+Green, use Red+Green+Blue with refactoring, turn it off, or decide case by case withask-me.ai-code-discussion-auto-follow-up-enabled: when non-nil, discussion-style prompts can offer a send-time choice to append 2-3 numbered candidate next steps. You can customize this variable directly or toggle it from the transient menu withC-c a F.ai-code-next-step-suggestion-suffix: customize the exact instruction appended for those numbered next-step suggestions.ai-code-use-gptel-classify-prompt: when paired with the settings above, GPTel can classify prompts so code-change prompts skip discussion follow-up suggestions and discussion prompts skip test follow-up.ai-code-tdd-cycle: run a guided TDD flow from the menu, including separate Red, Green, Blue stages or the combined one-prompt flows.ai-code-build-or-test-project: run build/test explicitly fromC-c a bwhen you want a direct verification step in the middle of the loop.ai-code-prompt-suffix: add persistent project rules when needed, so repeated instructions such as response language, coding constraints, or test expectations do not have to be retyped in every prompt.ai-code-grill-me-enabled: when non-nil, offer a one-shot clarification step (/"Grill me before acting?"/) immediately before the completed prompt is sent forai-code-code-change,ai-code-ask-question,ai-code-implement-todo, andai-code-send-command. When accepted, the AI reads the bundled =prompt/grilling.v1.md= harness and asks targeted clarifying questions before acting, reducing ambiguity in the request. The harness is adapted from [[https://github.com/mattpocock/skills/blob/main/skills/productivity/grilling/SKILL.md][mattpocock/skills – grilling]]. Disabled by default; enable it with: #+begin_src emacs-lisp (setq ai-code-grill-me-enabled t) #+end_src- [[https://github.com/obra/superpowers][obra/superpowers]] pair well with these features.
With the built-in =get_diagnostics= MCP tool, the loop can move further left:
- record a diagnostics baseline before editing so the AI knows which warnings or errors already existed
- re-run =get_diagnostics= after each edit on the touched files before moving on to slower test commands
- treat completion as /no new diagnostics/ on the touched files relative to the baseline, instead of requiring the entire project to be clean
- use tests as the next sensor in the loop, not the first one
Screenshot:
[[file:./emacs_mcp_tool_diagnosis.png]]
The benefit is practical:
- faster feedback after each AI code change
- less context switching between prompting, testing, and follow-up fixes
- more consistent AI behavior because verification is part of the workflow
- easier to let the AI continue with the next step after a failed or passing test
This is why features such as ai-code-auto-test-type, ai-code-discussion-auto-follow-up-enabled, ai-code-grill-me-enabled, and ai-code-tdd-cycle fit the idea of harness engineering: they turn testing, clarification, and follow-up into part of the system, not an afterthought in each prompt.
Nit: During using auto test feature, I prefer to turn off the approval request from AI, it will make the whole process more smooth. Eg. for Codex CLI, it is
#+begin_src emacs-lisp (setq ai-code-codex-cli-program-switches '("-a" "never")) #+end_src
- Relevant article: [[https://martinfowler.com/articles/exploring-gen-ai/harness-engineering.html][Harness Engineering]]
*** Desktop Notifications (Experimental)
When working with multiple AI sessions, it can be useful to receive desktop notifications when AI responses are complete. This is especially helpful when you prompt an AI and then switch to other tasks while waiting for the response.
**** Enabling Notifications
- Notifications are disabled by default.
- Press
C-c athenNto toggle notifications on/off. - Alternatively, use
M-x ai-code-notifications-toggle. - To enable notifications in your config: #+begin_src emacs-lisp (setq ai-code-notifications-enabled t) #+end_src
**** How It Works
- The package monitors terminal activity in AI session buffers.
- When the terminal has been idle for ~5 seconds (configurable via
ai-code-backends-infra-idle-delay), it's considered a completed response. - If the AI session buffer is not currently visible/focused, a desktop notification is sent.
- Notifications are throttled to avoid spam (minimum 2 seconds between notifications).
**** Platform Support
- On Linux with D-Bus, native desktop notifications are used.
- On other platforms, notifications appear in the Emacs minibuffer.
*** Portable Agent Handoff via Task Files
To transfer development work between different AI coding backends (e.g., from Codex to Antigravity CLI) without relying on backend-specific session histories, ai-code-interface.el supports portable agent handoffs using Org-mode task files.
- Create or Open Task Files (
K/ai-code-create-or-open-task-file): Quickly initialize a new task file (by default under.ai.code.files/) with date, branch, selected backend, and structured Org headings (Task Description,Investigation,Code Change). - Generate Portable Handoff (
H/ai-code-agent-handoff):- Run
C-c a H(without a prefix) when not on an Org heading to ask the current AI agent to append a structured handoff section (* Agent Handoff YYYY-MM-DD HH:MM) summarizing the task objective, current progress, files modified, design decisions, failed approaches, test results, and a startup prompt for the next agent. - Run
C-c a Hwith a prefix argument (e.g.C-u C-c a H) to load the whole task file as neutral handoff context in a new AI session. - Run
C-c a Hwhen the cursor is positioned on an Org heading to load only that specific subtree as prompt context for the active session.
- Run
** AI coding CLI backend
*** Backend Configuration This package acts as a generic interface that requires a backend AI assistant package to function. You can configure it to work with different backends.
- Press
C-c ato open the AI menu, thensto "Select Backend". - Pick one of the supported backends and the integration will switch immediately.
- The selection updates the start/switch/send commands and, for CLI backends, the CLI used by
ai-code-apply-prompt-on-current-file. - Press
C-c athenS(ai-code-install-backend-skills) to install backend skills for the currently selected backend.- If a backend does not define its own installer,
Sfalls back to prompting the active AI CLI to read a skills repository README and perform setup. - The default suggested repository is [[https://github.com/obra/superpowers][obra/superpowers]], which is a very useful starting point for adding reusable coding skills to supported CLIs.
- A practical workflow is: press
C-c a, thenS, keep the default URL, and let the backend read the repository README and install the skills it describes. - [[https://github.com/obra/superpowers][obra/superpowers]] pair well with this package's existing harness-oriented workflows, especially the
ai-code-auto-test-typefeedback loop,ai-code-tdd-cycle, andai-code-pull-or-review-diff-filecode review flow.
- If a backend does not define its own installer,
Natively supported options:
- [[https://github.com/openai/codex][OpenAI codex CLI]] (
[[./ai-code-codex-cli.el][ai-code-codex-cli.el]]) - [[https://pi.dev/][Pi]] (
[[./ai-code-pi.el][ai-code-pi.el]]) - [[https://antigravity.google/product/antigravity-cli][Antigravity CLI]] (
[[./ai-code-antigravity-cli.el][ai-code-antigravity-cli.el]]) - [[https://opencode.ai/][Opencode]] (
[[./ai-code-opencode.el][ai-code-opencode.el]]) - [[https://github.com/anthropics/claude-code][Claude Code]] (
[[./ai-code-claude-code.el][ai-code-claude-code.el]])- Binds =Shift+Enter=/=Ctrl+Enter= inside Claude sessions to send Claude's multiline input sequence.
- [[https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-cli][GitHub Copilot CLI]] (
[[./ai-code-github-copilot-cli.el][ai-code-github-copilot-cli.el]])- Sets =TERM_PROGRAM=vscode= by default and binds =Shift+Enter=/=Ctrl+Enter= inside Copilot sessions to emulate Copilot CLI's VS Code multiline setup.
- [[https://github.com/google-gemini/gemini-cli][Gemini CLI]] (
[[./ai-code-gemini-cli.el][ai-code-gemini-cli.el]]) - [[https://kilo.ai/][Kilo]] (
[[./ai-code-kilo.el][ai-code-kilo.el]]) - [[https://grokcli.io/][Grok CLI]] (
[[./ai-code-grok-cli.el][ai-code-grok-cli.el]]) - [[https://docs.cursor.com/en/cli][Cursor CLI]] (
[[./ai-code-cursor-cli.el][ai-code-cursor-cli.el]]) - [[https://github.com/openinterpreter/openinterpreter][Open Interpreter CLI]] (
[[./ai-code-open-interpreter-cli.el][ai-code-open-interpreter-cli.el]]) - [[https://kiro.dev/cli/][Kiro CLI]] (
[[./ai-code-kiro-cli.el][ai-code-kiro-cli.el]]) - [[https://cnb.cool/codebuddy/codebuddy-code][CodeBuddy Code CLI]] (
[[./ai-code-codebuddy-cli.el][ai-code-codebuddy-cli.el]]) - [[https://aider.chat/][Aider CLI]] (
[[./ai-code-aider-cli.el][ai-code-aider-cli.el]])
It also supports external backends through customization of the ai-code-backends variable; currently it includes:
- [[https://eca.dev/][ECA (E
No comments yet
Be the first to share your take.