Skip to content

romgrk/zym

Repository files navigation

zym

zed + neovim + cursor
Native GTK 4 — no Electron.
Node.js under the hood — the full npm ecosystem.

A keyboard-driven, modern code editor — blending the best from neovim, atom, zed, vscode, and so many others — with coding agents living right alongside you — each tracked live, so you always know which agent is working, waiting, or done.

Beta state. Tested on Linux; might not run on macOS or Windows yet.

zym running a coding agent side by side with the editor, file tree, and a fuzzy command palette

Highlights

  • ⌨️ Vim beyond its best: the vim-mode-plus plugin ported from Atom — so good it's better than the original. Multi-cursor, occurrences, text objects, operators, and more (target.vim, leap.nvim, etc).
  • 🤖 Agents (well at least claude) — you work alongside your minions. Jump to their workbench to see what they edited. Jump to your workbench to work on your own.
  • 🪟 Built for simplicity — a space-leader scheme (thanks Spacemacs) and fuzzy finders for everything.
  • 🎨 Native GNOME look — Adwaita with simple theming support.
  • Editor essentials — LSP, tree-sitter syntax highlighting, file tree, git integration, and more.

Coming up: 🌳 git worktree integration: spawn your minions in their own worktrees and switch to their view whenever you want.

Jump to the details: Keybindings · Notifications · Agents · Configuration

In action

Coding agents

Run claude and friends in the workbench, branch and switch between them from a fuzzy command palette, and drive everything without leaving the keyboard.

Fuzzy command palette listing the agent: commands

Code intelligence (LSP)

Language servers power completion, hover docs, and diagnostics — and zym offers to install a missing server for you.

Autocomplete popup with documentation for the selected entry Hover tooltip showing an inferred type Toast offering to install a missing language server

Navigation & search

Jump to any symbol, search the project with ripgrep, or find-and-replace with regex in the current file.

Symbol picker filtering workspace symbols Project-wide ripgrep picker with live results In-buffer regex search and replace

Git & GitHub

Checkout a pull request branch without leaving your editor. Filter as if you were on GitHub.

Pull request picker filtered by author

Create a pull request in a single click.

Creating a pull request from the current branch

See live CI check status, and jump to any run log:

CI checks all passing for a branch

Project sidebar

A file tree and a live git status view sit side by side in the left dock.

File tree in the sidebar Git status view listing staged and unstaged changes

Requirements

  • Node.js and pnpm
  • GTK 4, libadwaita, and GtkSourceView 5 with their GObject-Introspection typelibs installed (Gtk-4.0, Adw-1, GtkSource-5)

Install

pnpm add -g github:romgrk/zym

Usage

zym [file]

Keybindings

zym is organized around a space leader: press space, then a mnemonic. Press space ? to see the keymap panel.

Bindings live in src/keymaps/default.ts. To override them, drop a ~/.config/zym/keymap.json (the same { "selector": { "keystroke": "command" } } shape) — user bindings take priority over the defaults.

Selectors target a zym component by name with an #id: #AppWindow, #Panel, #FileTree, #TextEditor.insert-mode, etc.

A binding's value may also pass arguments to its command, using { "command": "...", "args": [...] } instead of a bare string. For example, Alt+1Alt+8 are a single parameterized command:

{ "#Panel": { "alt-3": { "command": "tab:go-to", "args": [2] } } }

Use the value "unset!" to release a keystroke for a selector so it falls through to the widget instead of triggering a binding. Widgets that take literal text input (entries, the terminal, the editor in insert mode) carry a .has-text-input class, and a single rule frees Space there even though it's the global leader prefix:

{ ".has-text-input": { "space": "unset!" } }

Notifications

Modeled on Atom's NotificationManager, zym separates posting a notification from showing it. Subsystems post through the global hub, zym.notifications, which keeps every notification for the session; views render from it.

zym.notifications.addInfo('Saved');
zym.notifications.addWarning('Untracked files hidden');
zym.notifications.addError('Push failed', { detail: 'rejected: non-fast-forward' });

There are five severities — addInfo, addSuccess, addWarning, addError, and addFatalError — each taking a message and optional { detail, description, icon, dismissable, buttons }. By default a notification auto-expires; pass dismissable: true to keep its toast until it's closed.

Each posted notification shows up in two places:

  • a transient toast over the workbench (one action button is mapped from buttons), and
  • the notification log, a panel in the bottom dock holding the full session history (severity icon, message, optional detail, and the time it was posted).

On a toast, detail/description and any buttons beyond the first are dropped — they belong to the log. The log is hidden until toggled with Space n; while it's focused, c clears the history and q hides it (commands notifications:toggle-log and notifications:clear, also reachable from the command picker). Window actions like saving and the git commands post through this hub, so their results land in the log too.

Agents

zym can host terminal-based coding agents (such as claude) right inside the workbench. An agent is a terminal like any other, except it runs the agent CLI instead of a login shell and is tracked in the global registry zym.agents. When the agent process exits the pane is not torn down — a "process exited" notice is printed and the agent stays listed, flipped to an exited status, so you can read its final output.

  • Space a a opens the agent quick-switcher (agent:switch), a fuzzy picker over the running agents. Typing a prompt and choosing Start agent launches a fresh agent seeded with that prompt.
  • Space a n launches a new agent (agent:new). The argv comes from the agent.command config (default ['claude']).

Running agents appear in the workbench list:

Indicator Meaning
green dot idle / ready
amber dot waiting for the user (e.g. a permission prompt)
grey cog working
muted dot the process has exited

Activating a row reveals and focuses that agent's terminal.

For a claude agent the live status is driven by Claude Code hooks: zym launches claude with a per-session --settings block whose hooks write a status word to a file the terminal watches (via a Gio file monitor). The reporter script is bundled at assets/hooks/agent-status.sh.

Configuration

Settings live in ~/.config/zym/config.json (or $XDG_CONFIG_HOME/zym/), created automatically on first launch. The file is a flat map of dotted keys to values:

{
  "editor.tabLength": 4,
  "editor.fontSize": 15,
  "core.followSystemColorScheme": false
}

Each key is an override on top of its built-in default — only list the ones you want to change; deleting a key reverts it to the default. A value that's out of range or the wrong type is ignored with a warning. Saving the file applies the changes immediately, no restart needed.

You can also open the preferences window (space , ,, or config:open-editor from the command picker), which writes back to the same config.json. Its labels are the config keys themselves (e.g. the fileTree group, the hideHidden row), so they match exactly what you'd write by hand. To edit the JSON in a tab instead, use config:open-as-text.

The baseline keys:

Key Type Default Description
core.followSystemColorScheme boolean true Follow the system light/dark preference
editor.tabLength integer 2 Spaces a tab is rendered as (1–16)
editor.fontFamily string "" Editor font family; empty uses the platform mono
editor.fontSize integer 13 Editor font size in points (6–100)

License

GPL-3.0-or-later.

The tree-sitter highlight queries under src/syntax/queries/ are vendored from Zed (crates/grammars/src/), which are licensed GPL-3.0 — bundling them is why zym is distributed under the GPL.

About

[BETA] A modal source-code editor built with GTK 4 on node-gtk

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors