An idiomatic Emacs UI for Claude Code — structured, navigatable, fully native.
emacs-gravity gives you a magit-style working memory interface for Claude Code. Instead of watching a scrolling terminal, you get a structured, collapsible view of every session: plans, tool executions, agent trees, file changes, and tasks — all keyboard-navigatable, all in Emacs.
Claude Code's TUI is hidden by default. You see the conversation as data, not as a chat log.
I'm using it as my daily driver for several projects with Claude Code TUI. While stability is imploving, we're at beta quality, mostly.
- unmanaged sessions are the most frequently used and have the least amount of bugs
- the most confusing "feature" is that in 90% of the cases you see permission request or question displayed both in TUI and Gravity. The remaining 10% Claude may appear "stuck" because the request/question is not shown in the TUI, but only in Gravity. The menubar indicator helps a lot with this case.
- managed sessions (tmux) are not well tested yet. They are my next priority.
- known issue is you have to have running tmux before Gravity can start managed session.
- performance is OK. With many sessions and frequent updates editors freeze too often. I regularly have performance focused sessions, but I'm not sure we can ever get to state where Gravity buffers are receiving frequent updates and regular editors feel as smooth as usual.
This project has been vibecoded on purpose as experiment, so desipite my best effort to keep complete test suite, regressions happen.
Project is being used & developed exclusively on MacOS, so windows & linux users may hit obstacles I'm unaware of.
Breaking change. v3 is a ground-up rewrite of the backend. The v2 standalone mode (where Emacs held all state directly) is gone. You must remove v2 completely before upgrading — gravity-server is now required.
- Server-driven architecture — All session state moved from Emacs Lisp hash tables to gravity-server, a long-running TypeScript/Effect backend. Emacs is now a thin terminal client that applies semantic patches and renders via magit-section.
- Multi-client support — Multiple terminals connect to the same server simultaneously. The macOS menu bar app and Emacs share the same live state. First responder wins for inbox actions.
- Semantic patch protocol — Typed incremental updates (
add_tool,complete_agent,set_plan) replace full state rebuilds. Any client that speaks the protocol can render the full UI — future web or native dashboards included. - Centralized enrichment — Transcript parsing, agent attribution, and event enrichment run server-side with full in-memory state. No more file I/O for agent tracking.
- Inbox system — Permissions, plan reviews, and questions from all sessions funnel into a centralized inbox. Any connected terminal can respond.
- macOS menu bar client — New lightweight Swift app with colored status dots per session, project-grouped dropdown, health monitoring, and auto-reconnect.
- Two-socket architecture — Hook socket (bridge shim, one-shot per event) and terminal socket (persistent client connections) are cleanly separated.
- Monorepo with shared types —
packages/{shared, emacs-bridge, gravity-server}with npm workspaces and type-safe protocol definitions shared across all components. - Beads issue tracking integration — Projects with a
.beads/directory get a live Issues section in the overview buffer. Open, in-progress, and blocked issues displayed per project with priority labels, status indicators, and async refresh.
See ARCHITECTURE.md for the full v3 design and docs/refactor-implementation.md for the design rationale.
- Remove old socket config — v2 connected the bridge directly to Emacs. Delete any custom socket paths pointing at Emacs.
- Delete agent state files — Remove
~/.claude/emacs-bridge-agents.json(agent state is now in-memory in gravity-server). - Clean install — Run
npm installat the monorepo root. - Re-register the plugin — Update
marketplace.jsonif needed (thesourcepath is unchanged). - Update your init.el — Replace
(claude-gravity-start)with(claude-gravity-server-start). - Delete stale byte-compiled files — Run
rm -f *.elcin the project root. Emacs loads.elcover.el, so stale compiled files silently override your changes.
You already live in Emacs. Claude Code is powerful, but its terminal UI is a firehose — scrolling text, interleaved tool calls, agent output mixed with thinking. emacs-gravity restructures all of that into something you can actually navigate.
- Idiomatic Emacs UI — Built on magit-section. Collapsible trees, TAB to expand, RET to visit. If you know magit, you know emacs-gravity.
- Structured session transcripts — Every tool call, agent dispatch, thinking block, and assistant message organized into turns. Expand what matters, collapse the rest.
- Deep agent visibility — Subagents render as nested trees. See their tool calls, thinking, and results. Inspect transcripts with a keystroke.
- Multi-session message center — Track multiple Claude sessions simultaneously, grouped by project. Switch between them like buffers.
- Plan review with feedback — Review Claude's plans in a dedicated buffer. Add inline comments, edit the text, write
@claude:markers. Smart approve: clean plans pass through, annotated plans auto-deny with structured feedback. - Runs anywhere Emacs runs — Terminal, TTY, SSH, tmux. No Electron, no browser, no GUI required.
- Turn-based YOLO mode — Go YOLO for just one turn when you know what to expect. Useful in planning mode.
emacs-gravity is a server-driven, multi-client system. A long-running TypeScript backend owns all session state and broadcasts semantic patches to any number of connected terminal clients over a typed protocol.
Claude Code (12 hook events)
|
emacs-bridge (Node.js one-shot shim)
| hook socket
gravity-server (TypeScript, long-running backend)
|-- enrichment, state management, inbox
| semantic patches over terminal socket
Terminal clients
|-- Emacs client (15 modules, ~11.5k lines) -- magit-section UI
'-- macOS menu bar (gravity-menubar, Swift) -- status dots + dropdown
How it works: Claude Code fires hook events (PreToolUse, PostToolUse, Stop, SubagentStart, etc.) which the bridge shim forwards to gravity-server. The server enriches events (transcript parsing, agent attribution), manages session state (turn tree, tool/agent indexes, inbox), and emits semantic patches — typed operations like add_tool, complete_agent, set_plan — to all connected terminals.
Terminals maintain a read-replica of the session state. Any client that speaks the protocol can render the full gravity UI — Emacs, a native app, or a future web dashboard.
See ARCHITECTURE.md for the full system design.
packages/
shared/ -- Shared types (Session, Patch, protocol messages)
emacs-bridge/ -- Claude Code plugin (one-shot hook forwarder)
gravity-server/ -- Stateful backend (state, enrichment, terminal protocol)
gravity-menubar/ -- macOS menu bar app (Swift, standalone)
gravity-server supports multiple simultaneous terminals. Currently two production clients ship with the project.
The full interactive UI. 15 Emacs Lisp modules (~11.5k lines) built on magit-section, providing:
- Session overview — All active sessions grouped by project with status indicators (idle/responding/ended)
- Session detail — Turn-based conversation view with collapsible response steps, inline diffs, agent trees
- Plan review — Dedicated buffer with inline comments,
@claude:markers, diff view, smart approve/deny with structured feedback - Permission management — Review permission requests, generate allow-patterns, write to
settings.local.json - Capabilities browser — All plugins, skills, agents, commands, and MCP servers in a navigatable tree
- Tmux integration — Launch and manage Claude Code sessions in tmux from Emacs; external tmux sessions integrate via hooks
- Inbox — Centralized queue of pending approvals, plan reviews, and questions across all sessions
gravity-menubar is a lightweight Swift app that connects to gravity-server alongside Emacs. It provides at-a-glance session status without switching to your terminal.
- Status dots — One colored circle per active session: green (idle), yellow (responding), orange (needs attention)
- Session dropdown — Sessions grouped by project with status labels ("idle 3m", "responding", "ended") and pending inbox items
- Health monitoring — 10-second heartbeat with 30-second timeout detection, auto-reconnect on disconnect
- Icon state machine — Menu bar icon reflects aggregate state: disconnected, attention (inbox items waiting), responding, neutral
The menu bar is read-only — it observes session state but doesn't send actions back to the server. Think of it as a dashboard you glance at while working in another app.
Build and run: cd packages/gravity-menubar && swift build && swift run
Requires macOS 13+ and Swift 5.9+.
See all pending approvals, plan reviews and other actions in the inbox. React when you want on what you want.
All active sessions at a glance, grouped by project. Status indicators show idle/responding/ended. Session counts, tool counts, elapsed time.
Turn-based conversation view. Each user prompt starts a turn; tools are grouped into response steps with collapsible headings. Assistant thinking (purple) and text (orange) rendered with margin indicators.
Dedicated buffer for reviewing Claude's plans. Add inline comments with c (orange wave-underline overlays). Edit the plan text directly. View diffs with C-c C-d. Smart approve: clean plans pass through, annotated plans auto-deny with structured feedback.
Subagents render as nested trees inside the turn that spawned them. See each agent's tool calls, thinking, and completion text. Running agents highlighted with gold background. Completed agents show duration and summary.
File edits displayed as unified diffs directly in the session buffer, alongside the tool that made them. Read, Edit, and Write operations tracked per file with aggregated diffs available via SPC.
When Claude requests permissions, review in a dedicated buffer. Generate allow-patterns from tool signatures with A (copy) or a (write to settings). Pattern suggestions based on tool name and arguments.
Files section shows all read/edit/write operations with per-file aggregation. Tasks section tracks TaskCreate/TaskUpdate lifecycle with status indicators ([x] done, [/] in progress, [ ] pending).
All plugins, skills, agents, commands, and MCP servers rendered in a collapsible tree. See what's available across global, project, and plugin scopes. Navigate to source files with RET.
Launch and manage Claude Code sessions in tmux directly from Emacs. Compose prompts in a dedicated buffer, send via C-c C-c. External sessions running inside tmux are fully integrated via hooks. Session liveness is monitored server-side.
| emacs-gravity | claude-code-ide.el | claude-code.el + monet | gptel | aider.el / aidermacs | |
|---|---|---|---|---|---|
| Approach | Hook-based server + semantic patches | MCP bridge (Claude calls Emacs) | Terminal emulator (eat/vterm) + IDE protocol via WebSocket (monet) | Direct API client | Aider CLI wrapper |
| What you see | Structured turn tree (magit-section) | Terminal output + MCP-enhanced context | Raw terminal output; monet adds inline diffs and diagnostics | Chat buffer | Terminal output + ediff |
| Multi-session | Yes — per-project grouping, overview buffer | No | Yes — project-aware instances | Multiple buffers | Multiple aider sessions |
| Agent tracking | Full nested tree with transcript access | No | No | N/A | No |
| Plan review | Dedicated buffer, inline comments, diff, structured feedback | No | No | N/A | No |
| Permission mgmt | Pattern generation + write to settings | No | No | N/A | No |
| Inline diffs | In session buffer alongside tool context | No | Yes (monet — ediff or simple diff) | No | Yes (ediff) |
| Multi-client | Yes — Emacs + macOS menu bar (same server) | No | No | No | No |
| Capabilities browser | Plugins, skills, agents, MCP — navigatable | No | No | No | No |
| Needs Claude Code CLI | Yes | Yes | Yes | No (API only) | No (uses Aider) |
| Extra dependencies | Node.js (gravity-server) | None | eat or vterm; monet needs websocket.el | None | Aider (Python) |
Different philosophies: claude-code.el and claude-code-ide.el embed the Claude Code terminal inside Emacs — you interact with Claude's TUI directly. monet enhances claude-code.el with Claude Code's IDE protocol (diffs, diagnostics, go-to-definition) over WebSocket. emacs-gravity hides the TUI entirely and reconstructs the conversation as structured, navigatable data via hooks and a server-driven architecture. gptel and aider.el are general-purpose LLM tools that happen to support Claude models but don't integrate with Claude Code's hook system, agent framework, or plan workflow.
| Google AntiGravity | Cursor | emacs-gravity | |
|---|---|---|---|
| UI paradigm | Web panels in IDE | VS Code sidebar | magit-section (terminal-native) |
| Plan review | View + comment | — | View + comment + diff + structured feedback |
| Agent visibility | Flat list | Minimal | Full nested tree with transcript access |
| Multi-session | No | No | Yes — per-project grouping |
| Multi-client | No | No | Yes — Emacs + menu bar (same server) |
| Extensibility | Closed | Closed (extensions API) | Elisp — fully hackable |
| Runs in | Chrome / Electron | Electron | Terminal / TTY / SSH |
| Open source | No | No | Yes |
- Emacs 27.1+ with
magit-section(>= 3.0) andtransient(>= 0.3) - Node.js 18+ and npm
- Claude Code CLI installed
cd emacs-gravity
npm installThe bridge is a Claude Code plugin that hooks into lifecycle events. Register it via a marketplace file.
Create or edit ~/.claude/plugins/marketplace.json:
{
"name": "local-emacs-marketplace",
"owner": {
"name": "your-name",
"email": "your-email@example.com"
},
"plugins": [
{
"name": "emacs-bridge",
"description": "Bridge to Emacs via Unix Socket",
"source": "/absolute/path/to/emacs-gravity/packages/emacs-bridge"
}
]
}Important: The
sourcepath must be absolute. Claude Code resolves plugins at startup from this file.
After saving, restart Claude Code. You should see hook status messages (e.g., "gravity: session start") in the Claude Code status line, confirming the plugin is active.
Add to your ~/.emacs.d/init.el:
(add-to-list 'load-path "/path/to/emacs-gravity")
(require 'claude-gravity)
(claude-gravity-server-start)This starts gravity-server (if not already running) and connects Emacs as a terminal client.
M-x claude-gravity-status — open the overview buffer
TAB — expand/collapse sections
RET — visit session or file
? — transient menu (all commands)
The Emacs package is split into 15 modular files with a thin loader:
| Module | Purpose |
|---|---|
claude-gravity.el |
Thin loader — requires all modules |
claude-gravity-core.el |
Utilities, logging, custom variables, tlist |
claude-gravity-faces.el |
37 faces and fringe bitmaps |
claude-gravity-session.el |
Session state CRUD |
claude-gravity-discovery.el |
Plugin/skill/agent/MCP capability discovery |
claude-gravity-state.el |
Session state helpers, inbox, tool/agent lookup |
claude-gravity-text.el |
Text rendering: dividers, markdown, wrapping |
claude-gravity-diff.el |
Inline diffs, tool/plan display |
claude-gravity-render.el |
UI section rendering (turns, tools, agents, tasks) |
claude-gravity-ui.el |
Overview/session buffers, keymaps, transient menu |
claude-gravity-plan-review.el |
Plan review buffer, comment overlays, feedback flow |
claude-gravity-client.el |
Terminal socket client to gravity-server |
claude-gravity-actions.el |
Permission/question action buffers, inbox handling |
claude-gravity-tmux.el |
Tmux session management, compose buffer |
claude-gravity-daemon.el |
Agent SDK daemon bridge (ON HOLD) |
claude-gravity-debug.el |
Terminal protocol debug viewer |
Load order: core -> {faces, session, discovery} -> state -> {text, diff} -> render -> ui -> plan-review -> actions -> client -> {tmux, daemon, debug}
Each module has no circular dependencies, making isolated testing and customization straightforward. Every face, keybinding, and rendering function is yours to override.
- ARCHITECTURE.md — System design, modules, hooks, state API
- DEVELOPMENT.md — Build, debug, test workflows
- UI-SPEC.md — Visual specification for all UI states
- docs/refactor-implementation.md — v3 design: gravity-server and terminal protocol
- docs/session-data-model.md — Session plist structure reference
- docs/tmux-interactive-sessions.md — Tmux integration
- OpenCode support — Basic infrastructure exists for OpenCode integration, but it's on hold pending further development on their side.
- Anthropic Agent SDK bridge — A near-complete bridge using
@anthropic-ai/claude-agent-sdkfor a long-running daemon mode (no hooks needed). On hold because the SDK requires a pay-per-use API key — using it with a Claude Max/Pro subscription violates Anthropic's TOS. See #6536. Code lives indaemon.ts/daemon-session.ts/claude-gravity-daemon.el.
GPL-3.0. See LICENSE.









