Skip to content

Latest commit

 

History

484 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Claude Code IDE for Emacs

https://github.com/axiweave/claude-code-ide.el/workflows/CI/badge.svg https://img.shields.io/badge/GNU%20Emacs-28--30-blueviolet.svg https://img.shields.io/badge/License-GPL%20v3-blue.svg

Note: https://yfu.tw/blog/en/open-model-harness/ — I now use omp (Oh My Pi), and it is the only CLI actively checked against. Some omp-specific features (live-prompt window/cursor sync, clipboard image paste, selection-change notifications) require my fork, Axiweave/oh-my-pi, rather than upstream omp.

Overview

Claude Code IDE for Emacs provides project-aware terminal sessions for Claude Code, Codex, OpenCode, Pi, and Oh My Pi, with shared session management, terminal integration, and window workflows. Claude Code additionally has native integration through the Model Context Protocol (MCP), creating a bidirectional bridge between Claude and Emacs that can leverage Emacs features—from LSP and project management to custom Elisp functions.

This project is a fork of manzaltu/claude-code-ide.el and has substantially diverged with a session sidebar/manager, persistent layouts, activity tracking, expanded transient workflows, and Ghostel-only terminal support. The project name is provisional; please open an issue with naming suggestions.

What This Fork Adds

  • CC Manager global and repo-local sidebars, quick slots, and persistent per-session layouts
  • CLI-aware start, continue, and resume workflows for Claude Code, Codex, OpenCode, Pi, and Oh My Pi; see Basic Commands
  • Session state indicators in the CC Manager: Oh My Pi reports idle, working, needs-input, done, and failed over MCP; other agents use output-driven idle and working detection
  • Ghostel-only terminal integration, with vterm and eat support removed; see Terminal Backend Configuration
  • Expanded transient navigation and file-reference workflows; see Basic Commands and Session Customization
  • Remote Worktree Management: explicit remote Worktree list, open, and create through the manager, plus remove/move/merge/push/prune through remote Magit

Features

  • Automatic project detection and session management
  • Terminal integration with full color support using ghostel
  • Image-aware s-v / H-v paste for local Claude Code, Codex, and Oh My Pi, plus the verified remote OMP route
  • CLI-specific start, continue, and resume commands for Claude Code, Codex, OpenCode, Pi, and Oh My Pi
  • Claude Code MCP protocol implementation for IDE integration
  • Tool support for file operations, editor state, and workspace info
  • Extensible MCP tools server for accessing Emacs commands (xrefs, tree-sitter, project info, e.g.)
  • Diagnostic integration with Flycheck and Flymake
  • Advanced diff view with ediff integration (modify suggestions before applying)
  • Tab-bar support for proper context switching
  • Selection and buffer tracking for better context awareness

Emacs Tool Integration

This package enables Claude Code to leverage the full power of Emacs through MCP tools integration. Claude can directly access and utilize Emacs capabilities including:

  • Language Server Protocol (LSP) integration through xref commands for intelligent code navigation (eglot, lsp-mode and others)
  • Tree-sitter for syntax tree analysis and understanding code structure at the AST level
  • Imenu for structured symbol listing and navigation within files
  • Project integration for project-aware operations
  • Any Emacs command or function can be exposed as an MCP tool, allowing Claude to:
    • Perform project-wide searches and refactoring
    • Access specialized modes and their features
    • Execute custom Elisp functions tailored to your workflow

This deep integration means Claude Code understands your project context and can leverage Emacs’ extensive ecosystem to provide more intelligent and context-aware assistance.

Screenshots

Active File Awareness

Claude Code automatically knows which file you’re currently viewing in Emacs

Code Selection Context

Claude Code can access and work with selected text in your buffers

Advanced Diff View with Diagnostics

Integrated ediff view for code changes, with Claude Code able to directly access diagnostic data (errors, warnings, etc.) from opened files

Automatic Text Mentions

Automatically mention and reference selected text in Claude conversations

Session Restoration

Resume previous Claude Code conversations with the –resume flag

Installation

Prerequisites

  • Emacs 28.1 or higher
  • A supported coding-agent CLI installed and available in PATH: Claude Code (claude, the default), Codex (codex), OpenCode (opencode), Pi (pi), or Oh My Pi (omp)
  • ghostel package (for terminal support)

Installing Claude Code CLI

Follow the installation instructions at Claude Code Documentation.

Installing the Emacs Package

Currently, this package is in early development.

To install using emacs-version >= 30 and use-package with the vc binding:

(use-package claude-code-ide
  :vc (:url "https://github.com/axiweave/claude-code-ide.el" :rev :newest)
  :bind ("C-c C-'" . claude-code-ide-menu) ; Set your favorite keybinding
  :config
  (claude-code-ide-emacs-tools-setup)) ; Optionally enable Emacs MCP tools

To install using use-package and straight.el:

(use-package claude-code-ide
  :straight (:type git :host github :repo "axiweave/claude-code-ide.el")
  :bind ("C-c C-'" . claude-code-ide-menu) ; Set your favorite keybinding
  :config
  (claude-code-ide-emacs-tools-setup)) ; Optionally enable Emacs MCP tools

Doom Emacs

In packages.el:

(package! claude-code-ide
  :recipe (:host github :repo "axiweave/claude-code-ide.el"))

In config.el:

(use-package! claude-code-ide
  :bind ("C-c C-'" . claude-code-ide-menu) ; Set your favorite keybinding
  :config
  (claude-code-ide-emacs-tools-setup)) ; Optionally enable Emacs MCP tools

After saving the above, run: doom sync in the terminal.

Usage

Basic Commands

The easiest way to interact with Claude Code IDE is through the transient menu interface, which provides visual access to all available commands. Simply run M-x claude-code-ide-menu to open the interactive menu.

With a C-u prefix, launch suffixes s/S, d/D, c/C, and r/R prompt for claude, codex, opencode, pi, or omp for that new session only. Uppercase suffixes still explicitly bypass permissions.

CommandDescription
M-x claude-code-ide-menuOpen transient menu with all Claude Code commands
M-x claude-code-ide-emacs-tools-setupSet up built-in MCP tools (e.g. xref, project)
M-x claude-code-ideStart Claude Code for the current project
M-x claude-code-ide-send-promptSend prompt to Claude from minibuffer input
M-x claude-code-ide-continueContinue most recent conversation in directory
M-x claude-code-ide-resumeResume Claude Code with previous conversation
M-x claude-code-ide-stopStop Claude Code for the current project
M-x claude-code-ide-switch-to-bufferSwitch to project’s Claude buffer
M-x claude-code-ide-list-sessionsList all active Claude Code sessions and switch
M-x claude-code-ide-manager-toggle-sidebarToggle the default CC Manager sidebar
M-x claude-code-ide-manager-toggle-global-sidebarToggle the global CC Manager sidebar
M-x claude-code-ide-manager-toggle-repo-sidebarToggle the repo-local CC Manager sidebar
M-x claude-code-ide-manager-focusFocus the default CC Manager sidebar
M-x claude-code-ide-manager-focus-globalFocus the global CC Manager sidebar
M-x claude-code-ide-manager-focus-repoFocus the repo-local CC Manager sidebar
M-x claude-code-ide-manager-refreshRefresh the CC Manager live session list
M-x claude-code-ide-check-statusCheck if Claude Code CLI is installed and working
M-x claude-code-ide-insert-at-mentionedSend selected text to Claude prompt
M-x claude-code-ide-send-escapeSend escape key to Claude terminal
M-x claude-code-ide-insert-newlineInsert newline (LF for omp, \ + Enter otherwise)
M-x claude-code-ide-toggleToggle visibility of Claude Code window
M-x claude-code-ide-toggle-recentToggle most recent Claude window globally
M-x claude-code-ide-show-debugShow the debug buffer with WebSocket messages
M-x claude-code-ide-clear-debugClear the debug buffer

Current-File References

Use @ in claude-code-ide-menu to reference the current file. The path is relative to the receiving Session directory. Selected lines retain the #L316 or #L316-320 suffix.

For a Session on v12mac at /Users/yufu/v12x, the remote file /rpc:v12mac:/Users/yufu/v12x/packages/core/lib/executor.ts becomes @packages/core/lib/executor.ts#L316 when line 316 is selected. A file outside that directory uses its absolute host-local path without the RPC prefix.

The RPC destination must exactly match the Session’s configured destination. Different destinations, unsupported remote routes, and missing Session context produce an error before insertion. The action does not resolve SSH aliases or establish new connections. Local behavior and the separate # action remain unchanged. The f, F, and h actions browse the Session host through the editor transport and send a path without the editor’s remote connection prefix. f searches the Session directory on that host, and h the account home directory. f and F send a path relative to the Session directory, and h an absolute path. Set claude-code-ide-file-reference-picker-function to a flat search such as fd through consult to pick a file by search for f instead of by directory. A prefix argument, and h, keep the read-file-name prompt.

Multi-Project Support

Claude Code IDE automatically detects your project using Emacs’ built-in project.el. Each project gets its own Claude Code instance with a unique buffer name like *claude-code[project-name]*.

You can run multiple Claude Code instances simultaneously for different projects. Use claude-code-ide-list-sessions to see all active sessions and switch between them.

Window Management

  • Running claude-code-ide when a session is already active will toggle the window visibility
  • The window can be closed with standard Emacs window commands (C-x 0) without stopping Claude
  • Use claude-code-ide-toggle-recent to toggle the most recent Claude window from anywhere, regardless of your current project context. This is useful when you’re outside a project directory but want to quickly hide/show Claude

Persistent Sessions with zmx

Agent processes normally die with Emacs. With zmx installed, the package can run each agent CLI inside a zmx session. The process then survives Emacs restarts, buffer kills, and dropped connections. You can detach in Emacs and reattach from a plain terminal, or the reverse. See the zmx guide for setup, attachment, lifecycle, and troubleshooting details.

Enable it globally:

(setq claude-code-ide-use-zmx t)

How it works:

  • New sessions run as zmx attach <name> <agent-command>. Names follow cci-<agent>-<project>-<id> (see claude-code-ide-zmx-session-prefix).
  • On session start, matching zmx sessions for the project and agent are offered for reattach, with a “Create new session” option. Continue and resume offer only matching sessions with zero attached clients.
  • When cc-manager is hidden, reattachment from Start keeps it hidden and preserves the editor windows. The terminal opens in the configured side window. When cc-manager is visible, reattachment uses its managed layout.
  • M-x claude-code-ide-attach lists all zmx sessions, including ones started outside Emacs, and adopts the selection into a full session with idle tracking and manager visibility.
  • Killing the terminal buffer detaches only. Closing its window only hides the terminal. M-x claude-code-ide-stop asks before it kills the zmx session. That stops the agent for every attached client. From a terminal, use zmx attach <name> and zmx kill <name>.

Known limitation: environment variables such as the Claude Code MCP port are frozen when the zmx session is created. If you reattach from a different Emacs instance, or after an Emacs restart, port-based integrations (MCP, SSE) break for that session. Plain terminal use of the agent is unaffected. Exception: Oh My Pi rediscovers the Emacs SSE endpoint and reconnects on its own, so selection sync and session state resume after an Emacs restart.

The zmx integration follows the design of emacs-term-sessions (GPL-3+), which provides general-purpose persistent terminals on top of zmx. This package implements only the small agent-session subset itself, so there is no dependency. Use emacs-term-sessions when you want persistent shells beyond coding agents.

Existing Remote Agents

Remote attachment connects to an existing zmx session through SSH. It never starts an Agent or creates a remote zmx session. See the remote guide for host setup, attachment, Project views, cleanup, and troubleshooting details.

Reattachment works with stock zmx. Emacs runs zmx attach <name> false to adopt an existing session. If a target disappears after discovery or a reconnect check, the false guard ends the replacement session immediately. No shell, Agent, or persistent replacement remains. This guard applies to local adoption and remote reattachment. Ordinary local session creation stays unchanged. See the attach guard contract for the verified versions.

Configure exact SSH destinations:

