[[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]]
AI Code Interface is a backend-agnostic Emacs workflow layer for AI-assisted software development.
Use Codex, Claude Code, Gemini CLI, Pi, agent-shell/ACP, and other coding agents while keeping the same Emacs workflow for context, prompting, code changes, review, TDD, Git, tasks, and session management.
** Why AI Code Interface?
AI coding agents change quickly. AI Code Interface keeps your developer workflow stable while allowing the agent underneath to change: the backend can change; your Emacs workflow does not have to.
If you want the deepest possible integration with one specific agent runtime, a dedicated client may be a better fit. If you use or evaluate multiple coding agents and want one consistent Emacs workflow, AI Code Interface is built for that.
Workflow portability is the core idea:
- Keep the same context and prompt workflow.
- Keep the same code-change, review, refactoring, and TDD workflow.
- Keep the same task, Git, MCP, and session workflow.
- Switch the AI backend without rebuilding your Emacs setup.
** Design Philosophy
AI Code Interface unifies developer workflows, not agent runtimes.
Native coding CLIs keep ownership of their own interaction model, tool execution, retries, queueing or steering, permissions, and other runtime behavior. AI Code Interface integrates with those capabilities rather than reimplementing them.
Structured external backends such as agent-shell/ACP can provide deeper lifecycle and UI integration when available, without making those semantics a requirement for every backend. This keeps the common workflow portable while allowing each backend to use its native strengths.
See [[https://github.com/tninja/ai-code-interface.el/tree/main#ai-coding-cli-backend][AI coding CLI backend]] for the full backend list and configuration details.
- 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: Show candidates as you type in task file, using company ;; (add-hook 'ai-code-prompt-mode-hook #'ai-code-prompt-completion-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
** Windows
Native Windows Emacs is supported. Ghostel is the recommended terminal backend because it uses ConPTY and provides pre-built Windows native modules. If the default vterm backend cannot start on native Windows, AI Code automatically falls back to Ghostel. See [[./docs/windows.org][Native Windows Support]] for setup and troubleshooting.
** 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.
- while a local preview is visible, line scrolling (=scroll-up-line=, =scroll-down-line=, evil's =C-e= / =C-y=) and the plain mouse wheel move by pixels, one line height per step, instead of jumping a whole image.
- [[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 the =Fix Flycheck errors in scope= action under =C-c a b= and 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]]
cape/company: For inline completion of prompts you have written before, described under [[*Reusing Prompts You Already Wrote][Reusing Prompts You Already Wrote]]. Prompt completion itself needs neither package.cape, when installed, adds English dictionary words to the same candidate list with no configuration;companyshows the candidates as you type once you opt in. Neither is a dependency, and neither is loaded when it is not installed.projectile: For project root initialization.
*** 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.Hsends a session checkpoint prompt when run from an AI session buffer, asking 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, , or jump directly to the right location, nearby symbols such as , , or trigger code navigation in the associated file, and web links open in your browser. Symbol navigation first tries , then when available, and finally falls back to searching in the opened file buffer. Set to if you want to disable this link rendering. [[./clickable_link_ai_session.png]]
[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. - Value-driven Simplification: Press
C-c a rand choose the second entry to discuss either the current branch (relative to a selected base, with an explicit choice about uncommitted changes) or a repository topic. The AI investigates code and asks one question at a time; you decide what to keep and how to simplify. This entry starts a discussion and does not edit code. - 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 choose to generate tests, implement code, run tests, and then refactor the changed code in one flow.
*** Reusing Prompts You Already Wrote
Most of what you retype into a prompt is wording, not structure: "explain the current code", the handoff instructions you send at every backend switch. This completes those from the prompt history files AI Code already keeps, across every repository it knows about -- projectile's known projects, ai-code-prompt-completion-roots, the current directory and the fallback location, with remote (Tramp) roots skipped so completion never opens a connection. Point ai-code-prompt-completion-files (nil by default) at files of your own -- a prompt library you keep by hand, a diary, any Org file whose wording you reuse. Setting ai-code-prompt-completion-use-org-roam adds the notes org-roam tracks the same way -- off by default, since a whole zettelkasten contributes note sections rather than prompts. In both, every headline offers two prompts however deep it sits, its own text and the text written under it, and whatever stands before the first headline -- the whole of a file written without any -- is split on blank lines. Datetree headlines, tags, statistics cookies and link wrappers are markup rather than wording and drop out, as does a heading of a word or two, quicker typed than picked from a popup. Neither history filter below applies there: you wrote those files, so they are offered as written. A large diary is worth measuring before you point at it -- 10MB of Org indexes in about a second and contributes on the order of 10^5 candidates.
It needs no configuration: opening a prompt file installs the capf, so completion-at-point (=M-TAB=) offers your earlier prompts right away, and if =cape= is installed its cape-dict words join the same candidate list. Only the popup front-end is left to you:
#+begin_src emacs-lisp ;; Show candidates as you type, using company (add-hook 'ai-code-prompt-mode-hook #'ai-code-prompt-completion-setup) #+end_src
Both =cape= and =company= are optional: neither is a dependency, and neither is loaded when it is not installed. Set ai-code-prompt-completion-enable-company to nil when a front-end such as corfu shows the candidates instead, or (remove-hook 'ai-code-prompt-mode-hook #'ai-code-prompt-completion--enable) to opt out completely. If your own config already merges capfs with cape, add ai-code-prompt-completion-capf to that list rather than relying on the default: the first capf at a given hook depth answers, and yours is added first.
Candidates are the prompts you wrote by hand, ranked by how often you wrote them, shown as a truncated first line and inserted whole. A prompt is recalled from any word of three characters or more in its first line, not only the opening one, and choosing it rewrites the line from the start when what you already typed there opens that same prompt -- so a half-finished - Go ahead with the suggested refac completes in place, while a TODO: of your own stays put. Matching still begins at a word: Emacs only offers a non-exclusive capf once plain prefix completion could succeed, so factor reaches refactoring only if your own completion-styles include flex. Prompts AI Code generated itself are left out by prefix (ai-code-prompt-completion-template-prefixes), and anything longer than ai-code-prompt-completion-max-lines is dropped as a one-off paste. The index is cached for the session; ai-code-prompt-completion-refresh rebuilds it.
One caveat on the dictionary half: cape-dict reads /usr/share/dict/words, which on macOS is Webster's 1934 edition. For a modern list, generate one and point cape-dict-file at it:
#+begin_src sh aspell -d en dump master | aspell -l en expand | tr ' ' '\n' | sort -u \
~/.emacs.d/dict-en.txt #+end_src
*** 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). -
Tree-sitter semantic scope: when the current buffer has an active Tree-sitter parser, prompts carry structural context derived from the real syntax tree instead of just a function name. A prompt for a method now includes its enclosing type, both declaration headers, and the function's line range:
#+begin_example Enclosing class: UserService Class definition: class UserService(BaseService): Function: find_user Function definition: def find_user(self, user_id: int) -> str: Function range: lines 2-4 #+end_example
-
Tree-sitter
@#symbol completion: after picking a file with@(e.g.,@src/service.py), type#to pick a symbol from that file. When Tree-sitter is active (python-ts-mode,rust-ts-mode, etc.), candidates are qualified names in file-definition order (Bar,Bar.baz), each annotated with its header and line (def baz(self): line 4); otherwise it falls back to an alphabetically sortedimenulist. Works in comments,*.prompt.orgbuffers, and AI session buffers.
Screenshot:
[[file:./symbol-completion-example-screenshot.png]]
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
**** Agent actions on Magit hunks
Place point on a textual hunk in Magit status, diff, or revision buffers, then use the existing AI commands:
| Key | Action on selected hunks | |-----+--------------------------| | =C-c a x= | Explain behavior changes, assumptions, and risks (read-only) | | =C-c a q= | Ask a question about the patch (read-only) | | =C-c a c= | Apply requested feedback to current working-tree source | | =C-c a t= | Add useful missing regression tests for the existing change | | =C-c a @= | Add or copy a patch snapshot through the context menu |
Use Magit's section selection to select multiple sibling hunk headings. A text selection inside one hunk includes the complete hunk and marks the selected excerpt as the focus. Invalid selections, binary diffs, combined merge hunks, and file headings are rejected by the hunk actions. The copy command still copies the branch name elsewhere in a Magit status buffer.
Context includes the repository, file paths, displayed diff provenance, HEAD at capture, and capture time. Stored hunks are snapshots: refresh Magit and capture again to update them. Staged hunks describe the index; edit and test requests tell the agent to re-read current source, preserve unrelated changes, and avoid staging or committing. Historical diffs support explain, question, and context capture; switch to a current status hunk before asking for edits or tests.
In Magit, =C-c a t= checks existing coverage and adds tests only where useful. The agent runs verification and reports commands and results. It does not claim a test-first Red/Green cycle for code already written, and it reports production failures without changing production code. This action and the read-only actions suppress automatic implementation TDD suffixes for that send. File-buffer TDD behavior is unchanged. =C-u= adds clipboard context to hunk questions and change requests, as it does in file buffers.
**** 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=, =github-copilot-cli=, or =antigravity= 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=, =github-copilot-cli=, =open-interpreter=, and =antigravity=.
Antigravity does not expand environment variables in MCP headers, so AI Code temporarily writes the session token to =.agents/mcp_config.json= with private permissions. Existing JSON configuration is merged and restored byte for byte when the last Antigravity session exits. If the file changes outside AI Code while a session is active, cleanup leaves the edited file untouched rather than overwriting it.
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 open-interpreter antigravity)) #+end_src
***** Make Sure It Works
- Start =claude-code=, =codex=, =github-copilot-cli=, =open-interpreter=, or =antigravity= 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. The =ask-me= choices also include Uncle Bob's coding agent harness and harness+; the original keeps the evidence-first gauntlet, while harness+ adds maintainability sensors and semantic modularity checks.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, lint, or scoped Flycheck fixes fromC-c a bwhen you want a direct verification or diagnostics 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_srcai-code-use-compose-buffer: when non-nil, edit prompts longer than two lines in a full =AI Compose= buffer instead of the minibuffer. Accept with =C-c C-c=, cancel with =C-c C-k=; =@= file completion works as in prompt buffers. Every invocation starts from a fresh buffer and any stale compose buffer is discarded. Disabled by default; enable it with: #+begin_src emacs-lisp (setq ai-code-use-compose-buffer t) #+end_src
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-or-checkpoint):C-c a Hpicks its behavior from the current buffer.- In an Org buffer, run
C-c a H(without a prefix) outside any handoff section 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 Hanywhere inside a handoff section, or with the cursor on any Org heading, to load only that subtree as prompt context for the active session. The cursor does not have to sit on the handoff headline itself. - In an AI session buffer,
C-c a Hsends the session checkpoint prompt (ai-code-session-checkpoint) instead. - In any other buffer,
C-c a Hasks which of the two actions to run.
- In an Org buffer, 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://developer.meta.com/ai/products/muse-code][Muse Code]] (
[[./ai-code-muse-cli.el][ai-code-muse-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]] ()
It also supports external backends through customization of the ai-code-backends variable; currently it includes:
- [[https://eca.dev/][ECA (Editor Code Assistant)]] (
[[./ai-code-eca.el][ai-code-eca.el]]) - [[https://github.com/xenodium/agent-shell][agent-shell]] (
[[./ai-code-agent-shell.el][ai-code-agent-shell.el]]) - Claude Code IDE (
[[https://github.com/manzaltu/claude-code-ide.el][claude-code-ide.el]]) - Claude Code (
[[https://github.com/stevemolitor/claude-code.el][claude-code.el]])
**** ECA (Editor Code Assistant) backend setup Install the [[https://eca.dev/][eca]] Emacs package, which provides the =eca=, =eca-session=, =eca-chat-open=, =eca-chat-send-prompt=, and =eca-chat--get-last-buffer= functions. Then select the backend in your config: #+begin_src emacs-lisp (ai-code-set-backend 'eca) #+end_src Note: =ai-code-apply-prompt-on-current-file= is CLI-pipe based and is not supported when =eca= is the active backend.
**** agent-shell backend setup
Install [[https://github.com/xenodium/agent-shell][agent-shell]] and its dependency [[https://github.com/xenodium/acp.el][acp.el]], then configure one of the ACP agent providers in agent-shell (for example Codex, Gemini, Opencode, etc.).
Select agent-shell via ai-code-select-backend (or (ai-code-set-backend 'agent-shell) in your config).
Note: ai-code-apply-prompt-on-current-file is CLI-pipe based and is not supported when agent-shell is the active backend.
**** Pi setup Install Pi with =npm install -g --ignore-scripts @earendil-works/pi-coding-agent=, or use the installer documented at [[https://pi.dev/][pi.dev]]. Ensure the =pi= executable is on your PATH, authenticate with an API key or =/login=, and select the backend with =C-c a s= or =(ai-code-set-backend 'pi)=. Customize =ai-code-pi-program= or =ai-code-pi-program-switches= to change the executable or startup flags. Once selected, =C-c a a= starts Pi and =C-c a R= resumes a session. In Pi session buffers, Shift+Enter and Ctrl+Enter insert a newline, and Ctrl+Escape sends Escape to cancel the current operation.
**** Grok CLI setup
Install [[https://grokcli.io/][grok-cli]] and ensure the grok executable is on your PATH.
Customize ai-code-grok-cli-program or ai-code-grok-cli-program-switches if you want to
point at a different binary or pass additional flags (for example,
selecting a profile). After that, select the backend through
ai-code-select-backend or bind a helper in your config.
**** CodeBuddy Code CLI setup
Install CodeBuddy Code CLI via npm: =npm install -g @tencent-ai/codebuddy-code=, or via Homebrew: =brew install Tencent-CodeBuddy/tap/codebuddy-code=.
Ensure the codebuddy executable is on your PATH.
Customize ai-code-codebuddy-cli-program or ai-code-codebuddy-cli-program-switches if you want to
point at a different binary or pass additional flags. After that, select the backend through
ai-code-select-backend or bind a helper in your config.
To resume previous conversations, use =-c= flag (automatically handled by the resume command).
**** Antigravity CLI setup
Install Antigravity CLI on macOS / Linux with:
=curl -fsSL https://antigravity.google/cli/install.sh | bash=
Review the script before piping it to your shell.
Ensure the agy executable is on your PATH.
Customize ai-code-antigravity-cli-program or ai-code-antigravity-cli-program-switches if you want to
point at a different binary or pass additional flags. After that, select the backend through
ai-code-select-backend or bind a helper in your config.
The resume command adds =--continue= automatically.
Emacs MCP tools are wired automatically through a temporary workspace
=.agents/mcp_config.json= entry when this backend is enabled in
=ai-code-mcp-agent-enabled-backends=.
**** Muse Code setup Install Muse Code on macOS or Linux with: =curl -fsSL https://dev.meta.ai/install.sh | bash= Review the script before piping it to your shell, then ensure the =muse= executable is available to Emacs through =PATH= and =exec-path=. Customize =ai-code-muse-cli-program= or =ai-code-muse-cli-program-switches= to use a different executable or pass additional startup flags. Select the backend with =ai-code-select-backend=. The resume command runs =muse resume=.
**** Open Interpreter CLI setup
[[https://github.com/openinterpreter/openinterpreter][Open Interpreter CLI]] is treated as a Codex-compatible CLI. It can be installed with:
=curl -fsSL https://www.openinterpreter.com/install | sh=
Ensure the interpreter executable is on your PATH.
Customize ai-code-open-interpreter-cli-program or ai-code-open-interpreter-cli-program-switches if needed.
The backend config command opens =~/.openinterpreter/config.toml=.
Then select the backend:
#+begin_src emacs-lisp
(ai-code-set-backend 'open-interpreter)
#+end_src
Resume runs =interpreter resume --last= to reopen the most recent session.
How to setup [[https://www.openinterpreter.com/docs/terminal/kimi-k3?utm_source=github&utm_medium=referral&utm_campaign=readme&utm_content=kimi_k3_docs][Kimi K3 for Open Interpreter CLI]]
You can add other backends by customizing the ai-code-backends variable.
**** Add a new AI coding CLI backend
-
[[https://github.com/tninja/ai-code-interface.el/pull/2][This PR]] adds github-copilot-cli. It can be an example to add basic support for other AI coding CLI.
-
Open an issue, post information about the new AI coding CLI backend (eg. cursor CLI?), at least providing the command line name. You can also include the version upgrade command, how to resume, where the configuration files are located, and so on. We can ask GitHub Copilot to add support features based on the issue.
** [[https://github.com/tninja/aider.el/blob/main/appendix.org#be-careful-about-ai-generated-code][Why Agile development with AI?]]
** FAQ
*** Q: [[https://github.com/tninja/ai-code-interface.el/issues/398][Unable to Esc to go back after invoking the slash commands in claude-code shell?]]
- A: Use Ctrl + esc key instead
*** Q: When test-after-change / TDD mode is enabled, AI keeps asking for tool-use approval. How can I make this smoother?
-
A: Enable auto-approval for your active AI coding CLI. For example, in Codex CLI, you can enable the following flag. #+begin_src elisp (setq ai-code-codex-cli-program-switches '("-a" "never")) #+end_src
-
For antigravity cli, it is
#+begin_src elisp (setq ai-code-antigravity-cli-program-switches '("--dangerously-skip-permissions")) #+end_src
- For github copilot cli, it is #+begin_src elisp (setq ai-code-github-copilot-cli-program-switches '("--allow-all")) #+end_src
*** Q: Codex CLI use my API key, instead of my ChatGPT Plus subscription and cost money, how to fix that?
- A: use
codex loginto login with your OpenAI account that has ChatGPT Plus subscription. After that, Codex CLI will use your ChatGPT Plus subscription automatically. To confirm, check with /status inside the codex CLI buffer.
*** Q: Using Opencode as backend, it might have performance issues with eat.el in Doom Emacs. [[https://github.com/tninja/ai-code-interface.el/issues/9#issuecomment-3543277108][Issue]]
- A: Use vterm as the backend; Opencode won't trigger mouse hover and will not cause Emacs flickering. Setting "theme" to "system" in the Opencode config can reduce glitches. From [[https://github.com/tninja/ai-code-interface.el/issues/9#issuecomment-3543335121][gkzhb's answer]]: #+begin_src json { "$schema": "https://opencode.ai/config.json", "theme": "system" } #+end_src
*** Q: During using ghostel terminal backend, for long conversation, I found the earliest conversation got truncated
- A: Ghostel trims old output after
ghostel-max-scrollbackbytes are used. The default is 5 MB, so increase it before starting Ghostel sessions. #+begin_src elisp (setq ghostel-max-scrollback (* 20 1024 1024)) ; 20 MB #+end_src
*** Q: How does image display work with the ghostel terminal backend?
-
A: Ghostel supports the Kitty graphics protocol. AI Code additionally previews local image file paths printed in Ghostel AI session buffers. You can tune this with: #+begin_src elisp ;; Native Kitty graphics file-loading mediums for trusted local sessions. (setq ai-code-backends-infra-ghostel-kitty-graphics-mediums '(file temp-file))
;; Inline preview for image paths printed by the AI CLI. (setq ai-code-session-link-ghostel-image-preview-enabled t) (setq ai-code-session-link-ghostel-image-preview-max-bytes (* 10 1024 1024)) ;; Display caps in logical pixels. nil (default) fits the session window. ;; AI Code requests the matching backing-pixel raster on HiDPI/Retina frames ;; and never enlarges the source. Set an integer for a fixed hard cap. (setq ai-code-session-link-ghostel-image-preview-max-width nil) (setq ai-code-session-link-ghostel-image-preview-max-height nil) #+end_src
=M-x ai-code-toggle-image-preview= turns these previews off or on in all Ghostel sessions without restarting them.
*** Q: Gemini CLI response is relatively slow, how to improve?
- A: use gemini-3-flash model, it is pretty fast, with good quality (being able to solve leetcode hard problems), and it is free. You can set the following in your Emacs config:
#+begin_src elisp (setq ai-code-gemini-cli-program-switches '("--model" "gemini-3-flash-preview")) #+end_src
** AI Assisted Programming related books
-
[[https://learning.oreilly.com/library/view/beyond-vibe-coding/9798341634749/][Beyond Vibe Coding]], by Addy Osmani, August, 2025
-
[[https://learning.oreilly.com/library/view/critical-thinking-habits/0642572243326/][Critical Thinking Habits for Coding with AI]], by Andrew Stellman, Oct 2025
-
[[https://github.com/tninja/aider.el?tab=readme-ov-file#ai-assisted-programming-related-books][More AI Assisted Programming related books]]
** Related Emacs packages
- Claude Code (
[[https://github.com/stevemolitor/claude-code.el][claude-code.el]]) - Claude Code IDE (
[[https://github.com/manzaltu/claude-code-ide.el][claude-code-ide.el]]) - Gemini CLI (
[[https://github.com/linchen2chris/gemini-cli.el][gemini-cli.el]]) - [[https://github.com/xenodium/agent-shell][agent-shell]] ([[https://github.com/xenodium/acp.el][acp.el]])
- [[https://eca.dev/][ECA (Editor Code Assistant)]]
- [[https://github.com/acmorrow/claude-code-ide-extras][claude-code-ide-extras.el]]
** License
Apache-2.0 License
** Contributing
Contributions, issue reports, and improvement suggestions are welcome! Please open an issue or submit a pull request on the project's GitHub repository.