Emacs integration for Codex CLI. It runs the Codex terminal UI inside Emacs per project and gives you a few high‑leverage helpers for sending prompts, regions, and files. No MCP. No diagnostics. No patch reviewer. Small surface, stable defaults.
Status: v0.1 (minimal feature set)
- Launch Codex CLI in a project‑scoped terminal buffer
- Side window on the right with fixed width
- Optional focus of the Codex window when shown
- Send prompt from minibuffer, active region, or any file under the project
- Smart chunking for large sends with progress messages
- Optional per‑session preamble injected once
- Last‑block resend and optional injection log buffer
Non‑goals for v0.1: MCP tools, Flycheck/Flymake bridges, ediff workflows, complex menus.
- Emacs 28 or newer
- Codex CLI installed and on PATH (
codex --versionshould work) - Optional:
vtermfor a better terminal; falls back to built‑interm
Ensure MELPA is configured, then:
(use-package codex-cli
:ensure t
:bind (("C-c c s" . codex-cli-start)
("C-c c c" . codex-cli-toggle)
("C-c c q" . codex-cli-stop)
;; ("C-c c Q" . codex-cli-restart)
("C-c c p" . codex-cli-send-prompt)
("C-c c r" . codex-cli-send-region)
("C-c c f" . codex-cli-send-file)
("C-c c b" . codex-cli-copy-last-block))
:init
(setq codex-cli-executable "codex"
codex-cli-terminal-backend 'vterm
codex-cli-width 90))Note: If this package isn’t on MELPA yet, use Option B.
(use-package codex-cli
:vc (:fetcher github :repo "bennfocus/codex-cli.el")
:bind (("C-c c s" . codex-cli-start)
("C-c c c" . codex-cli-toggle)
("C-c c q" . codex-cli-stop)
;; ("C-c c Q" . codex-cli-restart)
("C-c c p" . codex-cli-send-prompt)
("C-c c r" . codex-cli-send-region)
("C-c c f" . codex-cli-send-file)
("C-c c b" . codex-cli-copy-last-block))
:init
(setq codex-cli-executable "codex"
codex-cli-terminal-backend 'vterm
codex-cli-width 90))(use-package codex-cli
:load-path "/path/to/codex-cli.el" ;; adjust to your checkout
:bind (("C-c c s" . codex-cli-start)
("C-c c c" . codex-cli-toggle)
("C-c c q" . codex-cli-stop)
;; ("C-c c Q" . codex-cli-restart)
("C-c c p" . codex-cli-send-prompt)
("C-c c r" . codex-cli-send-region)
("C-c c f" . codex-cli-send-file)
("C-c c b" . codex-cli-copy-last-block))
:init
(setq codex-cli-executable "codex"
codex-cli-terminal-backend 'vterm
codex-cli-width 90))- Ensure Codex CLI is available:
which codex && codex --version - Open a file inside your project in Emacs.
M-x codex-cli-start(orC-c x s) to open a*codex-cli:PROJECT*buffer on the right.- Try:
M-x codex-cli-send-promptto paste a message into the terminal- Select a region then
M-x codex-cli-send-region M-x codex-cli-send-fileto send any file under the project
codex-cli-startstart or focus the session for the current projectcodex-cli-toggleshow or hide the side window without killing the processcodex-cli-restartkill and start again in the same buffercodex-cli-stopterminate the process and bury the buffercodex-cli-send-promptminibuffer input pasted into the terminalcodex-cli-send-regionsend active region or whole buffer as a fenced blockcodex-cli-send-filepick a project file and send as a fenced blockcodex-cli-copy-last-blockre‑send the last injected block
(defgroup codex-cli nil
"Run Codex CLI inside Emacs with helpers."
:group 'tools :prefix "codex-cli-")
(defcustom codex-cli-executable "codex" "Path to Codex CLI.")
(defcustom codex-cli-extra-args nil "List of extra args passed to Codex CLI.")
(defcustom codex-cli-side 'right "Side window placement: left or right.")
(defcustom codex-cli-width 90 "Side window width in columns.")
(defcustom codex-cli-terminal-backend 'vterm "Preferred terminal backend: vterm or term.")
(defcustom codex-cli-max-bytes-per-send 8000 "Chunk size for large sends.")
(defcustom codex-cli-session-preamble nil "Optional text to inject once after start.")
(defcustom codex-cli-log-injections t "Mirror injected blocks into a log buffer.")
(defcustom codex-cli-focus-on-open t "Select the Codex side window after displaying it.")Content formatting
By default, the package wraps content with a header and a fenced code block:
# File: relative/path/to/file.ext
```<lang>
<content>
```
The language tag is guessed from the current major mode or file extension. If unknown, it is omitted.
Alternatively, you can send file references instead of full content:
@relative/path/to/file.ext#L17-26
Enable this style and tweak formatting via:
(setq codex-cli-send-style 'reference)
(setq codex-cli-reference-prefix "") ;; e.g., "i " if your CLI expects it
(setq codex-cli-reference-format-single "@%s#L%d")
(setq codex-cli-reference-format-range "@%s#L%d-%d")
(setq codex-cli-reference-file-format "@%s")When using reference style, codex-cli-send-region emits a file+line token if the buffer visits a file; otherwise it falls back to fenced content. codex-cli-send-file emits a whole‑file token like @path.
Fast path while editing:
- Open the changed file and
M-x eval-buffer
Hard reload when you changed many files:
(unload-feature 'codex-cli t)
(load (expand-file-name "/path/to/codex-cli.el/codex-cli.el") nil 'nomessage)If Emacs reports dependencies are still loaded, unload in reverse order:
(mapc (lambda (f) (ignore-errors (unload-feature f t)))
'(codex-cli-term codex-cli-utils codex-cli-project codex-cli))
(load (expand-file-name "/path/to/codex-cli.el/codex-cli.el") nil 'nomessage)Byte‑compile to catch warnings:
emacs -Q --batch -L /path/to/codex-cli.el \
-f batch-byte-compile /path/to/codex-cli.el/*.elIf you added ERT tests as suggested in tasks.md:
emacs -Q --batch \
-L /path/to/codex-cli.el \
-l /path/to/codex-cli.el/codex-cli.el \
-l /path/to/codex-cli.el/tests/codex-cli-test.el \
-f ert-run-tests-batch-and-exit- Codex not found set
(setq codex-cli-executable "/full/path/to/codex")and verify(executable-find codex-cli-executable) - Window size tweak
(setq codex-cli-width 100)and restart the session - Focus behavior enable
(setq codex-cli-focus-on-open t)to select the Codex window when it opens - Unicode or paste issues install
vtermor set(setq codex-cli-terminal-backend 'vterm) - Wrong project root open a file inside the repo or set
default-directorybefore starting - Preamble runs twice increase the post‑spawn idle delay in your code a little
- v0.1 minimal (this release)
- v0.2 small hydra or transient for core actions and
.dir-locals.elpreamble support
For the full design, see spec.md.
MIT
Inspired by the excellent editor‑agent integration patterns in the Emacs community. Built as a clean, minimal alternative tailored for Codex CLI.
