Skip to content

emskin/emskin

Repository files navigation

emskin — Emacs dressed in a Wayland compositor

emskin

Dress Emacs in a Wayland skin.

中文文档

emskin wraps Emacs inside a nested Wayland compositor so that any program — browsers, terminals, video players, etc. — can be embedded into Emacs windows as if they were native buffers.

demo

Features

  • Embed any program — Wayland and X11 apps alike, including FPS games / browser Pointer Lock (pointer constraints + raw mouse delta)
  • Window mirroring — display the same app in multiple Emacs windows
  • Input method support — shares the host IM with precise cursor positioning
  • Clipboard sync — bidirectional between host and embedded apps
  • Launcher support — rofi / wofi / zofi work out of the box
  • Automatic focus management — new windows auto-focus; focus falls back on close
  • Built-in screen recording & screenshots — toggle MP4 capture or snap a PNG, no external tools

Compatibility

Desktop Wayland X11
GNOME
KDE
Sway
COSMIC

pgtk Emacs (--with-pgtk) is recommended. GTK3 X11 Emacs also works via XWayland.

Install

Requires Rust ≥ 1.89 (rust-toolchain.toml pins 1.92.0). If your distro ships an older rustc, install via rustup:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Arch Linux (AUR)

yay -S emskin-bin

From source

# Dependencies (Arch Linux)
sudo pacman -S wayland libxkbcommon mesa

# Option 1: cargo install
cargo install --git https://github.com/emskin/emskin.git

# Option 2: build from source
git clone https://github.com/emskin/emskin.git
cd emskin && cargo build --release

Quick Start

# Zero-config: auto-loads built-in elisp, no Emacs setup needed
emskin --standalone

Usage

Open embedded apps

Inside Emacs running in emskin:

M-x emskin-open-native-app RET firefox
M-x emskin-open-native-app RET foot

The app embeds into the current Emacs window and receives keyboard focus.

Keyboard interaction

When an embedded app has focus, keystrokes go directly to it. Emacs prefix keys (C-x, C-c, M-x) are intercepted and sent back to Emacs; focus restores automatically after the key sequence completes.

  • C-x o — switch Emacs windows (embedded apps follow buffer switches)
  • C-x 1 / C-x 2 / C-x 3 — normal window operations; embedded apps resize automatically

Effects

emskin ships five live-toggleable effects, plus a non-toggleable startup splash.

Effect Variable Toggle What it does
measure emskin-measure M-x emskin-toggle-measure Figma-style pixel inspector: crosshair, coordinates, rulers
skeleton emskin-skeleton M-x emskin-toggle-skeleton Frame-layout wireframes (debug overlay, clickable labels)
cursor trail emskin-cursor-trail M-x emskin-toggle-cursor-trail Elastic spring trail behind the mouse pointer
jelly cursor emskin-jelly-cursor M-x emskin-toggle-jelly-cursor Jelly-style animation on Emacs's text caret (pgtk-only color sync)
recorder emskin-record M-x emskin-toggle-record MP4 screen capture with on-screen indicator (red dot + MM:SS timer)

All default to off. Configure in ~/.emacs.d/init.el:

(setq emskin-cursor-trail t
      emskin-jelly-cursor t)

Values sync automatically on IPC connect, so setq works unchanged. After changing a variable mid-session, run M-x emskin-apply-config to push it immediately.

Recording & screenshots

Two independent commands; either one works while the other is active:

Command Output Customize
M-x emskin-toggle-record ~/Videos/emskin/emskin-YYYYMMDD-HHMMSS.mp4 emskin-record-dir, emskin-record-fps (default 30)
M-x emskin-screenshot ~/Videos/emskin/emskin-YYYYMMDD-HHMMSS.png emskin-screenshot-dir (defaults to emskin-record-dir)

The recorder is also exposed as a regular toggle (above), so it picks up the same setq + emskin-apply-config lifecycle as the other effects. Bind to your key of choice — for example:

(global-set-key (kbd "C-c C-r") #'emskin-toggle-record)

Workspaces

Each Emacs frame maps to a workspace:

  • C-x 5 2 — create workspace
  • C-x 5 o — switch workspace
  • C-x 5 0 — close current workspace

A top-anchored workspace bar (emskin-bar) appears automatically once a second workspace exists and disappears when you drop back to one. Control it via --bar=<mode> on the emskin CLI:

  • --bar=auto (default) — find emskin-bar next to the emskin binary, falling back to PATH
  • --bar=none — don't launch a bar (e.g. you run waybar yourself)
  • --bar=/path/to/binary — launch a custom bar instead (anything speaking zwlr-layer-shell-v1 + ext-workspace-v1, such as waybar with the right modules)

The bar is a standalone Wayland client — it never talks to emskin's private IPC, only standard Wayland protocols — and its lifecycle follows the compositor: it starts when emskin starts and exits when the Wayland socket closes.

Launchers

Bind a key to launch rofi / zofi:

;; zofi — a launcher designed for emskin, see https://github.com/emskin/zskins
(defun my/emskin-zofi ()
  (interactive)
  (start-process "zofi" nil "setsid" "zofi"))
(global-set-key (kbd "C-c z") #'my/emskin-zofi)

;; rofi
(defun my/emskin-rofi ()
  (interactive)
  (start-process "rofi" nil
                 "setsid" "rofi"
                 "-show" "combi"
                 "-combi-modi" "drun,ssh"
                 "-terminal" "foot"
                 "-show-icons" "-i"))
(global-set-key (kbd "C-c r") #'my/emskin-rofi)

Emacs Configuration

Without --standalone, load the elisp manually:

(add-to-list 'load-path "/path/to/emskin/elisp")
(require 'emskin)

CLI Options

emskin [OPTIONS]

  --standalone            Standalone mode: auto-load built-in elisp
  --no-spawn              Don't start Emacs; wait for external connection
  --command <CMD>         Program to launch (default: "emacs")
  --arg <ARG>             Arguments for --command (repeatable)
  --bar <MODE>            Workspace bar: "auto" (default), "none", or a path
  --xkb-layout <LAYOUT>   Keyboard layout (e.g. "us", "cn")

FAQ

Crash on startup in a VM

emskin supports software rendering (llvmpipe), but older Mesa (< 21.0) may crash at high resolutions:

# Check renderer
glxinfo | grep "OpenGL renderer"

# If llvmpipe at high resolution, reduce it
xrandr --output Virtual-1 --mode 1920x1080

Make sure mesa is installed: sudo pacman -S mesa mesa-utils (Arch) or sudo apt install mesa-utils (Debian/Ubuntu).

Acknowledgements

  • Smithay — the Rust Wayland compositor library emskin is built on.
  • holo-layer — the jelly text-cursor effect and the elisp caret-tracking pattern (post-command-hook + pos-visible-in-window-p) are adapted from holo-layer. Thanks to @manateelazycat.

License

GPL-3.0