An editor with the soul of EmacsUn editor con el alma de Emacs

The editor you reshape while it runs. El editor que transformas mientras corre.

GEMAX keeps what makes Emacs great — a Lisp you rewrite live, named commands, modes, keymaps, magit, org — and rebuilds everything else from scratch in Rust: GPU rendering, a real terminal, a core that never blocks, and an MCP server so AI agents can drive it the way you do.

GEMAX conserva lo que hace grande a Emacs —un Lisp que reescribes en vivo, comandos con nombre, modos, keymaps, magit, org— y reconstruye todo lo demás desde cero en Rust: render por GPU, un terminal de verdad, un núcleo que nunca se bloquea y un servidor MCP para que los agentes de IA lo manejen igual que tú.

$ tar xzf gemax-0.1.0-linux-x86_64.tar.gz && cd gemax-0.1.0-linux-x86_64 && ./install.sh

Linux · x86_64 · X11 & Wayland · Rust + Janet · pre-v0.1 Why another editor?¿Por qué otro editor?

An illustration, drawn in HTML — real screenshots are further down. Una ilustración hecha en HTML; las capturas reales están más abajo.

1,1581158 tests across 24 cratespruebas en 24 crates
126 Janet packages — magit, dired, org…paquetes Janet: magit, dired, org…
137 operations in one language-neutral APIoperaciones en una API independiente del lenguaje
1 place in the whole editor that waitssolo lugar en todo el editor que espera

PhilosophyFilosofía

A tiny core.
Everything else is a package.
Un núcleo mínimo.
Todo lo demás es un paquete.

Emacs proved that an editor should be a programmable environment, not a fixed program. But its architecture — one thread, a display engine welded to the interpreter — can't host a GPU renderer, a modern terminal or real asynchronous work. GEMAX starts again from the idea, not from the code.

Emacs demostró que un editor debe ser un entorno programable, no un programa cerrado. Pero su arquitectura —un solo hilo, el motor de pantalla soldado al intérprete— no puede alojar un render por GPU, un terminal moderno ni trabajo asíncrono de verdad. GEMAX vuelve a empezar desde la idea, no desde el código.

01

MicrokernelMicrokernel

The core edits text and draws windows. Magit, dired, org-mode, the LSP interface, the debugger panels — all of it is Janet you can read, copy and replace without recompiling anything.

El núcleo edita texto y dibuja ventanas. Magit, dired, org-mode, la interfaz del LSP, los paneles del depurador: todo es Janet que puedes leer, copiar y reemplazar sin recompilar nada.

packages/

├─ magit.janet status · stage · rebase · forge

├─ dired.janet file manager

├─ org-mode.janet agenda · capture · babel

├─ lsp.janet eglot-style client UI

├─ dap.janet debugger panels

└─ … 121 more

02

Nothing blocksNada se bloquea

There is exactly one wait in the whole editor: the top of the event loop. Search, prompts, the debugger and language servers are state, not loops — so a slow server never freezes your typing.

En todo el editor hay una sola espera: el tope del bucle de eventos. La búsqueda, los prompts, el depurador y los servidores de lenguaje son estado, no bucles: un servidor lento nunca congela lo que escribes.

loop {
    render(&frame);      // always runs
    let ev = read_event(); // the only wait
    dispatch(ev);        // routes by state
}
03

Rust provides, Lisp decidesRust ofrece, Lisp decide

Rust supplies the fast primitives: ropes, faces, events, a GPU glyph atlas. Janet decides what you see. If changing how something looks needs a recompile, it's a bug in the design.

Rust pone las primitivas rápidas: ropes, faces, eventos, un atlas de glifos en la GPU. Janet decide qué ves. Si cambiar cómo se ve algo exige recompilar, es un error de diseño.

# the modeline is data, not code
(set-modeline
  {:left   [:modified :buffer-name]
   :center [:git-branch]
   :right  [:diagnostics :position :mode]})
04

One API, every languageUna API, todos los lenguajes

Every operation has a name and JSON values. Janet calls it, a WebAssembly component written in any language calls it, an AI agent over MCP calls it — the same 137 operations, with the same answers.

Cada operación tiene nombre y valores JSON. La llama Janet, la llama un componente WebAssembly escrito en cualquier lenguaje, la llama un agente de IA por MCP: las mismas 137 operaciones, con las mismas respuestas.

; Janet
(split-window :below)
// Rust, compiled to a WASM component
api::split_window(SplitWindowSide::Below)?;
# any MCP client
eval '(split-window :below)'

LineageLinaje

What we kept from Emacs.
What we rebuilt.
Lo que conservamos de Emacs.
Lo que reconstruimos.

Kept, on purposeConservado, a propósito
  • M-x & named commandscomandos con nombre
  • major & minor modesmodos mayores y menores
  • keymaps & hooks
  • buffers, windows, framesbuffers, ventanas, frames
  • kill ring & registerskill ring y registros
  • keyboard macrosmacros de teclado
  • magit · dired · org
  • /ssh:host:/path
  • C-x C-f muscle memorymemoria muscular
Emacs GEMAX
Extension languageLenguaje de extensión Emacs Lisp Janet, a modern Lisp — plus WASM components in any languageJanet, un Lisp moderno, más componentes WASM en cualquier lenguaje
Event loopBucle de eventos single-threaded; a slow command freezes everythingun solo hilo; un comando lento congela todo one loop that never blocks; I/O on its own threads; a watchdog names slow packagesun bucle que nunca se bloquea; la E/S en sus propios hilos; un watchdog nombra a los paquetes lentos
DisplayPantalla redisplay coupled to the interpreterredisplay acoplado al intérprete wgpu renderer with a glyph atlas, smooth scroll and shaders — or a terminal UIrender wgpu con atlas de glifos, scroll suave y shaders, o una interfaz de terminal
TerminalTerminal term.el · vterm libghostty-vt, Ghostty's emulator core, linked statically: kitty images, live search, shell markslibghostty-vt, el núcleo del emulador Ghostty, enlazado estáticamente: imágenes kitty, búsqueda en vivo, marcas del shell
PluginsPlugins all in-process, unsandboxedtodo en el mismo proceso, sin aislamiento Janet in-process, or sandboxed WASM that is cut off at 500 ms and restartedJanet en el proceso, o WASM aislado que se corta a los 500 ms y se reinicia
AIIA packages bolted onpaquetes agregados encima an MCP server built in — agents are first-class users of the editorun servidor MCP integrado: los agentes son usuarios de primera clase del editor

ArchitectureArquitectura

Layers that don't know about the layers above. Capas que no saben de las de arriba.

Twenty-four Rust crates, each with one job. The core has no I/O and no UI; the renderers, the terminal and the language tools plug into it. Click a layer.

Veinticuatro crates de Rust, cada uno con una tarea. El núcleo no tiene E/S ni interfaz; los renders, el terminal y las herramientas de lenguaje se conectan a él. Haz clic en una capa.

gemax-core

Pure data and commands: text lives in a rope (O(log n) edits), windows are views with their own cursor, the frame holds the layout tree. No I/O, no rendering, no Janet. Interactive commands like isearch are state on the frame, never a nested loop.

Datos y comandos puros: el texto vive en un rope (ediciones O(log n)), las ventanas son vistas con su propio cursor y el frame guarda el árbol de layout. Sin E/S, sin render, sin Janet. Los comandos interactivos como isearch son estado en el frame, nunca un bucle anidado.

YouTú

Two front ends share one event loop: gemax-gui (GPU, winit) and gemax in any terminal. Same commands, same keymaps, same packages.

Dos interfaces comparten un mismo bucle: gemax-gui (GPU, winit) y gemax en cualquier terminal. Los mismos comandos, keymaps y paquetes.

Janet

An embedded Lisp that feels like Emacs Lisp: defcommand, define-derived-mode, hooks, buffer-locals. Evaluate a form with C-x C-e and the editor changes on the spot. Long work runs in cooperative fibers with a per-frame budget.

Un Lisp embebido que se siente como Emacs Lisp: defcommand, define-derived-mode, hooks, variables locales al buffer. Evalúas una forma con C-x C-e y el editor cambia en el acto. El trabajo largo corre en fibers cooperativos con un presupuesto por cuadro.

WASM components

Plugins compiled against wit/gemax.wit, generated from the API table — Rust, Go, C, anything that targets the component model. Sandboxed by wasmtime; a plugin that hangs is cut off and restarted, and disabled after three restarts.

Plugins compilados contra wit/gemax.wit, generado desde la tabla de la API: Rust, Go, C, cualquier lenguaje que apunte al component model. Aislados con wasmtime; un plugin que se cuelga se corta y se reinicia, y tras tres reinicios se desactiva.

MCP

gemax-mcp lets Claude Code or any MCP client open files, edit exact ranges, run commands, set breakpoints and wait for results. The guide it reads is generated from the packages you have loaded — never stale.

gemax-mcp deja que Claude Code o cualquier cliente MCP abra archivos, edite rangos exactos, ejecute comandos, ponga breakpoints y espere resultados. La guía que lee se genera desde los paquetes que tienes cargados: nunca queda vieja.

gemax-api

One table of operations with typed signatures. Janet natives, the WASM interface and MCP are three faces of it — add an operation once and every language gets it. Settings work the same way: one registry, read and written by name.

Una sola tabla de operaciones con firmas tipadas. Las nativas de Janet, la interfaz WASM y MCP son tres caras de ella: agregas una operación una vez y la reciben todos los lenguajes. Los ajustes funcionan igual: un registro, leído y escrito por nombre.

gemax-gpu

wgpu 29 and glyphon. A frame that didn't change costs nothing; terminal cells use a Ghostty-style glyph atlas; cursor breathing, smooth scroll, pane animations and post-process shaders are optional and data-driven.

wgpu 29 y glyphon. Un cuadro que no cambió no cuesta nada; las celdas del terminal usan un atlas de glifos al estilo Ghostty; la respiración del cursor, el scroll suave, las animaciones de paneles y los shaders son opcionales y se configuran como datos.

gemax-pty

A real terminal on Ghostty's VT core: one fused I/O thread (2.8 MB of cat in under 70 ms), kitty graphics, native search across the scrollback, OSC 133 shell marks, and agent detection by screen.

Un terminal de verdad sobre el núcleo VT de Ghostty: un solo hilo de E/S (2,8 MB de cat en menos de 70 ms), gráficos kitty, búsqueda nativa en todo el historial, marcas OSC 133 del shell y detección de agentes por pantalla.

LSP · DAP · tree-sitter

An eglot-style LSP client (diagnostics to inlay hints), a DAP client for debugpy, delve, codelldb and js-debug, and tree-sitter for 19 languages built in — plus any grammar loaded at run time.

Un cliente LSP al estilo eglot (de diagnósticos a inlay hints), un cliente DAP para debugpy, delve, codelldb y js-debug, y tree-sitter con 19 lenguajes incluidos, más cualquier gramática cargada en tiempo de ejecución.

diff · preview · notebook · graph

Reusable engines with many consumers: a git-independent diff with syntax and word-level refine, a native Markdown/PDF preview, a Jupyter codec that keeps .ipynb byte-faithful, and a layered graph layout.

Motores reutilizables con muchos consumidores: un diff independiente de git con sintaxis y refinado por palabra, un preview nativo de Markdown y PDF, un códec de Jupyter que conserva el .ipynb byte a byte y un layout de grafos por capas.

Daily driverPara el día a día

Everything you'd move in with.
Written in Lisp.
Todo lo que necesitas para mudarte.
Escrito en Lisp.

Magit

Status, staging by hunk or by line, interactive rebase, conflicts with smerge, Forge for GitHub.

Status, stage por hunk o por línea, rebase interactivo, conflictos con smerge, Forge para GitHub.

Org-mode

Agenda, capture, refile, babel, tables, folding — and org-modern bullets.

Agenda, capture, refile, babel, tablas, plegado, y viñetas al estilo org-modern.

LSP

Diagnostics, completion with snippets, go-to-definition, rename, code actions, inlay hints.

Diagnósticos, completado con snippets, ir a la definición, renombrar, code actions, inlay hints.

DebuggerDepurador

Breakpoints, stepping and locals for Python, Go, Rust, C/C++ and JavaScript.

Breakpoints, paso a paso y variables locales para Python, Go, Rust, C/C++ y JavaScript.

Terminal

Ghostty's emulator inside a buffer: images, search, scrollback, and an occur of links and commands.

El emulador de Ghostty dentro de un buffer: imágenes, búsqueda, historial y un occur de links y comandos.

Dired

A Dirvish-class file manager with preview, marks and editable listings — local or over ssh.

Un gestor de archivos al nivel de Dirvish, con vista previa, marcas y listados editables, local o por ssh.

NotebooksNotebooks

Jupyter .ipynb as plain text, real kernels, outputs and plots under each cell.

Jupyter .ipynb como texto plano, kernels reales, salidas y gráficos bajo cada celda.

Remote filesArchivos remotos

/ssh:host:/etc/hosts, TRAMP-style, opened and saved in the background.

/ssh:host:/etc/hosts, al estilo TRAMP, abiertos y guardados en segundo plano.

Preview

Native Markdown with mermaid, d2 and typeset math; PDF, LaTeX with SyncTeX, and Typst.

Markdown nativo con mermaid, d2 y fórmulas tipografiadas; PDF, LaTeX con SyncTeX y Typst.

  • and alsoy además
  • perspectives
  • dream diff
  • smerge
  • visual-line
  • folding
  • rectangles
  • registers
  • bookmarks
  • swiper
  • which-key
  • tree-sitter indent
  • outline
  • project tree
  • auth-source
  • ELisp → Janet
  • 19 languageslenguajes

Built for agentsHecho para agentes

Your editor.
Their workspace, too.
Tu editor.
También su lugar de trabajo.

Coding agents live in terminals and read files. GEMAX gives them a proper seat: an API they can drive, a board that tells you which one needs you, and the same diff review you'd get in an IDE.

Los agentes de código viven en terminales y leen archivos. GEMAX les da un lugar de verdad: una API que pueden manejar, un tablero que te dice cuál te necesita y la misma revisión de diffs que tendrías en un IDE.

goto {"line": 42}

edit {"line": 42, "text": "…"}

key {"chord": "C-x C-s"}

← ok · save-buffer · echo: Saved

wait_for {"debug_stopped": true}

← stopped=stats.py:12

An MCP server insideUn servidor MCP adentro

Claude Code — or any MCP client — edits exact ranges, runs commands, sets breakpoints and waits for output, instead of simulating keystrokes. Every answer says what actually happened.

Claude Code, o cualquier cliente MCP, edita rangos exactos, ejecuta comandos, pone breakpoints y espera resultados, en vez de simular teclas. Cada respuesta dice qué pasó de verdad.

*Agents* 3 · 1 blockedbloqueada

◆ api-server Claude Bash(rm -rf dist)

● docs Codex README.md

○ web Claude done 3m agolisto hace 3m

◌ notes Claude to resumepara retomar

Agents at a glanceLos agentes de un vistazo

GEMAX reads each terminal's screen and knows whether Claude Code, Codex or 20-odd other agents are working, waiting for you, or done — across workspaces and ssh. Desktop notifications, and sessions that come back after a restart.

GEMAX lee la pantalla de cada terminal y sabe si Claude Code, Codex u otros veintitantos agentes están trabajando, esperándote o terminaron, en cualquier workspace y por ssh. Avisos de escritorio y sesiones que vuelven tras reiniciar.

*Claude Diff: wrap.rs* hunk 1/2

- let first = cols - pad;

+ let first = cols.saturating_sub(pad).max(1);

let hang = …

a acceptaceptar r rejectrechazar C-c C-c applyaplicar

Claude Code speaks IDEClaude Code habla IDE

GEMAX implements the same IDE protocol as VS Code and JetBrains: Claude sees your selection and diagnostics, and its edits arrive as diffs you accept or reject hunk by hunk.

GEMAX implementa el mismo protocolo de IDE que VS Code y JetBrains: Claude ve tu selección y tus diagnósticos, y sus ediciones llegan como diffs que aceptas o rechazas hunk por hunk.

ExtendingExtender

Four ways to extend it.
Pick the one that fits.
Cuatro formas de extenderlo.
Elige la que encaja.

TierNivel Good forSirve para If it misbehavesSi se porta mal
defcommandJanet, main threadJanet, hilo principal commands, hooks, quick editscomandos, hooks, ediciones rápidas a watchdog names it in *Warnings*un watchdog lo nombra en *Warnings*
defcommand-asynccooperative fibersfibers cooperativos scans, background analysisrecorridos, análisis en segundo plano a per-frame budget; C-g cancelsun presupuesto por cuadro; C-g cancela
WASM componentComponente WASMany language, sandboxedcualquier lenguaje, aislado untrusted or CPU-heavy codecódigo no confiable o pesado preempted, restarted, then disabledse interrumpe, se reinicia y luego se desactiva
call-process-asyncits own OS processsu propio proceso formatters, linters, CLIsformateadores, linters, CLIs it can't block the editorno puede bloquear el editor
# ~/.config/gemax/init.janet
(defcommand open-todo
  "Open the project's TODO.org beside the code."
  (split-window :right)
  (call-command "other-window")
  (find-file "TODO.org"))

(bind-key "C-c t" "open-todo")
# place the cursor after a form, press C-x C-e: it exists now

Real screenshotsCapturas reales

Not a mockup.
The editor, as it is today.
No es una maqueta.
El editor, tal como es hoy.

InstallInstalar

Start with C-x C-f. Empieza con C-x C-f.

  1. 1

    DownloadDescarga

    One tarball with gemax-gui, the terminal editor gemax and the MCP server. Linux x86_64.

    Un tarball con gemax-gui, el editor de terminal gemax y el servidor MCP. Linux x86_64.

    First package coming soonEl primer paquete, muy pronto
  2. 2

    Run the installerCorre el instalador

    Installs into ~/.local without sudo, checks your machine, and prints the one command your distro needs, if any.

    Instala en ~/.local sin sudo, revisa tu máquina e imprime el único comando que tu distro necesite, si hace falta.

    $ ./install.sh
  3. 3

    Open itÁbrelo

    Your keys already work. Your config lives in ~/.config/gemax/init.janet, and M-x knows the rest.

    Tus teclas ya funcionan. Tu configuración vive en ~/.config/gemax/init.janet y M-x sabe el resto.

    $ gemax-gui

Tested on fresh Ubuntu, Debian, Fedora, Arch and openSUSE, under X11 and Wayland. Runs on Vulkan or plain OpenGL. Pre-v0.1: daily-usable, still moving fast.

Probado en Ubuntu, Debian, Fedora, Arch y openSUSE recién instalados, con X11 y Wayland. Funciona con Vulkan u OpenGL. Pre-v0.1: se usa a diario y todavía cambia rápido.