Eine Ebene über Windows liegt in Emacs der Frame — das, was das Betriebssystem als „Fenster" begreift und im macOS-Dock, in der Windows-Taskleiste oder in der GNOME-Übersicht als eigenes App-Element zeigt. Auf einer ganz anderen Achse stehen Tabs: zwei verschiedene Tab-Konzepte (tab-bar-mode für Workspaces, tab-line-mode für Buffer pro Window) leben seit Emacs 27 parallel im Editor. Beide werden häufig verwechselt, beide sind nützlich — wer den Unterschied zwischen Frame, Workspace-Tab und Buffer-Tab kennt, ordnet seine Arbeit sauber zwischen den Konzepten ein und nutzt jedes für genau das, was es kann.
Frames: OS-Fenster derselben Emacs-Instanz
Ein Frame ist in Emacs das Konzept, das andere Editoren „Window" nennen würden — und das ist die Quelle der dauerhaften Sprachverwirrung. Was bei VS Code oder Sublime das App-Fenster ist, heißt in Emacs Frame; was Emacs „Window" nennt, ist nur ein rechteckiger Bereich innerhalb eines Frames. Wer den Begriffs-Tausch einmal verinnerlicht hat, liest jede Emacs-Doku ohne Stolpern.
Konkret ist ein Frame das, was dein Window-Manager sieht und verwaltet: ein App-Fenster mit Titelleiste, Schließen-Button, eigenem Eintrag in macOS-Dock, Windows-Taskleiste oder GNOME-Aktivitätenübersicht. Mehrere Frames zu öffnen bedeutet nicht, mehrere Emacs-Instanzen zu starten — alle Frames gehören demselben Emacs-Prozess, teilen sich denselben Lisp-Heap, dieselbe Konfiguration, dieselbe Buffer-Liste, dieselben Kill-Ring- und Registern-Inhalte. Du schließt eine Datei in Frame A, sie ist auch aus Frame B verschwunden, weil sie ja nur einmal als Buffer existiert.
Diese Architektur hat zwei sehr praktische Konsequenzen:
- Frames sind billig. Einen neuen Frame zu öffnen kostet kaum Ressourcen — kein Lisp-Reload, kein erneutes Auswerten der
init.el, keine zweite Kopie der Pakete. Wer ein zweites OS-Fenster braucht, sollte einen Frame öffnen, nicht eine zweite Emacs-Instanz starten. - Frames sind synchron. Ein Buffer-Wechsel in Frame A taucht sofort in der Buffer-Liste von Frame B auf; ein per
kill-ring-save(M-w) gemerkter Text kann in jedem anderen Frame eingefügt werden. Frames sind unterschiedliche Sichten auf denselben Editor-State.
Typische Use-Cases für mehrere Frames:
- Ein Frame pro Monitor. Auf einem Multi-Display-Setup öffnet jeder Frame auf seinem eigenen Bildschirm, jeder mit eigenem Window-Layout. Alle Buffer bleiben aber synchron sichtbar.
- Ein Frame pro Projekt. Während Frame A das Backend bearbeitet, hält Frame B das Frontend-Repository — visuell getrennt, technisch derselbe Emacs.
- Schnelle Notiz. Ein winziger Frame mit dem
*scratch*-Buffer oder einer Org-Datei, der dauerhaft am Bildschirmrand schwebt. - Präsentation. Ein Frame mit großer Schrift und reduzierter Modeline für Vorträge, parallel ein normaler Arbeits-Frame.
Das C-x 5-Prefix: Frame-Operationen
Emacs strukturiert seine Tastenbelegung systematisch nach Konzept-Ebenen. Das C-x 4-Prefix öffnet Aktionen jeweils in einem anderen Window (siehe Fenster und Splits). Das C-x 5-Prefix ist die exakt analoge Familie eine Ebene höher: alles, was darunter liegt, betrifft Frames. Die Mnemonik ist konsistent — 4 = Window, 5 = Frame, und unter beiden Prefixes finden sich dieselben Verben in derselben Reihenfolge.
| Tastenkombination | Befehl | Wirkung |
|---|---|---|
| C-x 5 2 | make-frame-command | neuen Frame öffnen (dupliziert das aktuelle Layout in einem neuen OS-Fenster) |
| C-x 5 0 | delete-frame | aktuellen Frame schließen — Fehler, wenn nur noch ein Frame existiert |
| C-x 5 1 | delete-other-frames | alle anderen Frames schließen, nur der aktuelle bleibt |
| C-x 5 o | other-frame | zwischen Frames wechseln (mehrfaches Drücken zykliert) |
| C-x 5 b | switch-to-buffer-other-frame | Buffer in einem neuen Frame öffnen |
| C-x 5 f | find-file-other-frame | Datei in einem neuen Frame öffnen |
| C-x 5 d | dired-other-frame | Dired-Verzeichnis-Browser in neuem Frame öffnen |
| C-x 5 u | undelete-frame | zuletzt geschlossenen Frame wiederherstellen (undelete-frame-mode) |
Die Symmetrie zum C-x 4-Prefix ist beabsichtigt: Wer C-x 4 f kennt (Datei im anderen Window), tippt für „Datei in neuem OS-Fenster" reflexiv C-x 5 f — und es klappt. Genau diese strenge Konsistenz macht Emacs-Bindings beim Lernen unbequem und im Alltag mühelos.
Ein häufiger plattform-spezifischer Tipp: C-x 5 1 (delete-other-frames) bezieht sich auf das aktuelle Terminal/Display. Frames auf einem zweiten X-Display oder auf einem Daemon-Terminal-Anschluss bleiben erhalten — gewollt, aber überraschend, wenn man das erste Mal mit zwei Displays arbeitet.
Frames per Konfiguration anpassen
Wie ein Frame beim Öffnen aussieht — Größe, Position, Schriftart, Hintergrundfarbe, Fenster-Dekoration — wird über Frame-Parameter gesteuert. Diese Parameter leben in zwei Listen, die Emacs beim Start liest und beim Erzeugen jedes neuen Frames konsultiert:
initial-frame-alist— gilt nur für den allerersten Frame, der beim Start erscheint. Praktisch für „Start-Frame im Vollbild, alle weiteren normal".default-frame-alist— gilt für jeden weiteren Frame, der danach geöffnet wird (etwa durch C-x 5 2 oderemacsclient -c). Das ist der Ort für deine generellen Defaults.
Wo dieser Code hingehört
Beide Variablen werden in deiner zentralen Konfigurations-Datei (~/.emacs.d/init.el oder ~/.config/emacs/init.el) gesetzt. Was diese Datei tut, wann sie gelesen wird und wie man sie sinnvoll strukturiert, erklärt der Artikel Konfiguration mit init.el und early-init.el im Detail.
;; Standard-Frame: 120 Zeichen breit, 40 Zeilen hoch, hübsche Schrift
(setq default-frame-alist
'((width . 120)
(height . 40)
(font . "Iosevka 13")))
;; Erster Frame beim Start zusätzlich maximiert
(setq initial-frame-alist
'((fullscreen . maximized)))Die wichtigsten Parameter im Überblick:
| Parameter | Wert | Wirkung |
|---|---|---|
width | Integer (Zeichen-Spalten) | Frame-Breite in Zeichen, nicht in Pixeln |
height | Integer (Zeichen-Zeilen) | Frame-Höhe in Zeichen |
font | String („Family Größe") | Standard-Schrift des Frames |
fullscreen | nil / fullboth / maximized / fullheight / fullwidth | Fenster-Modus |
undecorated | t / nil | Titelleiste und OS-Rahmen ein/ausblenden |
alpha | Integer 0–100 oder (focus unfocus) | Fenster-Transparenz |
background-color / foreground-color | Farb-String | Default-Farben (besser über Themes) |
left / top | Integer (Pixel) | Position auf dem Bildschirm |
Wichtig: Parameter werden beim Erzeugen des Frames ausgewertet — eine Änderung an default-frame-alist wirkt erst beim nächsten neuen Frame, nicht rückwirkend auf bereits offene. Wer das aktuelle Fenster sofort anpassen will, nutzt set-frame-parameter mit explizitem Frame-Argument oder schreibt für interaktive Tests M-x set-frame-font.
tab-bar-mode: Workspace-Tabs (seit Emacs 27)
Seit Emacs 27 bringt der Editor einen vollwertigen Workspace-Switcher mit: die Tab-Bar. Sie erscheint als horizontale Leiste am oberen Rand jedes Frames und enthält benannte Tabs, zwischen denen mit einem Klick oder einer Tastenkombination gewechselt wird. Der Clou ist das, was sich hinter einem Tab verbirgt: jeder Tab speichert eine eigene Window-Konfiguration — also das komplette Splits-Layout samt Buffer-Zuweisung pro Window.
Anders gesagt: Ein Tab ist nicht ein Buffer, sondern ein Layout. Wechselst du den Tab, ändert sich das gesamte Fenster-Arrangement im Frame. Genau das macht tab-bar-mode zum eingebauten Ersatz für externe Pakete wie eyebrowse oder perspective, die jahrelang dieselbe Funktion brachten.
Aktivieren und Default-Setup
;; Tab-Bar global aktivieren
(tab-bar-mode 1)
;; Erst ab 2 Tabs anzeigen (Wert 1 = "nur wenn mehr als ein Tab")
(setq tab-bar-show 1)
;; Neue Tabs starten mit *scratch* statt mit dem aktuellen Buffer
(setq tab-bar-new-tab-choice "*scratch*")
;; Tabs durchnummerieren (für M-1, M-2 ... Quick-Switch)
(setq tab-bar-tab-hints t)Die C-x t-Befehle
| Tastenkombination | Befehl | Wirkung |
|---|---|---|
| C-x t 2 | tab-new | neuen Tab anlegen |
| C-x t 0 | tab-close | aktuellen Tab schließen |
| C-x t 1 | tab-close-other | alle anderen Tabs schließen |
| C-x t o | tab-next | nächsten Tab aktivieren |
| C-x t RET | tab-bar-select-tab-by-name | Tab nach Namen auswählen (mit Completion) |
| C-x t r | tab-rename | aktuellen Tab umbenennen |
| C-x t m | tab-move | Tab in der Leiste verschieben |
| C-x t b | switch-to-buffer-other-tab | Buffer in einem neuen Tab öffnen |
| C-x t f | find-file-other-tab | Datei in einem neuen Tab öffnen |
| C-x t d | dired-other-tab | Dired in neuem Tab |
| C-TAB | tab-next | nächster Tab (browser-üblicher Shortcut) |
| C-S-TAB | tab-previous | vorheriger Tab |
History und Undo
Ein oft übersehener Schalter: tab-bar-history-mode. Aktiviert, merkt sich Emacs pro Tab die letzten Window-Konfigurationen, sodass C-x t L und C-x t R wie ein Undo/Redo für Layout-Änderungen funktionieren. Praktisch, nachdem man versehentlich ein Split-Layout zerschossen hat.
tab-line-mode: Buffer-Tabs pro Window
Verwirrend ähnlich benannt, aber konzeptionell etwas anderes: tab-line-mode zeigt eine Tab-Leiste pro Window, und jeder Tab darin steht für einen Buffer, nicht für ein Layout. Klick auf einen Tab schaltet den Buffer in diesem Window um — genau das Verhalten, das aus VS Code, Sublime oder Browsern vertraut ist.
Standardmäßig listet tab-line-mode alle bisher in diesem Window angezeigten Buffer. Über die Variable tab-line-tabs-function lässt sich die Gruppierung wechseln:
tab-line-tabs-window-buffers— alle bisher im Window besuchten Buffer (Default)tab-line-tabs-mode-buffers— alle Buffer mit demselben Major-Mode wie der aktuelletab-line-tabs-buffer-groups— Buffer nach beliebigen Gruppen, plus Gruppen-Wähler-Tab
Weil eine Tab-Leiste pro Window in einem stark gesplitteten Layout schnell sehr unruhig wirkt, aktivieren viele User tab-line-mode nicht global, sondern selektiv über Hooks — etwa nur in Programm-Modi:
;; tab-line nur in Code-Buffern anzeigen
(add-hook 'prog-mode-hook #'tab-line-mode)
;; nur Buffer mit demselben Major-Mode in der Tab-Liste zeigen
(setq tab-line-tabs-function #'tab-line-tabs-mode-buffers)Wer die Leiste global will, ruft stattdessen (global-tab-line-mode 1) auf. Bedienung erfolgt primär per Maus oder über die Tasten C-x <left> / C-x <right>, die ohnehin previous-buffer / next-buffer im aktuellen Window aufrufen.
tab-bar vs. tab-line — wann was?
Die Namen unterscheiden sich um einen Buchstaben, die Konzepte um eine ganze Achse. Eine kurze Gegenüberstellung räumt die Verwechslung dauerhaft aus dem Weg.
| Aspekt | tab-bar-mode | tab-line-mode |
|---|---|---|
| Sichtbar pro | Frame (eine Leiste oben) | Window (eine Leiste je Window) |
| Ein Tab repräsentiert | Window-Konfiguration (Layout) | Buffer |
| Wechsel ändert | das ganze Layout im Frame | nur den Buffer in genau diesem Window |
| Browser-Analogie | Window-Sets / mehrere Browser-Fenster | Tabs innerhalb eines Browser-Fensters |
| Aktivierung | (tab-bar-mode 1) | (global-tab-line-mode 1) oder per Hook |
| Tastatur-Prefix | C-x t | meist Maus + C-x <left/right> |
| Typische Nutzung | Workspaces pro Aufgabe | „Klick-Workflow" wie in modernen GUI-Editoren |
Eine grobe Empfehlung nach Hintergrund:
- Aus VS Code, Sublime, JetBrains kommst du? Dann fühlt sich
tab-line-modedirekt nach Hause an — Buffer als Tabs, anklickbar, sichtbar. - Aus einem Tiling-WM (i3, Hyprland, AwesomeWM) kommst du? Dann ist
tab-bar-modedie natürliche Wahl — benannte Workspaces mit voller Layout-Kontrolle. - Beides geht auch zusammen. Die beiden Modi sind orthogonal: Du kannst einen Tab in der Tab-Bar haben, in dem mehrere gesplittete Windows jeweils ihre eigene Tab-Line zeigen. Das mag visuell überladen werden, technisch ist es vorgesehen.
tab-bar mit project.el integrieren
Eine der lohnendsten Kombinationen ist tab-bar-mode zusammen mit dem eingebauten project.el: pro Projekt ein eigener Tab, der das passende Layout (Code-Fenster, Test-Buffer, Compilation-Output) sauber kapselt. Die Bausteine dafür liefert Emacs out-of-the-box:
(tab-bar-mode 1)
(tab-bar-history-mode 1)
;; Beim Projekt-Wechsel automatisch in einen Projekt-Tab
(setq project-switch-commands
'((project-find-file "Datei suchen" ?f)
(project-dired "Dired" ?d)
(project-eshell "Eshell" ?e)))
;; Neuer Tab startet leer und wartet auf den ersten Befehl
(setq tab-bar-new-tab-choice "*scratch*")Mit etwas Klebe-Lisp lässt sich daraus eine project-switch-project-Variante bauen, die jedes neue Projekt in einen eigenen, nach Projekt benannten Tab öffnet — viele Konfigurations-Frameworks (Doom, Crafted, Prelude) liefern dieses Muster fertig mit. Mehr dazu im Detail-Artikel zu project.el.
Frames vs. Tabs vs. Windows — die Entscheidungsmatrix
Drei Konzepte, drei Achsen — eine kompakte Übersicht für den Alltag:
| Konzept | Tastatur-Einstieg | Wann sinnvoll |
|---|---|---|
| Frame | C-x 5 2 | mehrere Monitore, separate OS-Fenster, Präsentations-Setup, schwebende Notiz |
Tab (tab-bar) | C-x t 2 | thematische Workspaces im selben Frame (Backend / Frontend / Docs) |
Tab (tab-line) | Maus / C-x <right> | sichtbare Buffer-Liste pro Window für Klick-orientierte Workflows |
| Window (Split) | C-x 2 / C-x 3 | gleichzeitige Sicht auf 2–4 Buffer, etwa Code + Test + Compilation |
Die richtige Wahl hängt am Use-Case, nicht am Geschmack:
- Was du parallel sehen willst → Splits (Windows).
- Was du nacheinander zwischen kompletten Layouts wechseln willst →
tab-bar. - Was du im selben Bereich nur schnell tauschen willst, ohne das Layout zu ändern →
tab-lineoder einfach C-x b. - Was räumlich getrennt sein soll (anderer Monitor, anderer Desktop) → Frames.
Wer alle vier Achsen souverän kombiniert, hat in Emacs ein Workspace-System, das den meisten externen Tools deutlich überlegen ist — und das ohne ein einziges Drittpaket.
Interessantes
Frame ist nicht teurer als Window
Einen Frame zu öffnen ist eine billige Operation — derselbe Emacs-Prozess, derselbe Lisp-Heap, dieselbe Buffer-Liste. Eine zweite Emacs-Instanz dagegen ist teuer: eigener Heap, doppelte Konfigurations-Auswertung, keine Buffer-Synchronisation. Wer „noch ein OS-Fenster" will, öffnet einen Frame, nicht eine weitere App.
`tab-bar-mode` speichert die Window-Konfiguration pro Tab
Ein Tab in der Tab-Bar ist ein gespeichertes Layout — vollständig mit Splits, Buffer-Zuweisung und Point-Position. Wechselst du den Tab, ändert sich das gesamte Window-Arrangement im Frame. Perfekt für „pro Aufgabe ein Layout"-Workflows, die früher externe Pakete wie eyebrowse oder perspective brauchten.
`tab-bar` und `tab-line` sind unterschiedliche Dinge mit ähnlichem Namen
Beide bringen Tabs, aber auf unterschiedlichen Ebenen: tab-bar ist eine Leiste pro Frame, jeder Tab ist ein Layout. tab-line ist eine Leiste pro Window, jeder Tab ist ein Buffer. Verwechslung ist extrem häufig — der Trick ist, sich „Bar = oberhalb des ganzen Frames, Line = oberhalb eines einzelnen Windows" zu merken.
Frame-Parameter wirken nur beim nächsten neuen Frame
default-frame-alist wird beim Erzeugen eines Frames konsultiert. Eine spätere Änderung an dieser Liste ändert nichts an bereits offenen Frames — sie greift erst beim nächsten C-x 5 2. Für sofortige Wirkung auf den aktuellen Frame nutzt man set-frame-parameter oder set-frame-font.
`tab-bar-mode` macht externe Workspace-Pakete weitgehend überflüssig
Pakete wie eyebrowse, perspective oder persp-mode haben jahrelang das geliefert, was tab-bar-mode heute eingebaut mitbringt. Für neue Konfigurationen ist die eingebaute Variante meist die richtige Wahl — weniger Abhängigkeiten, gepflegt vom Emacs-Core-Team, persistierbar über das Desktop-Paket.
`delete-other-frames` betrifft nur das aktuelle Terminal
C-x 5 1 schließt alle anderen Frames auf demselben Terminal/Display — Frames auf einem zweiten X-Display oder an einem zweiten Daemon-Client überleben das. Im Daemon-Modus mit mehreren emacsclient-Verbindungen ist das gewollt, beim ersten Kontakt aber überraschend.
`tab-line-mode` lässt sich beliebig gruppieren
Über tab-line-tabs-function bestimmst du, welche Buffer als Tabs im Window erscheinen — alle besuchten, alle mit gleichem Major-Mode oder eine eigene Gruppierung per Lisp-Funktion. Wer pro Projekt oder pro Datei-Endung gruppieren will, schreibt eine eigene Funktion in zwei Zeilen.
Im Daemon-Modus überleben Frames das Schließen des letzten Frames nicht alleine
Schließt du den letzten Frame eines Daemon-Emacs, läuft der Daemon weiter — aber unsichtbar im Hintergrund. Neue Frames öffnest du dann mit emacsclient -c (oder emacsclient -c -a "", um den Daemon bei Bedarf automatisch zu starten). Details dazu im Artikel Daemon und emacsclient.
Weiterführende Ressourcen
Externe Quellen
- GNU Emacs Manual — Frames — offizielle Einführung in das Frame-Konzept und seine Befehle.
- GNU Emacs Manual — Frame Commands — vollständige Liste der C-x 5-Bindings inklusive
undelete-frame. - GNU Emacs Manual — Frame Parameters —
default-frame-alist,initial-frame-alistund alle wichtigen Parameter. - GNU Emacs Manual — Tab Bars — komplette Referenz zu
tab-bar-mode, Befehlen und Variablen. - GNU Emacs Manual — Tab Line — Referenz zu
tab-line-modeund seinen Gruppierungs-Funktionen.