(setq claude-code-ide-remote-hosts '("my-agent-host" "user@another-host"))

The default list is empty. Your SSH configuration owns authentication, ports, jump hosts, and trusted host keys. Prepare these outside Emacs. Remote control requests cannot prompt for passwords or accept new host keys. Each control request has a 30-second deadline.

The remote executable is zmx from the remote command environment’s PATH. claude-code-ide-zmx-program controls only local zmx. Remote attachment does not require a local zmx or Agent executable.

  1. Run C-u M-x claude-code-ide-attach.
  2. Select a configured host.
  3. Select an existing Agent.

Use C-u M-x claude-code-ide-attach-all for bulk attachment. Use C-u M-x claude-code-ide-attach-select for marked selection. Without a prefix, these commands keep their local behavior. Bulk attachment names entries that lack usable metadata. Individual attachment permits manual Agent identification and remote-directory text entry. Neither value becomes a remote launch command.

Remote rows appear only in the global manager. Flat labels retain [HOST] PROJECT after rename. Grouped headings retain the host and project. Matching paths and zmx names on different hosts remain separate targets.

Selecting a connected row opens its terminal. Selecting a disconnected row does not contact its host. Press c to reattach explicitly with the same Session ID. Refresh, startup, and restored layouts never reconnect automatically.

A remote Attach process can end because the Agent exited or because the link dropped. When an Attach process ends, Emacs asks the host once with zmx list --short. A missing target proves the Agent exited, so Emacs removes the row. A listed target, a failed check, or a slow check keeps the disconnected row. An explicit detach never contacts the host.

Press s on a connected remote row to start a fresh Agent on that exact host and directory. The direct interactive SSH path creates a new zmx target without a Worktree operation. Remote S and prefixed s remain unavailable because remote launch ignores local CLI options.

A successful attachment requests project metadata asynchronously. A metadata failure does not undo attachment. Press ? m in the manager to refresh cached Git metadata for one configured host. The command uses known connected and disconnected rows. It does not discover or reattach Agents. Ordinary G refresh, startup, layout restore, view changes, and navigation never request remote metadata.

Metadata requests reject control characters, including DEL and C1 controls. Git response paths must have canonical absolute syntax. Emacs does not resolve these paths on the local filesystem. A malformed response rejects the whole batch. Failure reports identify the host and affected directories. Metadata failures preserve the last valid cache and do not close terminals.

Before reattaching a remembered remote row, Emacs checks the exact target with zmx list --short. A missing target or failed SSH check stops attachment before a terminal starts. Fresh attachments use discovery results without another SSH check. If the attach client exits during setup, Emacs reports an error instead of success.

Press D or X to detach the local client and remove its manager row. For a disconnected remote row, these commands remove only local history and the saved layout without contacting the host. Neither command stops the remote agent.

Press K to Stop the exact selected target. Stop asks for confirmation and names the host, target, and effect on all clients. After Stop, Emacs removes the row only when zmx confirms the kill and a separate request confirms absence. A timeout or ambiguous result leaves the row intact. Emacs never retries a kill.

Remote attachment uses the Ghostel backend, the package’s only terminal backend. Remote layouts show only the terminal unless you enable optional remote Project views. Remote project launch, Treemacs actions, text transfer, MCP, and SSE setup remain outside this mode. Remote companions support Magit, Dired, or an ordinary Ghostel shell, matching the selected layout preset. Use their normal commands for interactive Git, file access, or shell commands.

If attachment fails, inspect the host-qualified error. Check SSH authentication, trusted host keys, and remote PATH. A missing target remains disconnected. Emacs never replaces it with a new agent session. See the validation guide for backend coverage and the live acceptance procedure.

Optional Remote Project Views

Remote Project views require an installed compatible tramp-rpc client and its configured server binary on the remote host. Install and configure them separately. The package does not download, build, install, update, or deploy either component. Configure SSH credentials and host keys before use because automatic preparation cannot prompt.

Enable each exact host separately:

(setq claude-code-ide-remote-hosts '("my-agent-host")
      claude-code-ide-remote-project-view-hosts '("my-agent-host")
      claude-code-ide-remote-project-cleanup-hosts nil)

claude-code-ide-remote-hosts remains the access approval list. claude-code-ide-remote-project-view-hosts does not approve a host by itself. Changing either Project-view option starts no remote work.

The first managed display shows the terminal in an ordinary window. It then starts Project-view preparation in the background. The feature checks the current RPC connection and remote directory before it uses the configured status provider. The provider uses Magit when available and its normal Dired fallback otherwise. A failure leaves the terminal usable and reports the host, failed phase, and corrective action.

shell-left and shell-right use these same two host lists. There is no separate remote-shell approval list. Remote shells follow the installed RPC client’s PTY policy and Ghostel’s remote shell preferences. That policy can use a direct SSH PTY or an RPC PTY. An unsupported remote host produces an explanation instead of a local shell. See the remote guide for exact host admission, companion identity, and lifecycle details.

Project-view identity includes the exact host, canonical Worktree or directory, companion kind, captured provider, and requested directory. Different provider identities can share a native buffer. Cleanup preserves that buffer while another registered owner uses it. The feature reuses every surviving matching buffer without refreshing it. Use the view’s native g command when you want a refresh.

Close a Project-view window to suppress its automatic display for that Session. This suppression survives navigation and remote reattachment in the current Emacs process. Press manager R to reset the full layout and clear suppression. A fresh preparation worker runs a health check. A reset or mirror that reuses a live companion shell starts no worker or connection. Open the manager menu with ?, then press C to cancel only the pending Project-view attempt. Cancellation does not detach the terminal or close a shared RPC connection.

claude-code-ide-remote-project-cleanup-hosts independently permits conservative local buffer cleanup. Cleanup runs only after successful manager D or X detach. It can close only an unmodified Magit or Dired view that this feature created for the detached Session. It retains reused, custom, modified, shared, source-file, process, temporary, and uncertain buffers. It also retains buffers with unknown local kill or query hooks. Cleanup never saves, prompts, makes a remote request, or closes an RPC connection. Terminal close, network loss, Stop, and Emacs exit do not run this cleanup.

Remote Worktree Management

Remote Worktree management extends remote Agent attachment with explicit remote Worktree list, open, and create actions, plus the remove, move, merge, push, and prune actions available through remote Magit. Every action targets one exact Configured host and one absolute remote repository path. It never scans a host for repositories and never substitutes a local target when an action refuses.

Terms

  • Worktree: a main or linked working directory of one Git repository on one host.
  • Worktree backend: lane or wt (Worktrunk), selected per repository the same way as local worktree creation.
  • Remote agent and Session: as defined in Existing Remote Agents.
  • Worktree operation: one requested action (list, open, create, remove, move, merge, push, or prune) with a captured host, targets, and reported steps. Its result can remain unknown after observation ends.
  • Outcome check: an explicit, read-only re-examination of an operation’s remote state.

See CONTEXT.md for the full glossary.

Manager Commands

Press W in the sidebar, or in the main transient’s manager section, to open the Remote Worktree menu (claude-code-ide-manager-remote-worktree-menu):

KeyCommandEffect
oclaude-code-ide-manager-open-remoteAlways choose a Configured host and repository, select a Worktree, then reuse/attach/start its Agent. The repository picker lists recent paths for that exact host and also accepts a new absolute path as minibuffer input. A prefix argument starts an explicit sibling Agent.
wclaude-code-ide-manager-new-remote-worktreeChoose a Configured host and repository, ask one new name, create the Worktree, and start the configured Agent. A prefix argument creates only, then opens remote Magit without an Agent.
rclaude-code-ide-remote-worktree-showDisplay a retained operation’s result. Makes no remote request.

On an existing remote Session row or inside an existing remote Magit buffer, plain o (claude-code-ide-manager-open) and w (claude-code-ide-manager-new-worktree) already use that context’s exact host and repository, skipping the extra prompts. C-u o there starts an explicit sibling Agent; C-u w there creates the Worktree only.

The manager remembers at most 20 successfully requested repository paths per exact host, with the newest path first. It stores this history with manager persistence. Cancelled input and refused requests do not change it. A restored path never causes remote access.

Each command returns an operation ID rather than a path or session object. Every result stays attached to its captured host, so identical paths on two hosts never share a Session match or a result.

Remote Launch Configuration

claude-code-ide-remote-launch-config is an alist keyed by exact Configured host. Each value can override the Agent executable, Agent arguments, launch environment, or fresh-launch shell:

(setq claude-code-ide-remote-launch-config
      '(("my-agent-host" :executable "claude" :args ("--model" "sonnet"))
        ("ramhorn"
         :environment ("SKIP_TMUX=1")
         :shell "/usr/bin/zsh"
         :shell-args ("-lic"))))

The default executable is the globally selected Agent’s standard command name. Remote arguments and environment assignments default to empty lists. Local executable paths, local CLI flags, and local MCP settings are never inherited.

:environment is an optional part of the shell preference. It is a list of literal NAME=VALUE strings. Names must be unique shell variable names. The reserved ZMX_SESSION and ZMX_SESSION_PREFIX names are invalid. Each assignment initializes the configured shell before startup files run. The resulting value reaches the fresh Agent unless those files replace it. This lets ramhorn set SKIP_TMUX=1 before its startup files select a terminal multiplexer.

:shell and :shell-args form an optional pair. The shell path must be absolute. The nonempty argument list must tell that shell to execute the package command that follows it. The package does not append -c. For zsh, ("-lic") loads login and interactive startup files before it executes the command.

These settings apply only when a fresh sibling or Worktree Agent starts on that exact host. A host without them keeps direct launch. Attach, reattach, detach, and Stop never apply them.

Worktree preparation resolves the Agent in the selected environment. The owned zmx bootstrap then initializes that environment before the runner validates and starts the Agent. The control protocol uses a fixed locale and private permissions. The runner restores the shell’s locale and umask when it starts the Agent.

Explicit Refresh

Remote Lane and Worktrunk sections in Magit render an explicit snapshot; they never run a synchronous backend command while rendering. Request a fresh snapshot with M-x claude-code-ide-remote-worktree-refresh, or the corresponding refresh key in the magit-lane or magit-worktrunk transient on a remote Worktree. Ordinary manager navigation, automatic idle refresh, and startup never contact a host for this listing.

Lifecycle Boundaries

