Function: claude-code-ide--create-terminal-session
claude-code-ide--create-terminal-session is a natively compiled
function defined in claude-code-ide.el.
Signature
(claude-code-ide--create-terminal-session BUFFER-NAME WORKING-DIR PORT CONTINUE RESUME SESSION-ID)
Documentation
Create a new terminal session for Claude Code.
BUFFER-NAME is the name for the terminal buffer. WORKING-DIR is the working directory. PORT is the MCP server port. CONTINUE is whether to continue the most recent conversation. RESUME is whether to resume a previous conversation. SESSION-ID is the unique identifier for this session.
Returns a cons cell of (buffer . process) on success. Signals an error if terminal fails to initialize.
Source Code
;; Defined in /nix/store/yjvbhwl7p6zrbw9xlnni7y4hra8sa3pl-emacs-packages-deps/share/emacs/site-lisp/claude-code-ide.el
(defun claude-code-ide--create-terminal-session (buffer-name working-dir port continue resume session-id)
"Create a new terminal session for Claude Code.
BUFFER-NAME is the name for the terminal buffer.
WORKING-DIR is the working directory.
PORT is the MCP server port.
CONTINUE is whether to continue the most recent conversation.
RESUME is whether to resume a previous conversation.
SESSION-ID is the unique identifier for this session.
Returns a cons cell of (buffer . process) on success.
Signals an error if terminal fails to initialize."
;; Ensure terminal backend is available before proceeding
(claude-code-ide--terminal-ensure-backend)
(let* ((claude-cmd (claude-code-ide--build-claude-command continue resume session-id))
(default-directory working-dir)
(env-vars (append (list (format "CLAUDE_CODE_SSE_PORT=%d" port)
"TERM_PROGRAM=emacs"
"FORCE_CODE_TERMINAL=true")
(when claude-code-ide-no-flicker
(list "CLAUDE_CODE_NO_FLICKER=1")))))
;; Log the command for debugging
(claude-code-ide-debug "Starting Claude with command: %s" claude-cmd)
(claude-code-ide-debug "Working directory: %s" working-dir)
(claude-code-ide-debug "Environment: CLAUDE_CODE_SSE_PORT=%d" port)
(claude-code-ide-debug "Session ID: %s" session-id)
(claude-code-ide-debug "Terminal backend: %s" claude-code-ide-terminal-backend)
;; A buffer created here is unowned until this function returns: the
;; session's buffer slot is still nil, so the caller's error path could
;; never reap it. Track it and destroy it if construction fails.
(let ((created-buffer nil))
(condition-case err
(cond
;; vterm backend
((eq claude-code-ide-terminal-backend 'vterm)
(let* ((vterm-buffer-name buffer-name)
;; Set vterm-shell to run Claude directly
(vterm-shell claude-cmd)
;; vterm uses vterm-environment for passing env vars
(vterm-environment (append env-vars vterm-environment)))
;; Create vterm buffer without switching to it
(let ((buffer (save-window-excursion
(vterm vterm-buffer-name))))
(setq created-buffer buffer)
;; Check if vterm successfully created a buffer
(unless buffer
(error "Failed to create vterm buffer. Please ensure vterm is properly installed and compiled"))
;; Configure vterm buffer for optimal performance
(with-current-buffer buffer
(claude-code-ide--configure-vterm-buffer))
;; Get the process that vterm created
(let ((process (get-buffer-process buffer)))
(unless process
(error "Failed to get vterm process. The vterm module may not be compiled correctly"))
;; Check if buffer is still alive
(unless (buffer-live-p buffer)
(error "Vterm buffer was killed during initialization"))
(cons buffer process)))))
;; eat backend
((eq claude-code-ide-terminal-backend 'eat)
(let* ((buffer (get-buffer-create buffer-name))
(eat-term-name "xterm-256color")
;; Parse command string into program and args
(cmd-parts (claude-code-ide--parse-command-string claude-cmd))
(program (car cmd-parts))
(args (cdr cmd-parts)))
(setq created-buffer buffer)
(with-current-buffer buffer
;; Set up eat mode
(unless (eq major-mode 'eat-mode)
(eat-mode))
;; Configure position preservation if enabled
(when claude-code-ide-eat-preserve-position
(setq-local eat--synchronize-scroll-function
#'claude-code-ide--terminal-position-keeper))
;; Prepend our env vars to the buffer-local process-environment
(setq-local process-environment
(append env-vars process-environment))
(eat-exec buffer buffer-name program nil args)
;; Get the process
(let ((process (get-buffer-process buffer)))
(unless process
(error "Failed to create eat process. Please ensure eat is properly installed"))
(cons buffer process)))))
;; ghostel backend
((eq claude-code-ide-terminal-backend 'ghostel)
(let* ((cmd-parts (claude-code-ide--parse-command-string claude-cmd))
(program (claude-code-ide--resolve-program (car cmd-parts)))
(args (cdr cmd-parts))
(buffer nil))
(when-let* ((stale-buffer (get-buffer buffer-name)))
;; A buffer with a live session backpointer is a running sibling
;; instance, not a stale leftover — never kill it.
(when (claude-code-ide--buffer-session stale-buffer)
(error "Buffer %s already belongs to a running Claude Code instance"
buffer-name))
(kill-buffer stale-buffer))
(setq buffer (get-buffer-create buffer-name))
(setq created-buffer buffer)
(unless (buffer-live-p buffer)
(error "Failed to create ghostel buffer. Please ensure ghostel is properly installed"))
(with-current-buffer buffer
(setq default-directory working-dir)
(claude-code-ide--disable-ghostel-title-tracking)
;; Let `claude-code-ide--cleanup-session' be the single place that
;; kills the buffer. Otherwise ghostel's sentinel kills the buffer
;; first, firing `kill-buffer-hook' → cleanup-session, and then our
;; wrapping sentinel runs cleanup-session a second time.
(setq-local ghostel-kill-buffer-on-exit nil)
(let* ((process-environment (append env-vars process-environment))
(process (ghostel-exec buffer program args)))
;; `ghostel-exec' switches the buffer into `ghostel-mode', which
;; resets buffer-local variables.
(claude-code-ide--disable-ghostel-title-tracking)
(setq-local ghostel-kill-buffer-on-exit nil)
;; `ghostel-mode-hook' has run by now, so if `evil-ghostel-mode'
;; is enabled it has already seeded `evil-ghostel--escape-mode'
;; from the global default; override it for this buffer only.
(claude-code-ide--apply-ghostel-evil-escape)
(unless process
(error "Failed to create ghostel process. Please ensure ghostel is properly installed"))
;; Chain ghostel's own sentinel so its buffer-local timers,
;; focus-change hook, and `ghostel-exit-functions' still run
;; when `claude-code-ide--start-session' installs its own
;; sentinel on top. Without this, ghostel teardown is skipped.
(process-put process 'claude-code-ide--ghostel-sentinel
(process-sentinel process))
(cons buffer process)))))
(t
(error "Unknown terminal backend: %s" claude-code-ide-terminal-backend)))
((error quit)
(when (and created-buffer (buffer-live-p created-buffer))
(when-let* ((process (get-buffer-process created-buffer)))
(ignore-errors (delete-process process)))
(let ((kill-buffer-hook nil)
(kill-buffer-query-functions nil))
(ignore-errors (kill-buffer created-buffer))))
(signal (car err) (cdr err)))))))