Skip to content

steveyegge/efrit

Repository files navigation

Efrit - AI-Powered Emacs Coding Assistant

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.

Features

Conversational Chat (efrit-chat)

Multi-turn conversations with Claude that understand your Emacs context:

  • Ask questions about code, get explanations
  • Refactor with guidance
  • Debug issues interactively

Agentic Task Execution (efrit-do)

Execute natural language commands that Claude translates to actions:

  • "Create a buffer with today's date"
  • "List all elisp files in this directory and count them"
  • "Search for the function definition of efrit-execute"
  • "Run git status and show me the output"

Agent Session Buffer (efrit-agent)

A structured, real-time view of agentic sessions with:

  • Session status and elapsed time in header-line
  • Task progress tracking (TODOs) updated by Claude
  • Conversation view with expandable tool calls
  • Interactive input for follow-up commands and mid-session guidance

Agent Buffer Keybindings:

Key Action
n / M-n Next tool call
p / M-p Previous tool call
RET Expand/collapse tool at point
E Expand all tool calls
C Collapse all tool calls
w Copy tool output to kill ring
v Cycle verbosity (minimal/normal/verbose)
i Inject guidance mid-session
r Resume paused session
k Cancel session
g Refresh display
q Quit buffer (session continues)
1-4 Select option when Claude asks
? Show help

Rich Tool Suite

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

Robust Error Handling

  • Circuit breaker prevents infinite loops
  • Automatic error recovery and retry
  • Security controls on shell commands

AI-to-AI Communication

Other AI agents (Claude Code, Cursor, etc.) can interact with Efrit via file-based JSON queue for autonomous development.

Installation

Prerequisites

Quick Start

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)

API Key Configuration

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.

Usage

When to Use Each Mode

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:

  • Just asking?efrit-chat (conversational, no file changes)
  • Quick command?efrit-do (runs in background, shows progress buffer)
  • Complex task?efrit-agent (real-time visibility, can guide mid-session)

Key differences:

  • efrit-chat: Read-only context, conversational UI, retains history
  • efrit-do: Fire-and-forget, progress buffer with raw output
  • efrit-agent: Interactive session buffer with expandable tool calls, TODO tracking, and mid-session guidance (i key)

Commands

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

Examples

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?

Agentic Workflows

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:

  • Press i to inject guidance: "Focus on the src/ directory only"
  • Press k to cancel if going wrong direction
  • Wait for questions - Claude will ask via request_user_input and you can respond directly in the buffer

Providing corrections: When Claude asks a question, you can:

  • Type your response after the > prompt and press C-c C-s to send
  • Press 1, 2, 3, or 4 to select from offered options
  • Type "actually, I meant..." to correct course

Async Execution (Default Behavior)

By default, efrit-do executes asynchronously:

M-x efrit-do RET
> create a buffer with a function to reverse strings

Efrit automatically:

  1. Displays a progress buffer with real-time updates on Claude's thinking and tool execution
  2. Supports interruption with C-g (keyboard-quit)
  3. Queues commands if another command is already running (use efrit-do-show-queue to view)
  4. Shows session status in the minibuffer and modeline

The progress buffer shows:

  • Claude's reasoning and tool calls
  • Results from each step
  • Time elapsed

Synchronous Execution (Legacy)

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.

Background Execution

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.

Key Bindings

Enable the global keymap:

(efrit-setup-keybindings)  ; Binds C-c C-e prefix

Then use:

  • C-c C-e c - Chat interface
  • C-c C-e d - Async command with progress buffer
  • C-c C-e D - Async command in background
  • C-c C-e q - Start remote queue
  • C-c C-e Q - Queue status

Agent Communication (MCP)

AI 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.

Migration Guide

If you have existing keybindings or configurations using older Efrit APIs:

Old nameNew 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).

Configuration

;; 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 "~/.emacs.d/.efrit/")

;; 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

Elisp Evaluation Safety

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.

Shell Command Security

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.

Data Directory

All data lives under ~/.emacs.d/.efrit/:

.efrit/
├── cache/       # Temporary cache
├── context/     # Context persistence
├── queues/      # AI communication (requests/responses/processing/archive)
├── logs/        # Debug logs
└── sessions/    # Session data

Troubleshooting

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

Development

make compile  # Byte-compile elisp
make test     # Run test suite

See DEVELOPMENT.md for contributor guidelines.

Architecture

Efrit follows the Pure Executor principle:

  • Claude decides what to do
  • Efrit executes those decisions
  • No pattern matching or heuristics in the client

See ARCHITECTURE.md for design details.

License

Apache License 2.0. See LICENSE.

About

A native elisp coding agent running in Emacs

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •