Version 0.4.1
Efrit is an AI coding agent that brings Claude's intelligence directly into Emacs. It can execute natural language commands, explore codebases, run shell commands, and have multi-turn conversations - all while you stay in your editor.
Core principle: Zero client-side intelligence. Claude makes all decisions, Efrit executes.
⚠️ Security Note: Efrit executes AI-generated code in your Emacs. See SECURITY.md for trust model and recommended practices.
efrit-chat)Multi-turn conversations with Claude that understand your Emacs context:
efrit-do)Execute natural language commands that Claude translates to actions:
efrit-execute"efrit-agent)A structured, real-time view of agentic sessions with:
Agent Buffer Keybindings:
Actions use the C-c prefix so standard editing keys (C-k, C-g,
C-h, C-M-*, ...) keep their normal meaning in the input region.
| Key | Action |
|---|---|
TAB / S-TAB | Move between sections |
M-n / M-p | Next / previous tool call |
RET | Expand/collapse tool at point |
C-c C-c | Send input / continue session |
C-c C-k | Cancel session |
C-c C-n | New session |
C-c C-r | Resume paused session |
C-c C-p | Pause session |
C-c C-h | Browse session history |
C-c C-t | Toggle expand tool at point |
C-c C-e | Expand all tool calls |
C-c C-d | Collapse all tool calls |
C-c C-v | Cycle verbosity (minimal/normal/verbose) |
C-c C-o | Cycle display mode (minimal/smart/verbose) |
C-c C-g | Refresh display |
C-c C-q | Quit buffer (session continues) |
1-4 | Select option when Claude asks (in input region) |
C-c ? | Show help |
Efrit provides Claude with 35+ tools:
| Category | Tools |
|---|---|
| Code Execution | eval_sexp (elisp), shell_exec (shell commands) |
| File Editing | edit_file, create_file, undo_edit, format_file |
| Codebase Exploration | search_content, read_file, project_files, glob_files, file_info |
| Version Control | vcs_status, vcs_diff, vcs_log, vcs_blame |
| Task Management | todo_write, session_complete, request_user_input |
| Safety | confirm_action, checkpoint, restore_checkpoint, show_diff_preview |
| Diagnostics | get_diagnostics, elisp_docs |
| Issue Tracking | beads_ready, beads_create, beads_update, beads_close, beads_list |
| External | web_search, fetch_url, read_image |
| Buffer Management | buffer_create, display_in_buffer |
Other AI agents (Claude Code, Cursor, etc.) can interact with Efrit via file-based JSON queue for autonomous development.
git clone https://github.com/steveyegge/efrit.git
cd efrit
Add to ~/.emacs.d/init.el:
(add-to-list 'load-path "/path/to/efrit/lisp")
(require 'efrit)
Option A: Encrypted authinfo (recommended)
Create ~/.authinfo.gpg:
machine api.anthropic.com login personal password YOUR_API_KEY_HERE
Option B: Environment variable
export ANTHROPIC_API_KEY="sk-your-key-here"
Option C: Plain authinfo
Create ~/.authinfo:
machine api.anthropic.com login personal password YOUR_API_KEY_HERE
Verify with M-x efrit-doctor.
| Mode | Use When | Tools Available |
|---|---|---|
efrit-chat | Multi-turn conversations, asking questions, explanations | Buffer-centric (read buffer, search) |
efrit-do | Quick agentic commands, shows progress in minibuffer | Full suite (35+ tools) |
efrit-agent | Complex tasks needing visibility and interaction | Full suite + structured UI |
Decision guide:
efrit-chat (conversational, no file changes)efrit-do (runs in background, shows progress buffer)efrit-agent (real-time visibility, can guide mid-session)Key differences:
efrit-chat: Read-only context, conversational UI, retains historyefrit-do: Fire-and-forget, progress buffer with raw outputefrit-agent: Interactive session buffer with expandable tool calls, TODO tracking, and mid-session guidance (i key)| Command | Description |
|---|---|
M-x efrit-chat | Multi-turn conversational interface |
M-x efrit-do | Execute natural language command asynchronously with progress buffer |
M-x efrit-agent | Open the structured agent session buffer |
M-x efrit-do-sync | Execute natural language command synchronously (blocking) |
M-x efrit-do-silently | Execute command asynchronously without showing progress buffer |
M-x efrit-do-show-progress | Show the progress buffer for the active command |
M-x efrit-do-show-queue | Show commands queued for execution |
M-x efrit-doctor | Run diagnostics |
M-x efrit-help | Show help |
Simple queries:
M-x efrit-do RET
> what buffer am I in?
Code exploration:
M-x efrit-do RET
> search for all uses of 'defcustom' in this project and list them
Multi-step tasks:
M-x efrit-do RET
> create a new elisp file with a function that reverses a string, include proper headers
Shell integration:
M-x efrit-do RET
> run git log --oneline -10 and summarize the recent changes
Conversational:
M-x efrit-chat RET
You: Help me understand how the error handling works in this file
Assistant: [analyzes current buffer and explains]
You: Can you refactor it to use condition-case-unless-debug instead?
Bug fix workflow:
M-x efrit-agent RET
> The function `my-parse-data` throws an error on empty input. Find and fix it.
Claude will:
1. Search for the function definition
2. Analyze the code
3. Identify the bug
4. Create the fix with edit_file
5. Show you the diff for review
Refactoring workflow:
M-x efrit-agent RET
> Refactor all uses of deprecated `my-old-api` to use `my-new-api` in this project
Claude will:
1. Find all occurrences with search_content
2. Create a TODO list for each file
3. Edit each file, showing progress
4. Verify changes compile
Mid-session guidance: While Claude is working, you can:
i to inject guidance: "Focus on the src/ directory only"k to cancel if going wrong directionrequest_user_input and you can respond directly in the bufferProviding corrections: When Claude asks a question, you can:
> prompt and press C-c C-s to send1, 2, 3, or 4 to select from offered optionsBy default, efrit-do executes asynchronously:
M-x efrit-do RET
> create a buffer with a function to reverse strings
Efrit automatically:
C-g (keyboard-quit)efrit-do-show-queue to view)The progress buffer shows:
For simpler tasks or scripting, use efrit-do-sync for blocking execution:
(efrit-do-sync "list all python files in current directory")
This is the older API that waits for completion before returning.
To run a command without showing the progress buffer:
M-x efrit-do-silently RET
> long running task...
Progress is visible in the minibuffer. Show the buffer later with M-x efrit-do-show-progress.
Enable the global keymap:
(efrit-setup-keybindings) ; Binds C-c C-e prefix
Then use:
C-c C-e c - Chat interfaceC-c C-e d - Async command with progress bufferC-c C-e D - Async command in backgroundC-c C-e q - Start remote queueC-c C-e Q - Queue statusAI agents can interact with Efrit via the Model Context Protocol:
(efrit-remote-queue-start) ; Start the queue
Request format:
{
"id": "req_001",
"version": "1.0.0",
"type": "eval",
"content": "(buffer-name)",
"timestamp": "2025-11-28T20:00:00Z"
}
Types: eval (elisp), command (natural language), chat (conversation), status (health check)
Response format:
{
"id": "req_001",
"version": "1.0.0",
"status": "success",
"result": "*scratch*",
"timestamp": "2025-11-28T20:00:01Z"
}
See mcp/README.md for MCP server setup.
If you have existing keybindings or configurations using older Efrit APIs:
Old name → New name | Status
--- | --- | ---
efrit-do (sync) | efrit-do-sync | Deprecated
efrit-do-async | efrit-do | Primary interface
efrit-do-async-legacy | — | Do not use
If you have in your init.el:
;; OLD: sync command (blocking)
(global-set-key (kbd "C-c C-e d") 'efrit-do)
;; NEW: use async command with progress buffer
(global-set-key (kbd "C-c C-e d") 'efrit-do)
Or if you have code calling efrit-do-async:
;; OLD: explicit async
(efrit-do-async "your command")
;; NEW: efrit-do is async by default
(efrit-do "your command")
The async API is now recommended for all use cases. Use efrit-do-sync only if you need blocking behavior (e.g., in scripts where waiting for completion is required).
;; Model selection (default: claude-sonnet-4-5-20250929)
(setq efrit-default-model "claude-sonnet-4-5-20250929")
;; Max tokens per response
(setq efrit-max-tokens 8192)
;; Data directory
(setq efrit-data-directory (expand-file-name ".efrit" user-emacs-directory))
;; Enable debug logging
(setq efrit-log-level 'debug)
;; Progress buffer configuration
(setq efrit-do-show-progress-buffer t) ; Show progress buffer automatically
(setq efrit-do-queue-max-size 10) ; Max commands to queue
Efrit includes safety controls for eval_sexp:
;; Timeout for elisp evaluation (default: 30 seconds)
(setq efrit-tools-eval-timeout 30)
;; Disable elisp evaluation entirely (Claude uses predefined tools only)
(setq efrit-tools-sexp-evaluation-enabled nil)
See SECURITY.md for full security configuration.
Efrit restricts which shell commands Claude can execute. By default, a wide range of development tools are allowed (git, npm, cargo, go, python, etc.).
;; Disable all shell security checks (trust Claude completely)
(setq efrit-do-shell-security-enabled nil)
;; OR allow all commands but keep forbidden pattern checks
(setq efrit-do-allowed-shell-commands '("*"))
;; Add additional allowed commands
(add-to-list 'efrit-do-allowed-shell-commands "mycustomtool")
;; Disable forbidden pattern checking
(setq efrit-do-forbidden-shell-patterns nil)
The default forbidden patterns block truly dangerous commands like sudo, shutdown, and shell command injection via $(...) or backticks.
By default, all data lives under .efrit/ inside user-emacs-directory:
.efrit/
├── cache/ # Temporary cache
├── context/ # Context persistence
├── queues/ # AI communication (requests/responses/processing/archive)
├── logs/ # Debug logs
└── sessions/ # Session data
Check installation:
M-x efrit-doctor
API issues:
M-: (efrit-common-get-api-key) ; Should return your key
Debug logging:
(setq efrit-log-level 'debug)
M-x efrit-log-show
View errors:
M-x efrit-show-errors
make compile # Byte-compile elisp
make test # Run test suite
See DEVELOPMENT.md for contributor guidelines.
Efrit follows the Pure Executor principle:
See ARCHITECTURE.md for design details.
Apache License 2.0. See LICENSE.
Emacs Lisp
91.7%
TypeScript
4.0%
Shell
2.2%
JavaScript
1.2%
Version 0.4.1
Efrit is an AI coding agent that brings Claude's intelligence directly into Emacs. It can execute natural language commands, explore codebases, run shell commands, and have multi-turn conversations - all while you stay in your editor.
Core principle: Zero client-side intelligence. Claude makes all decisions, Efrit executes.
⚠️ Security Note: Efrit executes AI-generated code in your Emacs. See SECURITY.md for trust model and recommended practices.
efrit-chat)Multi-turn conversations with Claude that understand your Emacs context:
efrit-do)Execute natural language commands that Claude translates to actions:
efrit-execute"efrit-agent)A structured, real-time view of agentic sessions with:
Agent Buffer Keybindings:
Actions use the C-c prefix so standard editing keys (C-k, C-g,
C-h, C-M-*, ...) keep their normal meaning in the input region.
| Key | Action |
|---|---|
TAB / S-TAB | Move between sections |
M-n / M-p | Next / previous tool call |
RET | Expand/collapse tool at point |
C-c C-c | Send input / continue session |
C-c C-k | Cancel session |
C-c C-n | New session |
C-c C-r | Resume paused session |
C-c C-p | Pause session |
C-c C-h | Browse session history |
C-c C-t | Toggle expand tool at point |
C-c C-e | Expand all tool calls |
C-c C-d | Collapse all tool calls |
C-c C-v | Cycle verbosity (minimal/normal/verbose) |
C-c C-o | Cycle display mode (minimal/smart/verbose) |
C-c C-g | Refresh display |
C-c C-q | Quit buffer (session continues) |
1-4 | Select option when Claude asks (in input region) |
C-c ? | Show help |
Efrit provides Claude with 35+ tools:
| Category | Tools |
|---|---|
| Code Execution | eval_sexp (elisp), shell_exec (shell commands) |
| File Editing | edit_file, create_file, undo_edit, format_file |
| Codebase Exploration | search_content, read_file, project_files, glob_files, file_info |
| Version Control | vcs_status, vcs_diff, vcs_log, vcs_blame |
| Task Management | todo_write, session_complete, request_user_input |
| Safety | confirm_action, checkpoint, restore_checkpoint, show_diff_preview |
| Diagnostics | get_diagnostics, elisp_docs |
| Issue Tracking | beads_ready, beads_create, beads_update, beads_close, beads_list |
| External | web_search, fetch_url, read_image |
| Buffer Management | buffer_create, display_in_buffer |
Other AI agents (Claude Code, Cursor, etc.) can interact with Efrit via file-based JSON queue for autonomous development.
git clone https://github.com/steveyegge/efrit.git
cd efrit
Add to ~/.emacs.d/init.el:
(add-to-list 'load-path "/path/to/efrit/lisp")
(require 'efrit)
Option A: Encrypted authinfo (recommended)
Create ~/.authinfo.gpg:
machine api.anthropic.com login personal password YOUR_API_KEY_HERE
Option B: Environment variable
export ANTHROPIC_API_KEY="sk-your-key-here"
Option C: Plain authinfo
Create ~/.authinfo:
machine api.anthropic.com login personal password YOUR_API_KEY_HERE
Verify with M-x efrit-doctor.
| Mode | Use When | Tools Available |
|---|---|---|
efrit-chat | Multi-turn conversations, asking questions, explanations | Buffer-centric (read buffer, search) |
efrit-do | Quick agentic commands, shows progress in minibuffer | Full suite (35+ tools) |
efrit-agent | Complex tasks needing visibility and interaction | Full suite + structured UI |
Decision guide:
efrit-chat (conversational, no file changes)efrit-do (runs in background, shows progress buffer)efrit-agent (real-time visibility, can guide mid-session)Key differences:
efrit-chat: Read-only context, conversational UI, retains historyefrit-do: Fire-and-forget, progress buffer with raw outputefrit-agent: Interactive session buffer with expandable tool calls, TODO tracking, and mid-session guidance (i key)| Command | Description |
|---|---|
M-x efrit-chat | Multi-turn conversational interface |
M-x efrit-do | Execute natural language command asynchronously with progress buffer |
M-x efrit-agent | Open the structured agent session buffer |
M-x efrit-do-sync | Execute natural language command synchronously (blocking) |
M-x efrit-do-silently | Execute command asynchronously without showing progress buffer |
M-x efrit-do-show-progress | Show the progress buffer for the active command |
M-x efrit-do-show-queue | Show commands queued for execution |
M-x efrit-doctor | Run diagnostics |
M-x efrit-help | Show help |
Simple queries:
M-x efrit-do RET
> what buffer am I in?
Code exploration:
M-x efrit-do RET
> search for all uses of 'defcustom' in this project and list them
Multi-step tasks:
M-x efrit-do RET
> create a new elisp file with a function that reverses a string, include proper headers
Shell integration:
M-x efrit-do RET
> run git log --oneline -10 and summarize the recent changes
Conversational:
M-x efrit-chat RET
You: Help me understand how the error handling works in this file
Assistant: [analyzes current buffer and explains]
You: Can you refactor it to use condition-case-unless-debug instead?
Bug fix workflow:
M-x efrit-agent RET
> The function `my-parse-data` throws an error on empty input. Find and fix it.
Claude will:
1. Search for the function definition
2. Analyze the code
3. Identify the bug
4. Create the fix with edit_file
5. Show you the diff for review
Refactoring workflow:
M-x efrit-agent RET
> Refactor all uses of deprecated `my-old-api` to use `my-new-api` in this project
Claude will:
1. Find all occurrences with search_content
2. Create a TODO list for each file
3. Edit each file, showing progress
4. Verify changes compile
Mid-session guidance: While Claude is working, you can:
i to inject guidance: "Focus on the src/ directory only"k to cancel if going wrong directionrequest_user_input and you can respond directly in the bufferProviding corrections: When Claude asks a question, you can:
> prompt and press C-c C-s to send1, 2, 3, or 4 to select from offered optionsBy default, efrit-do executes asynchronously:
M-x efrit-do RET
> create a buffer with a function to reverse strings
Efrit automatically:
C-g (keyboard-quit)efrit-do-show-queue to view)The progress buffer shows:
For simpler tasks or scripting, use efrit-do-sync for blocking execution:
(efrit-do-sync "list all python files in current directory")
This is the older API that waits for completion before returning.
To run a command without showing the progress buffer:
M-x efrit-do-silently RET
> long running task...
Progress is visible in the minibuffer. Show the buffer later with M-x efrit-do-show-progress.
Enable the global keymap:
(efrit-setup-keybindings) ; Binds C-c C-e prefix
Then use:
C-c C-e c - Chat interfaceC-c C-e d - Async command with progress bufferC-c C-e D - Async command in backgroundC-c C-e q - Start remote queueC-c C-e Q - Queue statusAI agents can interact with Efrit via the Model Context Protocol:
(efrit-remote-queue-start) ; Start the queue
Request format:
{
"id": "req_001",
"version": "1.0.0",
"type": "eval",
"content": "(buffer-name)",
"timestamp": "2025-11-28T20:00:00Z"
}
Types: eval (elisp), command (natural language), chat (conversation), status (health check)
Response format:
{
"id": "req_001",
"version": "1.0.0",
"status": "success",
"result": "*scratch*",
"timestamp": "2025-11-28T20:00:01Z"
}
See mcp/README.md for MCP server setup.
If you have existing keybindings or configurations using older Efrit APIs:
Old name → New name | Status
--- | --- | ---
efrit-do (sync) | efrit-do-sync | Deprecated
efrit-do-async | efrit-do | Primary interface
efrit-do-async-legacy | — | Do not use
If you have in your init.el:
;; OLD: sync command (blocking)
(global-set-key (kbd "C-c C-e d") 'efrit-do)
;; NEW: use async command with progress buffer
(global-set-key (kbd "C-c C-e d") 'efrit-do)
Or if you have code calling efrit-do-async:
;; OLD: explicit async
(efrit-do-async "your command")
;; NEW: efrit-do is async by default
(efrit-do "your command")
The async API is now recommended for all use cases. Use efrit-do-sync only if you need blocking behavior (e.g., in scripts where waiting for completion is required).
;; Model selection (default: claude-sonnet-4-5-20250929)
(setq efrit-default-model "claude-sonnet-4-5-20250929")
;; Max tokens per response
(setq efrit-max-tokens 8192)
;; Data directory
(setq efrit-data-directory (expand-file-name ".efrit" user-emacs-directory))
;; Enable debug logging
(setq efrit-log-level 'debug)
;; Progress buffer configuration
(setq efrit-do-show-progress-buffer t) ; Show progress buffer automatically
(setq efrit-do-queue-max-size 10) ; Max commands to queue
Efrit includes safety controls for eval_sexp:
;; Timeout for elisp evaluation (default: 30 seconds)
(setq efrit-tools-eval-timeout 30)
;; Disable elisp evaluation entirely (Claude uses predefined tools only)
(setq efrit-tools-sexp-evaluation-enabled nil)
See SECURITY.md for full security configuration.
Efrit restricts which shell commands Claude can execute. By default, a wide range of development tools are allowed (git, npm, cargo, go, python, etc.).
;; Disable all shell security checks (trust Claude completely)
(setq efrit-do-shell-security-enabled nil)
;; OR allow all commands but keep forbidden pattern checks
(setq efrit-do-allowed-shell-commands '("*"))
;; Add additional allowed commands
(add-to-list 'efrit-do-allowed-shell-commands "mycustomtool")
;; Disable forbidden pattern checking
(setq efrit-do-forbidden-shell-patterns nil)
The default forbidden patterns block truly dangerous commands like sudo, shutdown, and shell command injection via $(...) or backticks.
By default, all data lives under .efrit/ inside user-emacs-directory:
.efrit/
├── cache/ # Temporary cache
├── context/ # Context persistence
├── queues/ # AI communication (requests/responses/processing/archive)
├── logs/ # Debug logs
└── sessions/ # Session data
Check installation:
M-x efrit-doctor
API issues:
M-: (efrit-common-get-api-key) ; Should return your key
Debug logging:
(setq efrit-log-level 'debug)
M-x efrit-log-show
View errors:
M-x efrit-show-errors
make compile # Byte-compile elisp
make test # Run test suite
See DEVELOPMENT.md for contributor guidelines.
Efrit follows the Pure Executor principle:
See ARCHITECTURE.md for design details.
Apache License 2.0. See LICENSE.
Emacs Lisp
91.7%
TypeScript
4.0%
Shell
2.2%
JavaScript
1.2%