The manager provides list, open, and create only. Remote Magit supplies the supported remove, move, merge, push, and prune actions. Backend commands and native Magit move capture use the same protected operation boundary. Native Magit push capture uses it only when claude-code-ide-remote-worktree-capture-native-push is non-nil (default nil); otherwise Magit pushes natively. Native capture preserves selected force flags, destination interpretation, and resolved publication refs before execution. See magit-lane and magit-worktrunk for each backend’s operation table and prerequisites. Lane refuses movement because it owns a fixed tree location. No backend moves a Worktree between hosts.

Worktrunk merge records landing and cleanup separately. A new blocking Agent can prevent cleanup after successful landing. Results retain that landing, and an explicit retry never repeats it.

Only a selected Lane backend uses the Lane initialization setting. Its instruction-file change still requires separate approval. Worktrunk rejects explicit Lane-only initialization options.

Agent Protection

A known Agent in an affected Worktree blocks removal, movement, history rewriting, and cleanup, even when idle or detached. A merge check covers both the source and destination Worktree. Failed Agent discovery, or an affected Agent whose identity cannot be resolved, blocks the action instead of assuming it is safe. Stop the Agent explicitly first, then retry: no Worktree action stops an Agent as a side effect, and force never bypasses this check.

Protection includes canonical descendant directories, including nested repositories and submodules. Sibling paths with the same prefix do not match.

Check Outcome and Retry

Progress appears without a focus change. Messages identify requests that cannot replace the selected result. Every result stays available through r in the Remote Worktree menu or M-x claude-code-ide-remote-worktree-show.

The results buffer provides these controls:

KeyEffect
gCheck outcome: an explicit, read-only re-examination of the captured host and target. Never mutates, retries, launches an Agent, or approves a hook.
rRetry: submits only a step Check outcome proved both unfinished and safe to attempt. Disabled otherwise. This is a new mutation with fresh confirmation, never a replay of a completed or uncertain step.
cCancel observation: stops local observation. It never stops or rolls back an already-submitted remote operation.
aRecover attachment: attaches the Agent an operation already started, when only that step remains.
vRecover view: reopens the remote view an operation already produced.
sSelect: choose which retained operation the buffer displays.
qClose: closes the results buffer. The operation record and any remote work continue.

Check outcome distinguishes completed, still running, confirmed unfinished, partially completed, and still unknown results. A matching directory or a missing response alone never proves completion. An entered command with a nonzero exit shows failed, even when its effects leave the overall outcome unknown. Retry never repeats an entered failed step.

You can inspect the same operation’s results while its owned attachment or Project-view completion continues. If an unrelated view owns focus at completion, the results show a deferred continuation and retain its recovery target. After you close results or cancel observation, only an explicit recovery action can attach a terminal or change the Project view.

Normal completion requests removal of an eligible completed operation resource after it retains terminal proof. It keeps unknown, partial, running, and live-bootstrap resources. Check outcome never removes resources.

Optional Dependencies

Remote Worktree management lives in claude-code-ide.el and calls into magit-lane or magit-worktrunk only when that package is loaded and its binary resolves on the selected host. Neither backend package requires claude-code-ide at load time; a remote-aware backend command reports that claude-code-ide is not loaded instead of doing partial work.

Remote Project views opened by create-only or remote Magit actions need the same optional tramp-rpc client as Optional Remote Project Views, currently Emacs 30.1 or later. Remote listing, creation, and launch through the results buffer still target Emacs 28.1 or later without that client.

Local worktree, Agent, and Magit workflows keep their existing behavior. No new host prompt, confirmation, or launch step is inserted into a local action.

CC Manager

claude-code-ide-manager-toggle-sidebar opens a dedicated left sidebar for Sessions. Existing commands, including claude-code-ide-list-sessions, keep their behavior.

CC Manager supports two scope families:

  • a global manager across live Sessions and remembered remote rows
  • a repo-local manager keyed by the current Git root

Generic commands such as claude-code-ide-manager-toggle-sidebar and claude-code-ide-manager-focus use claude-code-ide-manager-default-target to choose which scope to target. Explicit global and repo-local commands remain available when you want to bypass that policy.

The manager can:

  • Show flat rows or host-qualified project groups in the global manager
  • Show repo-local sessions with branch-first labels by default, falling back to basename when detached
  • Keep pinned Sessions above unpinned Sessions within each project in grouped view
  • Keep one manual order across flat and grouped global views
  • Edit and pin the complete session order for one manager scope
  • Restore per-session window layouts when you switch back
  • Put the sidebar cursor on the current Session when focus enters the sidebar

New manager layouts and explicit resets use claude-code-ide-manager-layout-preset. Each preset selects the companion type and side. The old separate side preference no longer controls layouts.

PresetCompanionSide
magit-left (default)Configured Git viewLeft
magit-rightConfigured Git viewRight
dired-leftDiredLeft
dired-rightDiredRight
shell-leftOrdinary Ghostel shellLeft
shell-rightOrdinary Ghostel shellRight

The Agent stays on the other side with its existing buffer and backend. The default Git provider uses Magit when available, with Dired as its fallback. The Dired presets always open the exact Session directory directly. The shell presets create ordinary terminals, not additional managed Agent Sessions. Manager state can persist across Emacs restarts through persist.el. See Switching Behavior for saved-layout precedence and shell lifetime.

The Magit presets temporarily retain claude-code-ide-manager-status-buffer-function for custom Git content. Dired and shell presets ignore this setting.

Entry Points

You can reach the manager in two ways:

  • Run M-x claude-code-ide-manager-toggle-sidebar to toggle the sidebar
    • pass a positive prefix argument to force open and focus
    • pass a negative prefix argument to force hide
  • Run M-x claude-code-ide-manager-toggle-global-sidebar to always target the global manager
  • Run M-x claude-code-ide-manager-toggle-repo-sidebar to always target the repo-local manager for the current Git root
  • Open the main transient and use:
    • t to toggle the default manager sidebar
    • T to toggle the global manager sidebar
    • o to toggle the repo-local manager sidebar
    • n to move to the next manager session and switch to it
    • p to move to the previous manager session and switch to it
    • P to pin or unpin the current active manager session
    • E to edit and pin the complete order for the selected manager scope
    • 1..9 to switch to manager slots 1 through 9
    • 0 to switch to manager slot 10
    • M to focus the manager window
    • G to refresh the local Session list without network requests
  • Press ? in the sidebar to open its manager menu.
    • v toggles flat and grouped global views
    • f toggles the focused view
    • C-j and C-k move between project groups
    • m refreshes cached project metadata for one configured remote host
    • o opens a project or worktree: in the global view it asks for the project, then for the worktree when the project has more than one. A target with a Session switches to it. C-u o starts a sibling Session at once. Otherwise the Start/Continue/Resume menu appears.
    • w creates a worktree and starts the default Agent in it. In the global view the project comes from the row under point, and is asked only when point is on no row. It asks for one name that becomes the branch and the tree. C-u w creates the tree and opens magit-status without an Agent.

Worktree Creation

claude-code-ide-worktree-backend selects the tool that creates a worktree: lane (copy-on-write trees under .lane/trees/ through magit-lane) or wt (Worktrunk, through magit-worktrunk). A repository that already has a .lane/ store always uses lane. Otherwise a directory-local value wins, then the git config key claude-code-ide.worktree-backend, then the global default. Neither Magit package is required at load time. The command reports the missing package or binary before it asks for a name.

With lane, a repository without a .lane/ store gets a bare one, created silently. Every lane command works on it, including note and why. What it lacks is the AGENTS.md protocol block that tells agents to use lane memory. Set claude-code-ide-lane-init-protocol to t to get one question before lane init instead, which writes that block, or run lane init by hand later. Names that already exist as a branch, or as a lane, are refused before anything is created.

claude-code-ide-manager-open-directory is the public entry for other packages: given a local directory it switches to its Session, or starts the default Agent there. magit-lane and magit-worktrunk bind a on their rows and transients to it.

What The Sidebar Shows

The sidebar shows live Sessions. The global manager also retains disconnected remote rows.

  • Flat global rows show the project basename
  • Grouped global rows show a branch or directory label below a host-qualified project heading
  • Repo-local manager rows use claude-code-ide-manager-repo-label-strategy, which defaults to branch-first with basename fallback
  • The full project path is available via hover text and in the echo area when point moves onto the row
  • The currently active session row is highlighted
  • The left gutter shows 📌 for pinned rows
  • Visible rows are assigned quick slots 1..9, 0 from top to bottom

Quick slots are derived from the current visible order. They are not stored separately, so pinning or reordering a row immediately changes which session each slot selects.

Grouped Global View

Press v to toggle the global manager between flat and grouped views. Repo-local managers keep their existing view. The manager saves the global view choice when persistence is enabled.

Press f to toggle the focused view. It shows only Sessions that need attention, numbered from 1, and the number keys follow those numbers. Set claude-code-ide-manager-focused-view to choose the view at startup. The f key changes only the running Emacs and never saves the setting. A Session that you handled leaves after you switch to another Session. A Session that waits for input stays. In the focused view, G shows every Session for one Avy pick and then returns to the focused view.

Git worktrees share one project heading when their canonical Git common directories match. Separate Git directories stay separate, even when project paths match. The host remains part of every remote group identity. Remote non-Git and unresolved groups use exact directory text. Thus /a/b and /a/b/ remain separate unresolved groups until metadata resolves them. For a separate Git directory, the heading uses that directory’s basename. Matching heading names also show their paths. A remaining collision shows the group identity. Headings do not accept Session actions. There are no project-wide actions. Rows use cached branch names, with directory names when no branch is available. Custom names appear after that label.

C-j and C-k choose the first row of the next or previous project group and wrap at the end. Selecting a disconnected row does not connect or change the active Session. Press c to reattach explicitly.

Grouped moves and editor Apply reorder only positions already occupied by the affected group in the flat sequence. For example, moving A2 above A1 changes A1 B1 A2 B2 to A2 B1 A1 B2. The first successful grouped move or Apply creates shared order keys when needed. Those keys also fix the fallback order of other rows in the shared flat sequence. Toggling views does not change the order.

Group order is stored for the global scope. Remote and local groups mix freely. M-P and M-N move the current row’s project group up or down. M-p and M-n move a group when the row is the only row of that group. A group move never changes row order keys, so the flat view keeps its order. A group with no stored position follows the stored groups, sorted by heading name.

In grouped global view, E includes live and disconnected rows under project headings. M-p and M-n move rows only within the same project. M-P and M-N move a complete project block with its rows. Each group has one heading line, which shows [HOST] PROJECT for a remote group. Headings are writable so Evil V, d, and p can move a heading with all its rows. Paste complete project blocks between other blocks. Each Session must remain under its original heading. Apply rejects changed heading text or identity, duplicate or missing headings or rows, edited labels, and changed project membership. Failure leaves the editor, pins, and order unchanged.

Session State Indicator

Each row reserves a left gutter so the session names stay aligned whether or not a marker is present.

  • Oh My Pi rows show the state the agent reports over MCP: ? when a dialog waits for you (approval, ask tool, extension prompt), ✓ when a turn finished, ✗ when a turn failed, ⚙︎ while working, and no marker when idle
  • Viewing a ✓ or ✗ row’s session clears the marker; ? stays until the agent reports again
  • ! clears output-idle bells and acknowledges completed or failed results for all live sessions, even with output-idle monitoring disabled. Working and input-request states stay visible.
  • A clear before the first agent report remembers a pending acknowledgment across reconnects. A working or input-request report resets the acknowledgment, so later results appear.
  • Rows without an agent report fall back to output detection: idle-enabled rows that are currently idle show 🔔, rows with recent output show ⚙︎
  • Pinned rows show 📌 in that gutter when no state marker applies
  • State markers take priority over output markers, which take priority over the pin marker
  • Rows with no marker keep the same alignment with blank gutter padding
  • Row faces: red claude-code-ide-manager-attention-session-face is reserved for ? and ✗, ✓ uses the blue claude-code-ide-manager-done-session-face, working rows use the green claude-code-ide-manager-working-session-face, and output-detected idle rows use the amber claude-code-ide-manager-idle-session-face
  • State highlighting applies only to non-current rows
  • The current session keeps claude-code-ide-manager-current-session-face even when it is idle
🔔 project-a
  project-b

State-Priority Navigation

M-x claude-code-ide-manager-next-priority-session focuses the next unvisited session’s terminal from any window, including when the sidebar is hidden. It uses the current manager scope, or the configured default scope when no sidebar is visible. It includes offscreen rows but excludes sessions without a live process and buffer.

The command uses this priority order:

  1. Reported needs-input
  2. Reported failed
  3. Reported done
  4. Output-idle with tracking enabled and no reported state
  5. Reported working, or output-working with tracking enabled and no reported state
  6. Other states, including reported idle

Reported state takes precedence over output flags. Within each priority, the command preserves sidebar pin and manual order. The current session counts as visited. New sessions join the current pass, and state changes can promote unvisited sessions. A visited session that changes to needs-input, failed, or done becomes eligible again within the pass. A new output-idle bell also renews a visited session when tracking is enabled and no reported state masks it. The command selects these changed sessions and unvisited sessions in the same priority order. After these visits, it returns to the first interrupted session before starting another pass. Repeated unchanged reports and unchanged bells do not interrupt the pass. Clearing a bell cancels its pending interruption. The return target must remain live and eligible. A manual visit to that target completes the return.

Global and repository scopes keep separate passes, shared across frames until Emacs restarts. A manual switch counts when that session is current at the next priority command. The normal switch path acknowledges done and failed but leaves needs-input unchanged. The package does not assign a global key to this command. Existing Avy selection and row-order navigation stay unchanged.

M-x claude-code-ide-manager-next-uncleared-session uses the same priority order but skips the final group of cleared or unmarked sessions. It still includes working sessions. Acknowledged results leave this cycle, while unresolved input requests remain eligible for later passes. This command keeps its own pass for each scope, separate from claude-code-ide-manager-next-priority-session. If no other uncleared session remains, it reports a user error without changing focus. Neither command changes the other’s visits or global key binding. Both forward commands select the agent’s window after the switch, even when a saved layout would restore editor focus.

M-x claude-code-ide-manager-previous-priority-session and M-x claude-code-ide-manager-previous-uncleared-session walk back through the sessions the matching pass left, most recent first. They skip sessions that left the scope and keep the forward pass’s visits. These commands do not force the agent window. Focus follows the target session’s saved layout, exactly as slot switching and manager row selection do, so the user returns to the buffer they last used there. That is the agent window when they left it selected, or when the saved buffer is gone. If no earlier session remains, they report a user error without changing focus.

Sidebar Keys

When point is in the manager buffer:

  • n moves to the next row, cycling to the first row after the last, and switches to it
  • p moves to the previous row, cycling to the last row before the first, and switches to it
  • RET switches to the session at point
  • g labels visible session names with Avy and focuses the selected session, like RET
  • SPC switches to the session at point
  • P toggles pin state for the selected row
  • E opens the complete pin-order editor for the selected manager scope
  • s starts a sibling session with the current CLI; S starts one with explicit permissions bypass
  • C-u s or C-u S prompts for a one-session CLI selection (uppercase also bypasses permissions)
  • a adopts a zmx session via claude-code-ide-attach (see Persistent Sessions with zmx)
  • W opens the Remote Worktree menu for a Configured host
  • D or X detaches the selected zmx-backed session and removes its row without stopping the agent, even when disconnected
  • c explicitly reattaches the selected disconnected remote target
  • K confirms Stop for the exact selected target
  • R resets the selected session to the configured layout preset, replacing a missing or exited companion shell
  • M-p moves the selected row up within its current pinned or unpinned group
  • M-n moves the selected row down within its current pinned or unpinned group
  • M-p or M-n moves the project group instead when the row is its group’s only row
  • M-P and M-N move the selected row’s project group up or down in grouped global view
  • v toggles flat and grouped global views
  • f toggles the focused view: only Sessions that need attention, numbered from 1
  • C-j moves to the next project in grouped global view
  • C-k moves to the previous project in grouped global view
  • ? m refreshes cached project metadata for one configured remote host
  • G refreshes the sidebar without network requests. In the focused view, G shows every Session for one Avy pick instead, and ? G still refreshes
  • 1..9 jump directly to the corresponding visible slot
  • 0 jumps to slot 10

g and C-u g search only the selected manager window. Labels start at each session name’s first character. ESC and C-g cancel selection.

Pins stay above unpinned rows within each project in grouped view. Flat view keeps all pinned rows above unpinned rows. Row moves never cross a pin boundary.

Pin Order Editor

Press E in the sidebar or main transient to open the pin-order editor. You can also run M-x claude-code-ide-manager-edit-pin-order.

The flat and repo-local editors list Sessions that were live when the editor opened. The grouped global editor also includes disconnected remote rows. Each Session has one numbered row.

  • M-p moves the current row up and renumbers all rows
  • M-n moves the current row down and renumbers all rows
  • M-P moves the current group block up with its rows and renumbers all rows
  • M-N moves the current group block down with its rows and renumbers all rows
  • In Evil mode, use V, d, and p to move complete rows within a project or complete project blocks
  • Stale row numbers are allowed
  • C-c C-c validates every opening row and heading, clears scope pins, and applies the displayed order
  • Empty lines between rows are allowed
  • C-c C-k discards all edits

Apply requires every opening row exactly once with unchanged visible text. It infers pin order from physical row order and ignores displayed numbers. Hidden session keys identify rows, so equal visible names remain distinct.

Do not recreate rows by typing their text. Typed rows do not contain the required hidden session key.

Sessions started after the editor opens stay outside its snapshot. Apply leaves those sessions unpinned, so the configured fallback sort still orders them.

Switching Behavior

The manager saves and restores layout per session key.

When you switch from one managed session to another:

  1. The current layout is captured for the session you are leaving
  2. If the target session already has a saved layout, that layout is restored
  3. Otherwise the manager builds the configured claude-code-ide-manager-layout-preset (see CC Manager for the six preset values)
  4. Focus returns to the last selected window for that session when possible
  5. If the previous focused window no longer exists, focus falls back to the Claude session buffer

If the target session buffer is gone by the time you switch, the manager refreshes itself and aborts cleanly instead of leaving stale sidebar state behind.

A saved layout always wins over the configured preset. Changing claude-code-ide-manager-layout-preset never touches an existing saved layout or a running companion shell.

Press R to discard the saved layout and rebuild the current preset explicitly. Only this explicit reset, or a brand-new session with no saved layout, starts a new companion shell.

Saved shell layouts and explicit shell resets reuse the Session’s live owned Ghostel shell. The shell survives navigation, Agent Stop, and detach. If an exited shell buffer remains, restoration preserves its output. If the buffer is missing, restoration keeps the Agent usable without starting a replacement. Both cases show reset guidance. Press R with a shell preset to start a replacement.

Persistence

The manager persists its own metadata with persist.el. This is separate from the live Claude session registry.

When persistence is enabled, the manager remembers:

  • pinned state
  • manual ordering
  • saved layout snapshots
  • last selected buffer for layout restore
  • remote host, exact zmx target, Agent identification, and custom name
  • flat or grouped global view
  • cached project identity and branch metadata

After restart, remembered remote rows start disconnected. Their labels, pinning, ordering, selection, and saved layouts remain local metadata. Press c to reattach. A removed host stays visible in history, but Emacs requires current host configuration before remote access.

With persistence disabled, disconnected rows remain available during the current Emacs session. A later Emacs session does not restore them. Each computer has independent history. Another Emacs can discover the same remote Agent without access to this history.

Configuration

Manager-specific options:

VariableDescriptionDefault
claude-code-ide-manager-persist-statePersist manager metadata across Emacs restartst
claude-code-ide-manager-window-widthWidth of the left manager side window22
claude-code-ide-manager-repo-label-strategyVisible label strategy for repo-local rowsbranch-or-basename
claude-code-ide-manager-repo-include-nestedInclude nested git roots in repo-local scopenil
claude-code-ide-manager-default-targetDefault target for generic manager commandsglobal
claude-code-ide-manager-layout-presetLayout preset for new and explicitly reset layoutsmagit-left
claude-code-ide-manager-status-buffer-functionCustom content provider used by magit-left and magit-rightclaude-code-ide-manager-magit-status-buffer

Diff Viewing with Ediff

When claude-code-ide-use-ide-diff is enabled (default), Claude’s code suggestions are displayed using Emacs’ powerful ediff interface. This provides two key advantages:

  1. Visual diff comparison - See exactly what Claude wants to change with side-by-side or unified diff views
  2. Interactive editing - You can modify Claude’s suggestions before applying them

How to use ediff:

  1. When Claude suggests code changes, ediff opens automatically
  2. The ediff control buffer becomes active (a small window with ediff commands)
  3. Buffer A shows the current code, Buffer B shows Claude’s suggestion
  4. You can modify Buffer B to refine Claude’s proposed changes
  5. Press q in the ediff control buffer to quit
  6. When prompted, choose whether to accept the changes (y or n)
  7. If you accept (y), any changes from Buffer B will be sent back to Claude to be applied on the original file

This allows you to refine Claude’s suggestions before they’re applied, ensuring the final code meets your exact requirements.

Configuration

Configuration Variables

