Elyra
Elyra The coding agent e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Elyra SQL Server MySQL-compatible SQL server in Rust Elyra Félagi Agents as teammates on one board Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra Sjá SEO & GEO workspace for macOS Elyra DataGrid Server-driven data grid for Laravel
Release notes
Changelog
Elyra
Editing

Editing

e provides the editing primitives you expect from a modern code editor.

Creating & saving files

  • ⌘N creates a new, empty untitled buffer — start typing right away.
  • ⌘S saves; for an untitled buffer it opens a Save As dialog, then reopens the file with the right language, LSP, and git support.
  • ⌘⇧S is Save As… for any buffer.

Line operations

Action Shortcut
Duplicate line ⌘D (or ⇧⌥↓)
Move line up / down ⌥↑ / ⌥↓
Delete line ⌘⇧K
Indent / outdent ⌘] / ⌘[

Line operations act on the line containing the caret, or on every line touched by the current selection.

Comments

Toggle line comments for the current line or selection with ⌘/. The comment token is chosen from the file's language (// for Rust/JS/TS/PHP/C/Go, # for Python/Shell/TOML, and so on). Toggling again removes them.

Multiple cursors

  • ⌘⇧D adds a cursor at the next occurrence of the current word or selection. Repeat to keep adding cursors, then edit them all at once.
  • ⌘⇧L selects all occurrences at once.
  • ⌥⌘↑ / ⌥⌘↓ add a cursor on the line above / below at the same column (column editing).
  • -click adds a cursor with the mouse; -drag adds a selection.

Auto-closing brackets & quotes

As you type (, [, {, ", ', or `, the matching closing character is inserted automatically and the caret is placed between them. In addition:

  • Type-over: typing a closing character when it already follows the caret steps over it instead of inserting a duplicate.
  • Wrap selection: with text selected, typing an opening bracket or quote wraps the selection.
  • Smart backspace: deleting the opening half of an empty pair removes both characters.
  • Apostrophes after a word (e.g. don't) are not auto-closed.

Disable this behaviour with "auto_close": false in your configuration.

Auto-indent

Pressing Enter keeps the indentation of the current line, so new lines line up with the code above.

Undo tree

Beyond the usual undo/redo (⌘Z / ⌘⇧Z), e records every edit into a branching undo tree. When you undo and then type something new, the old branch isn't thrown away — it becomes a sibling you can return to.

Press ⌘⌥U to open the tree. Each node shows how long ago it was and how many characters changed; a marks a branch point. Click any node to jump the buffer to that state ("time travel"). The tree is saved per file under ~/.config/e/undo/, so history survives across sessions.

Rename

Press F2 to rename every whole-word occurrence of the identifier under the caret within the current file. (Project-wide LSP rename depends on the language server.)

Code actions & refactors

Press ⌘. to ask the language server for code actions at the cursor or selection — quick fixes for diagnostics and refactors like extract variable / extract method — then pick one to apply. Availability depends on the server.

Compare files

Run Compare Active File With… from the command palette (⌘⇧P) to pick another file and see a line-by-line diff of it against the current file. (For changes vs git HEAD, use Show Git Diff vs HEAD.)

Saving

  • ⌘S saves the active file.
  • With format on save and trim on save enabled (the defaults), the file is formatted via the language server and trailing whitespace is trimmed before writing.
  • Auto-save writes dirty buffers after a short idle period.
  • EditorConfig: if the project has an .editorconfig, its indent_size / tab_width set the buffer's tab width, and trim_trailing_whitespace / insert_final_newline override the on-save settings for matching files.

See Configuration to adjust these.

Emmet

In HTML, Blade, Vue, Svelte and PHP files, type an Emmet abbreviation and press Tab to expand it (or run Emmet: Expand Abbreviation from the palette):

Abbreviation Expands to
.card>h2{Title}+p a div.card containing an <h2> and a <p>
ul>li.item$*3 a <ul> with three <li class="item1…3">
a / img / input tags with their default attributes
nav>(a+a+a) grouping with ()

Supported: tags, .class, #id, [attr=value], {text}, child >, sibling +, grouping (), multiplication *N and $ numbering. The caret lands at the first sensible insertion point.

Encoding & line endings

The status bar shows the file encoding and line-ending style. Click the LF / CRLF indicator to convert the buffer. Non-UTF-8 files are detected on open (BOM or Windows-1252) and saved back in their original encoding.

Unsaved changes & external edits

  • Closing a tab with unsaved changes prompts you to Save, Don't Save, or Cancel.
  • If a file changes on disk (e.g. after git checkout), clean buffers reload automatically. If you have unsaved edits, a bar offers to Reload (discard yours) or Keep yours.

Rename (F2)

Put the caret on a symbol and press F2. e asks the language server what the rename would change and shows you every site — the file, the line, and the line as it will read — before anything is written:

app/Models/Order.php
  14: public $total;
     → public $amount;
  27: return $this->total * 1.25;
     → return $this->amount * 1.25;

Rename applies it; Cancel leaves everything alone. Files you have open change through the buffer, so a rename is undoable like any other edit; the rest are written to disk.

The language server is what makes this safe: it knows which occurrences are the symbol and which are a word that happens to match inside a string or a comment, and it sees the whole workspace rather than the file you're in.

Without a language server for the language — or when the server declines the rename — e falls back to replacing whole-word matches in the current buffer. That is textual, so check the preview.

Move Class

Refactor: Move Class… in the command palette. It reads the active file's fully-qualified name from its path, asks for the new one, and previews the move:

App\Models\Order → App\Domain\Order
app/Models/Order.php → app/Domain/Order.php · 3 references in 2 other files

app/Http/Controllers/OrderController.php  (2 references)
tests/Feature/OrderTest.php  (1 reference)

Move rewrites the referrers, writes the file at its new path, and removes the old one. Referrers are written first: if one of those fails, the class is still where every reference expects it.

PSR-4 from your composer.json decides where the file goes, including autoload-dev, so moving a test class works the same way. A namespace no PSR-4 entry covers is refused rather than written somewhere Composer will never autoload it.

Matching is by whole name. Moving App\Models\Order leaves App\Models\OrderItem alone, and Legacy\App\Models\Order is a different class. Aliased imports keep their alias; a leading \ is preserved. Change the class name in the same move and its declaration and self-references follow — without renaming a method that happens to share the name.

References inside strings are not rewritten. A class name in a config array is indistinguishable from prose, and silently editing a string is the worse mistake. Search for the old name afterwards if you use them.