sage.el: AI Coding Assistant for Emacs

Table of Contents

Source: github.com/aygp-dr/sage.el

1. Executive Summary

sage.el is a modular AI coding assistant for Emacs that brings tool-calling capabilities to your editor. Unlike CLI-based assistants, sage.el is designed around Emacs' unique strengths: long-lived sessions, buffer persistence, and deep editor integration.

1.1. Key Differentiators

Feature sage.el Claude Code Gemini CLI
Session continuation Auto-continue Explicit –continue New each time
Editor integration Native Emacs Terminal Terminal
Tool ecosystem Extensible Elisp Fixed set Fixed set
org-mode support First-class None None
Magit integration Native External External

2. Why sage.el?

2.1. The REPL Paradigm

Unlike CLI tools where each invocation is stateless, sage.el follows REPL semantics:

  1. Continuous Context: Your conversation accumulates naturally
  2. Visual History: See previous exchanges in the *sage* buffer
  3. Project Binding: Context is scoped to your project directory

2.2. Emacs-Native Design

  • Buffer State: Conversations persist like any other buffer
  • Mode Integration: Works with project.el, projectile, magit
  • Org-mode: Export conversations, embed in documents
  • Tool Extensibility: Write tools in Elisp, not shell scripts

3. Architecture

verified · pilot-annotation-pass · 2026-10-08
sage.el (Modular Architecture)
├── sage.el              # Core REPL and user interface
├── sage-context.el      # Context window management
├── sage-emacs.el        # Emacs integration (buffers, files)
├── sage-log.el          # Structured JSON logging
├── sage-memory.el       # Conversation memory
├── sage-project.el      # Project-scoped session storage
├── sage-queue.el        # Request queue management
├── sage-ratelimit.el    # API rate limiting
├── sage-reflect.el      # Self-reflection and introspection
├── sage-session.el      # UUID-based session management
├── sage-tools.el        # Tool calling framework
└── sage-tool-factory.el # Dynamic tool generation

diagram-architecture.png

Figure 1: sage.el layer stack – UI, session management, execution engine, observability, optional integrations, and AI provider backends

3.1. Integration Modules

Optional Integrations
├── sage-magit.el        # Git operations via Magit
└── sage-org.el          # Org-mode document support

4. Development Methodology

4.1. RFC-Driven Design

Major features go through a formal RFC process:

  1. Proposal: Write RFC document with motivation, design, alternatives
  2. Multi-Stakeholder Review: L7 (API), CTO (Architecture), Developer, Release
  3. Test Specification: Aggressive test plan before implementation
  4. Implementation: Phased rollout with backward compatibility

See: RFC-SESSION-STORAGE.org

4.2. Parallel Agent Reviews

We use specialized "agent personas" for comprehensive code review:

Agent Focus Concerns
L7 API/Protocol UUID collision, file locking, rate limiting
CTO Architecture Scalability, resource usage, migration path
Elisp Dev Emacs conventions Blocking I/O, defcustom usage, project.el integration
MELPA Package quality Byte-compilation, checkdoc, package-lint

4.3. Beads Task Tracking

All development tasks are tracked using beads (bd):

bd list              # See all open issues
bd ready             # Find unblocked work
bd create "Feature"  # Create new task
bd close <id>        # Complete task

Current bead: gemini-repl-010-5uh (Session Storage RFC)

5. Features

5.1. Tool Calling System

;; Register a custom tool
(sage-tools-register
 "my-tool"
 :description "My custom tool"
 :parameters '((param1 . "string"))
 :handler #'my-tool-handler)

Built-in tools:

  • read_file, write_file, edit_file
  • bash (command execution)
  • search_files, list_files
  • project_info, buffer_info

5.2. Session Persistence

Sessions are stored per-project with automatic continuation:

~/.emacs.d/sage/projects/<encoded-path>/
├── <session-uuid>.jsonl       # Session conversation
├── sessions.json              # Session index
└── history/                   # Archived sessions

Key behaviors:

  • Auto-continue: Restart Emacs and pick up where you left off
  • Project-scoped: Different projects maintain separate contexts
  • Exportable: JSONL format compatible with other TCAs

5.3. Rate Limiting

(setq sage-ratelimit-requests-per-minute 60)
(setq sage-ratelimit-tokens-per-minute 100000)

Features:

  • Token counting with cl-100k-base estimation
  • Exponential backoff on 429 errors
  • Request queue with priority

5.4. Context Management

Automatic context window management:

(setq sage-context-max-tokens 128000)
(setq sage-context-reserve-output 4096)
  • Automatic truncation when approaching limits
  • Preservation of system prompts and recent messages
  • Token usage reporting via /context command

6. Interoperability

6.1. TCA Session Schema

sage.el follows the Tool Calling Agent (TCA) session schema for interoperability with other AI coding assistants:

{
  "uuid": "msg-uuid",
  "sessionId": "session-uuid",
  "role": "user|assistant|system|tool",
  "content": "message content",
  "timestamp": "2026-01-11T22:00:00Z",
  "tool_calls": [...]
}

Compatible with:

  • Claude Code (~/.claude/projects/)
  • Gemini CLI
  • Future: Amp, Aider, Cursor

6.2. Storage Presets

;; Claude Code compatible format
(setq sage-project-storage-preset 'claude-shared)

;; Emacs-native format (default)
(setq sage-project-storage-preset 'emacs-native)

7. Quality Assurance

7.1. Test Coverage

verified · pilot-annotation-pass · 2026-10-08
Tests: 99 passed, 0 failed
Modules tested:
- sage-test.el: 9/9 passed
- sage-context-test.el: 12/12 passed
- sage-emacs-test.el: 9/9 passed
- sage-memory-test.el: 18/18 passed
- sage-project-test.el: 18/18 passed
- sage-queue-test.el: 11/11 passed
- sage-ratelimit-test.el: 22/22 passed

Run tests:

make test-all          # Run all tests
make test-session      # Session-specific tests
make test-coverage     # With coverage report

7.2. CI/CD

corrected · pilot-annotation-pass · 2026-10-08

GitHub Actions runs on every push:

  • Byte compilation (Emacs 28.2, 29.4, 30.1)
  • ERT test suite
  • Checkdoc validation
  • Package-lint compliance

8. Getting Started

8.1. Installation

;; With straight.el
(straight-use-package
 '(sage :type git :host github :repo "aygp-dr/sage.el"))

;; With use-package
(use-package sage
  :straight (:type git :host github :repo "aygp-dr/sage.el")
  :config
  (setq sage-provider 'ollama)
  (setq sage-model "llama3.2"))

8.2. Basic Usage

M-x sage              ; Start REPL (auto-continues last session)
C-u M-x sage          ; Force new session

;; In sage buffer
/help                 ; Show available commands
/context              ; Show context usage
/session              ; Show session info
/reset                ; Clear current session

8.3. Configuration

;; Provider selection
(setq sage-provider 'gemini)  ; or 'ollama, 'openai, 'anthropic
(setq sage-model "gemini-2.0-flash")

;; Session behavior
(setq sage-session-auto-continue t)  ; Auto-continue (default)
(setq sage-session-max-age-hours 24) ; Force new after 24h

;; Rate limiting
(setq sage-ratelimit-requests-per-minute 60)

9. Roadmap

9.1. Phase 1: Core (Complete)

  • [X] Multi-provider support (Ollama, Gemini, OpenAI, Anthropic)
  • [X] Tool calling framework
  • [X] Session persistence
  • [X] Rate limiting
  • [X] Context management

9.2. Phase 2: Integration (In Progress)

  • [X] Magit integration
  • [X] Org-mode support
  • [ ] Project.el deep integration
  • [ ] Dired tool support

9.3. Phase 3: Advanced (Planned)

  • [ ] Sub-agent spawning
  • [ ] Cloud sync (optional)
  • [ ] Voice input (whisper.el)
  • [ ] Image understanding (multimodal)

9.4. Phase 4: Ecosystem (Future)

  • [ ] MELPA submission
  • [ ] Emacs Wiki documentation
  • [ ] Community tool repository

10. Contributing

See GitHub Repository for:

  • Issue tracking
  • Pull request guidelines
  • RFC process documentation

11. References

12. License

corrected · pilot-annotation-pass · 2026-10-08

GNU General Public License v3.0 (GPL-3.0) - See repository for full license text.

13. Contact

  • Author: Jason Walsh <j@wal.sh>
  • GitHub: aygp-dr
  • Mastodon: @jwalsh@emacs.ch