VariableDescriptionDefault
claude-code-ide-cli-pathSupported CLI to run (claude, codex, opencode, pi, or omp)"claude"
claude-code-ide-buffer-name-functionFunction for buffer namingclaude-code-ide--default-buffer-name
claude-code-ide-cli-debugEnable CLI debug mode (-d flag)nil
claude-code-ide-cli-extra-flagsAdditional CLI flags (e.g. “–model”)""
claude-code-ide-bypass-permissions-by-defaultLowercase transient launch actions bypass permissions when availablet
claude-code-ide-use-with-editorUse the current Emacs instance as $EDITOR for new sessionst
claude-code-ide-debugEnable debug loggingnil
claude-code-ide-terminal-initialization-delayInitialization delay for terminals0.1
claude-code-ide-log-with-contextInclude session context in log messagest
claude-code-ide-debug-bufferBuffer name for debug output"*claude-code-ide-debug*"
claude-code-ide-use-side-windowUse side window vs regular buffert
claude-code-ide-window-sideSide for Claude window'right
claude-code-ide-window-widthWidth for side windows (left/right)90
claude-code-ide-window-heightHeight for side windows (top/bottom)20
claude-code-ide-focus-on-openFocus Claude window when openedt
claude-code-ide-focus-claude-after-ediffFocus Claude window after opening edifft
claude-code-ide-show-claude-window-in-ediffShow Claude window during edifft
claude-code-ide-use-ide-diffUse IDE diff viewer instead of terminalt
claude-code-ide-switch-tab-on-ediffSwitch to Claude’s tab when opening edifft
claude-code-ide-system-promptCustom system prompt to appendnil
claude-code-ide-enable-mcp-serverEnable MCP tools servernil
claude-code-ide-mcp-server-portPort for MCP tools servernil (auto-select)
claude-code-ide-mcp-server-toolsAlist of exposed Emacs functionsnil
claude-code-ide-diagnostics-backendDiagnostics backend (auto/flycheck/flymake)'auto
claude-code-ide-prevent-reflow-glitchPrevent terminal reflow glitch (bug #1422)t

With claude-code-ide-use-with-editor enabled, editor commands such as C-g in Claude Code and Codex open their prompt buffer in the current Emacs instance. The package routes files matching claude-code-ide-prompt-buffer-patterns to the current window. The unbound command claude-code-ide-session-send-control-g sends C-g through Ghostel for users who want a dedicated keybinding.

For Oh My Pi Sessions, C-g and RET in terminal-input mode carry a per-Emacs nonce, and claude-code-ide-session-send-control-g carries it too. The Agent then opens its prompt buffer in the Emacs that pressed the key, even when another Emacs started the Session or attached it over a remote host. The prompt buffer opens in the window that received the key, and that window gets its previous buffer back when the prompt is closed. A key binding that selects another window first opens the prompt there and keeps the Agent terminal visible. This needs an Agent started after the upgrade. Copy mode and line mode keep their own keys, so a line-mode /todo edit still uses $EDITOR.

Session Customization

The package owns session buffer setup and idle monitoring. Your configuration can extend those behaviors through public hooks and reader functions:

  • claude-code-ide-session-mode and claude-code-ide-session-mode-map are package-owned
  • claude-code-ide-session-setup-hook runs in each session buffer for local UI or workflow setup
  • claude-code-ide-session-idle-delay controls the idle timeout before a session is considered idle; it defaults to 5 seconds
  • claude-code-ide-session-idle-default-enabled enables or disables idle monitoring by default
  • claude-code-ide-session-idle-enabled is the buffer-local switch for whether idle monitoring is active
  • claude-code-ide-session-idle-p is the buffer-local current idle state for the session buffer
  • claude-code-ide-session-idle-suppressed-predicate can suppress idle notifications for a session buffer
  • claude-code-ide-session-idle-hook runs with the session buffer when idle is detected
  • claude-code-ide-session-command-reader-function reads the command inserted by claude-code-ide-session-insert-command
  • claude-code-ide-session-file-reference-reader-function reads the file reference inserted by claude-code-ide-session-insert-file-reference
;; Personal session-buffer setup
(add-hook 'claude-code-ide-session-setup-hook
          (lambda ()
            (setq-local truncate-lines t)
            (visual-line-mode -1)))

;; Enable idle monitoring and add your own notification behavior
(setq claude-code-ide-session-idle-default-enabled t
      claude-code-ide-session-idle-delay 5)

(add-hook 'claude-code-ide-session-idle-hook
          (lambda (buffer)
            (when (buffer-live-p buffer)
              (message "Claude Code session idle: %s" (buffer-name buffer)))))

;; Optional: suppress idle notifications for selected session buffers
(setq claude-code-ide-session-idle-suppressed-predicate
      (lambda (buffer)
        (get-buffer-window buffer t)))

;; Optional: customize how inserted commands and file references are read
(setq claude-code-ide-session-command-reader-function
      (lambda (_buffer)
        (my/read-ai-command-string))
      claude-code-ide-session-file-reference-reader-function
      (lambda (_buffer)
        (my/read-file-reference-string nil t)))

Side Window Configuration

Claude Code buffers open in a side window by default. You can customize the placement:

;; Open Claude on the left side
(setq claude-code-ide-window-side 'left)

;; Open Claude at the bottom with custom height
(setq claude-code-ide-window-side 'bottom
      claude-code-ide-window-height 30)

;; Open Claude on the right with custom width
(setq claude-code-ide-window-side 'right
      claude-code-ide-window-width 100)

;; Don't automatically focus the Claude window
(setq claude-code-ide-focus-on-open nil)

;; Keep focus on ediff control window when opening diffs
(setq claude-code-ide-focus-claude-after-ediff nil)

;; Hide Claude window during ediff for more screen space
(setq claude-code-ide-show-claude-window-in-ediff nil)

;; Disable IDE diff viewer to show diffs in terminal instead
(setq claude-code-ide-use-ide-diff nil)

Or, if you’d prefer to use a regular window:

;; Use regular window instead of side window
(setq claude-code-ide-use-side-window nil)

Terminal Backend Configuration

Claude Code IDE uses Ghostel as its only terminal backend. There is no setting to choose a different terminal.

The ghostel backend supports session creation, core input dispatch, idle/working-state tracking, and the resize/reflow guard.

Install Ghostel and its matching native module before creating Agent or companion terminals. Other package features do not require Ghostel. This package never installs a native module automatically.

After the Ghostel-only upgrade, restart Emacs before using terminal commands. The package does not convert or reuse buffers from removed terminal integrations.

The ghostel backend is tested against Ghostel v0.50.0 (its removed pre-0.50.0 APIs are no longer referenced). To check the installed version, run M-x ghostel-debug and read the Module version: line, or evaluate (ghostel--module-version) in a Ghostel buffer. Ghostel checks the Elisp/native-module pairing against ghostel--minimum-module-version at load time and warns on mismatch. The bypass flags are --dangerously-skip-permissions for Claude Code, --dangerously-bypass-approvals-and-sandbox for Codex, --auto for OpenCode, none for Pi, and --auto-approve for Oh My Pi.

For new local omp and omp-dev processes in Ghostel, the launch frame selects the image protocol:

  • Graphical Emacs sets PI_FORCE_IMAGE_PROTOCOL=kitty.
  • Terminal Emacs sets PI_FORCE_IMAGE_PROTOCOL=off for readable image descriptions, including inside iTerm2 or tmux.

This policy does not change Pi, standalone omp, or the parent Emacs environment. Moving a buffer, redrawing, or reattaching zmx does not change a running process’s protocol. Start a fresh omp process to use the current frame’s policy.

Terminal Initialization Delay

Claude Code IDE includes a brief initialization delay when launching terminals to ensure proper layout rendering:

;; Adjust the terminal initialization delay (default is 0.1 seconds)
(setq claude-code-ide-terminal-initialization-delay 0.15)

;; Or disable it entirely (may cause visual glitches)
(setq claude-code-ide-terminal-initialization-delay 0)

This delay prevents display artifacts such as misaligned prompts and incorrect cursor positioning that can occur when terminal emulation is initializing. The default 100ms delay is imperceptible but ensures reliable terminal startup.

Terminal Keybindings

Claude Code IDE adds custom keybindings to the terminal for easier interaction:

KeybindingCommandDescription
S-<return>claude-code-ide-insert-newlineInsert a newline in the prompt
C-c C-cclaude-code-ide-session-send-interruptSend interrupt to the session
C-<escape>claude-code-ide-send-escapeSend escape key to cancel operations
s-v / H-vclaude-code-ide-session-paste-clipboardPaste text, local CLI images, or images through the verified remote OMP route

These keybindings are automatically set up for the Ghostel backend and only apply within Claude Code terminal buffers.

Local Claude Code, Codex, and OMP keep their direct C-v clipboard path. Remote OMP uses the existing terminal connection with matching Ghostel 0.54.0 native support, the verified OMP receiver, and lossless zmx input backpressure. Stock zmx 0.8.1 can discard large input when its queue fills. See the remote guide for the candidate requirements. Generic OSC 5522 support alone is not sufficient. Other remote CLIs keep their previous behavior and receive no new capability message. Valid text paste and keybinding precedence remain unchanged.

The remote attachment must own zmx input. If another client owns input, type normally in the intended Session before another image paste. An old unmarked attachment must reattach. After a timeout or disconnect, inspect the Agent before another paste because delivery can remain unconfirmed. The package never retries or sends a file-path substitute. See the remote guide for requirements and the acceptance record for measured results and open checks.

Terminal Reflow Glitch Prevention (Temporary)

Claude Code IDE includes a temporary workaround for a known Claude Code bug (#1422) where terminal reflows during window resizes can cause uncontrollable scrolling. This workaround is enabled by default for the Ghostel backend, but can be disabled if needed:

;; Disable the terminal reflow glitch prevention (not recommended until bug is fixed)
(setq claude-code-ide-prevent-reflow-glitch nil)

The workaround will be removed once the upstream bug is fixed.

Diagnostics Configuration

Claude Code IDE supports both Flycheck and Flymake for code diagnostics. By default, it will automatically detect which one is active:

;; Let Claude Code automatically detect the active diagnostics backend
(setq claude-code-ide-diagnostics-backend 'auto) ; default

;; Or force a specific backend
(setq claude-code-ide-diagnostics-backend 'flycheck)
(setq claude-code-ide-diagnostics-backend 'flymake)

Custom Buffer Naming

You can customize how Claude Code buffers are named:

(setq claude-code-ide-buffer-name-function
      (lambda (directory)
        (if directory
            (format "*Claude:%s*" (file-name-nondirectory (directory-file-name directory)))
          "*Claude:Global*")))

Custom CLI Flags

You can pass additional flags to the Claude Code CLI:

;; Use a specific model
(setq claude-code-ide-cli-extra-flags "--model opus")

;; Pass multiple flags
(setq claude-code-ide-cli-extra-flags "--model opus --no-cache")

;; Flags are added to all Claude Code sessions

Note: These flags are appended to the Claude command after any built-in flags like -d (debug) or -r (resume).

Custom System Prompt

You can append a custom system prompt to Claude’s default prompt, allowing you to customize Claude’s behavior for specific projects or contexts:

;; Set a custom system prompt
(setq claude-code-ide-system-prompt "You are an expert in Elisp and Emacs development.")

;; Or configure it per-project using dir-locals.el
;; In .dir-locals.el:
((nil . ((claude-code-ide-system-prompt . "Focus on functional programming patterns and avoid mutations."))))

;; Set via the transient menu: M-x claude-code-ide-menu → Configuration → Set system prompt

When set, this adds the --append-system-prompt flag to the Claude command. Set to nil to disable (default).

Debugging

Claude CLI Debug Mode

To enable debug mode for Claude Code CLI (passes the -d flag):

(setq claude-code-ide-cli-debug t)

Emacs Debug Logging

To enable debug logging within Emacs (logs WebSocket messages and JSON-RPC communication):

(setq claude-code-ide-debug t)

Then view debug logs with:

  • M-x claude-code-ide-show-debug - Show the debug buffer
  • M-x claude-code-ide-clear-debug - Clear the debug buffer

The debug buffer shows:

  • WebSocket connection events
  • All JSON-RPC messages (requests/responses)
  • Error messages and diagnostics
  • General debug information with session context

Multiple Claude Code Instances on One Project

Using git worktrees is the recommended way for running multiple Claude Code instances on different branches of the same project. This allows you to develop features or fix bugs in parallel:

# Create a new worktree for a feature branch
git worktree add ../myproject-worktree feature-branch
;; Start Claude Code in the main project
find-file /path/to/myproject
M-x claude-code-ide

;; Start another Claude Code instance in the worktree
find-file /path/to/myproject-worktree
M-x claude-code-ide

Each worktree is treated as a separate project by project.el, allowing you to have independent Claude Code sessions with their own buffers (e.g., *claude-code[myproject]* and *claude-code[myproject-worktree]*).

Emacs MCP Tools

Claude Code IDE includes built-in MCP tools that expose Emacs functionality to Claude, enabling powerful code navigation and analysis capabilities:

Built-in Tools

  • xref-find-references - Find all references to a symbol throughout the project
  • xref-find-apropos - Find symbols matching a pattern across the entire project
  • treesit-info - Get tree-sitter syntax tree information for deep code structure analysis
  • imenu-list-symbols - List all symbols (functions, classes, variables) in a file using imenu
  • project-info - Get information about the current project (directory, files, etc.)

Enabling MCP Tools

To enable these tools, add to your configuration:

;; Set up the built-in Emacs tools
(claude-code-ide-emacs-tools-setup)

Once enabled, Claude can use these tools to navigate your codebase. For example:

  • “Find the definition of function foo”
  • “Show me all places where this variable is used”
  • “What type of AST node is under the cursor?”
  • “Analyze the parse tree of this entire file”
  • “List all functions and variables in this file”
  • “How many files are in this project?”

Creating Custom MCP Tools

You can expose your own Emacs functions to Claude through the MCP tools system. This allows Claude to interact with specialized Emacs features, custom commands, or domain-specific functionality.

Tool Definition Format

Define tools using the claude-code-ide-make-tool function:

(claude-code-ide-make-tool
 :function #'function-name     ; The Emacs function to call
 :name "tool_name"             ; Name for Claude to use (snake_case recommended)
 :description "..."            ; Human-readable description
 :args '((:name "param1"       ; List of argument specifications
          :type string         ; Type: string, number, integer, boolean, etc.
          :description "..."   ; What this parameter does
          :optional t)))       ; Optional parameters marked with :optional t

Available argument types: string, number, integer, boolean, array, object, null

Context-Aware Tool Example

;; Define a context-aware function that operates in the session's project
(defun my-project-grep (pattern)
  "Search for PATTERN in the current session's project."
  (claude-code-ide-mcp-server-with-session-context nil
    ;; This executes with the session's project directory as default-directory
    (let* ((project-dir default-directory)
           (results (shell-command-to-string
                    (format "rg -n '%s' %s" pattern project-dir))))
      results)))

;; Define and register the tool (automatically added to claude-code-ide-mcp-server-tools)
(claude-code-ide-make-tool
 :function #'my-project-grep
 :name "my_project_grep"
 :description "Search for pattern in project files"
 :args '((:name "pattern"
          :type string
          :description "Pattern to search for")))

;; Enable Emacs tool MCP server
(claude-code-ide-emacs-tools-setup)

The claude-code-ide-mcp-server-with-session-context macro ensures your tool executes in the correct project context.

License

This project is licensed under the GNU General Public License v3.0 or later. See the LICENSE file for details.

Trademark Notice

Claude® is a registered trademark of Anthropic, PBC. Claude Code is an application developed by Anthropic, PBC.

Related Projects

About

Feature-rich Claude Code IDE integration for Emacs with multi-session management

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages