A modal text editor with a client–server architecture for Linux and macOS. Native, terminal and web clients connect to a shared server process.
- Selection-first motions, sneak, surround, transforms, motion undo/redo
- Tree-sitter integration (highlighting, indentation, selection expand/contract)
- LSP support (diagnostics, hover, go-to-definition, references, document/workspace symbols, formatting)
- Git integration (gutter, inline diff, blame, hunk staging, remotes, commit, branch switching, worktrees, history, stashes)
- Markdown reader mode
- Fuzzy pickers (files, buffers, shells, agents, symbols, diagnostics, git changes), workspace grep
- File explorer, cross-file jump history, workspace switching
- Native, terminal and web clients with consistent keymaps and behaviour
Prebuilt binaries for Linux and macOS (Apple Silicon) are attached to each release.
aether-<version>-<target>.tar.gz— the GUI build. Unpack it and putaeon yourPATH; needs a graphical environment at runtime.aether-<version>-<target>-no-gui.tar.gz— as above, but terminal/web only.aether-<version>-x86_64.AppImage(Linux) — the GUI build as one self-contained executable:chmod +xand run, nothing to unpack. Symlink it onto yourPATH(ln -s /path/to/aether-<version>-x86_64.AppImage ~/.local/bin/ae) and everyaecommand works through it; an AppImage integration tool can add the app-menu entry and icon.aether-<version>-<target>.dmg(macOS) — the GUI build as a drag-installAether.app. For the command line, symlink the binary it wraps (ln -s /Applications/Aether.app/Contents/MacOS/ae /usr/local/bin/ae).
macOS: downloads are unsigned, so clear the quarantine flag once —
xattr -d com.apple.quarantine ./aefor a.tar.gzbinary,xattr -dr com.apple.quarantine /Applications/Aether.appfor the app bundle.
Type Space y for the in-app searchable list. Holding the Shift key extends the selection (e.g.
Shift-w); a leading count repeats a motion (e.g. 3w). Space is the leader for
app/file/code commands, Space g the sub-leader for git operations, Space v the sub-leader for
the verbs of the view you are in (stop what it is running), and Space n reveals hover info at the
cursor. What a view offers to do — answering an agent, folding a tool call — is a button in the
view itself: Tab reaches it and Enter presses it.
| Key | Action |
|---|---|
h/l |
Character left/right |
j/Alt-j |
Logical/visual line down |
k/Alt-k |
Logical/visual line up |
w/Alt-w |
Select small/big word |
b/Alt-b |
Small/big word backward |
e/Alt-e |
Small/big word end |
0, Home |
Logical line start |
Alt-l, End |
Logical line end |
Alt-h |
First non-blank of line |
f/Alt-f |
Find character forward/backward (next key is the target) |
t/Alt-t |
Till character forward/backward |
s/Alt-s |
Sneak to small/big word (type a prefix, then the label on the word you want) |
m/Alt-m |
Matching bracket/inner matching bracket |
o/Alt-o |
Next/previous symbol |
p/Alt-p |
First non-blank of next/previous line |
g/Alt-g |
Go to line (count, default 1)/from end (default last) |
v/Alt-v |
Cursor down/up half a page |
Backspace/Alt-Backspace |
Jump back/forward (cross-file history) |
]/[ |
Next/previous jumplist entry |
}/{ |
Next/previous jumplist entry in this file |
Tab/Shift-Tab |
Next/previous button or input — the things a view offers to act on |
These move the view, not the cursor, and work the same in the reading view.
| Key | Action |
|---|---|
PageUp/PageDown |
Scroll a page up/down |
Alt-↑/Alt-↓ |
Scroll half a page up/down |
↑/↓ |
Scroll one line up/down |
←/→ |
Scroll one column left/right (in the reading view, the focused code block) |
| Key | Action |
|---|---|
, |
Collapse selection |
u/Alt-u |
Reverse selection (swap cursor and anchor) / orient it forward |
% |
Select all |
q/Alt-q |
Expand/contract selection to syntax node |
x/Alt-x |
Select line downward/upward |
z/Alt-z |
Undo/redo cursor motion |
r |
Repeat last motion, with its count and Shift as pressed (Shift-w r keeps extending) |
;/Alt-; |
Cursor near top/bottom of window |
| Key | Action |
|---|---|
/ |
Search |
? |
Search, selecting from the cursor to the match |
Alt-/ |
Search for current selection |
n/Alt-n |
Next/previous match |
Esc |
Clear the active search |
Alt-c/Alt-w/Alt-e toggle case sensitivity, whole-word and regex matching from the prompt, and
Alt-Backspace drops the query's last word. Up/Down recall earlier queries — here and in every
other overlay input (grep, globs, paths).
Every Ctrl edit works in both modes. The clipboard/edit keys are selection-scoped in normal and line-scoped in insert (since insert has no selection), on the same key; the rest are identical in both.
| Key | Normal | Insert |
|---|---|---|
Ctrl-e |
Change selection | Change line |
Ctrl-d |
Delete selection | Delete line |
Delete |
Delete selection | Delete character at cursor |
Ctrl-c |
Copy selection | Copy line |
Ctrl-x |
Cut selection | Cut line |
Ctrl-Alt-x |
Cut selection and insert | — |
Ctrl-v |
Paste before selection | Paste at cursor |
Ctrl-Alt-v |
Replace selection with clipboard | Replace line with clipboard |
Ctrl-s |
Surround selection (next key = delimiter) | Surround line |
Ctrl-Alt-s |
Unsurround selection | Unsurround line |
Ctrl-u |
Transform selection (next key = transform: case styles, invert, reverse, randomise) | Transform identifier under cursor |
Ctrl-z/Ctrl-Alt-z |
Undo/redo | Undo/redo |
Ctrl-r |
Repeat the last change on the current selection — a Ctrl edit, or an insert session as one unit (Ctrl-e foo Esc, then n Ctrl-r) |
Repeat the last insert session's typing inline |
Ctrl-l/Ctrl-h |
Indent/dedent | Indent/dedent |
Ctrl-j/Ctrl-k |
Move line(s) down/up | Move line(s) down/up |
Ctrl-Alt-j/Ctrl-Alt-k |
Move paragraph down/up | Move paragraph down/up |
Ctrl-g |
Join lines | Join lines |
Ctrl-Alt-g |
Un-join lines (cursor stays before the break) | Line break at caret, caret stays |
Ctrl-a/Ctrl-Alt-a |
Increment/decrement number | Increment/decrement number |
Ctrl-y/Ctrl-Alt-y |
Toggle line/block comment | Toggle line/block comment |
Ctrl-f |
Format document | Format document |
Ctrl-o/Ctrl-Alt-o |
Open line below/above | Open line below/above |
In insert mode, Tab indents to the next tab stop and Backspace steps back to the previous one,
both following the file's own indent style. Alt-←/Alt-→ move by word, and
Alt-Backspace/Alt-Delete delete the word before/after the caret.
| Key | Action |
|---|---|
i/a |
Insert at selection start/end |
Alt-i/Alt-a |
Insert at first non-blank of line/last line end |
Esc |
Leave insert mode |
Space u renders the current Markdown file — headings, tables, images, links and highlighted
code fences — as a read-only view with its own keys. The reading position is the cursor, so
toggling back lands where you were reading. Reading is how this window sees the file: another
window on the same file is not affected. Opening a file lands in whichever way it was last shown,
and the markdown_read setting (Space ,) decides for a file nobody has shown yet.
o/Alt-o step the document outline — the same outline the breadcrumb and Space o show, which
comes from the language server. Heading navigation therefore needs a Markdown language server
configured; the rest of the reading view works without one.
| Key | Action |
|---|---|
Space u |
Toggle the reading view |
j/k |
Focus next/previous element |
l/h |
Focus next/previous link in the block |
o/Alt-o |
Next/previous heading |
g/Alt-g |
First/last element |
z/Alt-z |
Undo/redo the reading-position move |
Enter |
Follow the link, open the image, jump to the footnote, or toggle a task's checkbox |
Ctrl-Enter |
Follow a relative link in a new window (GUI and browser: a terminal has no window to open it in, and no way to send the chord) |
Space n |
Show the link's or image's target |
x/Alt-x, Shift-j/Shift-k |
Select blocks — as in the editor, plain x walks and Shift extends |
u/Alt-u |
Reverse the selection / orient it forward |
%/, |
Select every block / collapse the selection to the cursor's block |
Ctrl-c |
Copy the selection, the link URL, or the element's Markdown source |
Ctrl-z/Ctrl-Alt-z |
Undo / redo |
Ctrl-r |
Repeat the last change on the focused block(s) |
Ctrl-a/Ctrl-Alt-a |
Check / uncheck the focused task item |
i/a |
Edit: insert at block/selection start / end |
Ctrl-e |
Edit: rewrite the selected block(s) |
Ctrl-o/Ctrl-Alt-o |
Edit: open a new block below / above — a list item inside a list, a paragraph elsewhere |
Ctrl-j/Ctrl-k |
Move block(s) down / up (Ctrl-Alt-j/k moves paragraphs in the editor) |
Ctrl-x, Ctrl-v/Ctrl-Alt-v |
Cut block(s); paste as block / replace selection |
Ctrl-d |
Delete block(s) (no clipboard) |
Ctrl-l/Ctrl-h |
Deepen/flatten: heading level, list nesting, or blockquote level |
Search, jump history and the scroll/placement keys behave as they do in normal mode.
| Chord | Action |
|---|---|
Space f/Space Alt-f |
Find files / in this file's directory |
Space b/Space Alt-b |
Switch buffer / new scratch |
Space t/Space Alt-t |
Switch shell / a new shell to run a command in |
Space a/Space Alt-a |
Switch agent conversation / a new one |
Space //Space Alt-/ |
Grep workspace / for current selection |
Space e/Space Alt-e |
File explorer / at workspace root |
Space w/Space Alt-w |
Switch workspace / open file by absolute path |
Space j/Space Alt-j |
Jumplist (Ctrl-j in any picker captures its results into it) / clear it |
Space p/Space Alt-p |
Copy relative/absolute path |
Space s/Space Alt-s |
Save / save as |
Space k/Space Alt-k |
Keep this document — in a review, the file under the cursor / reload from disk |
Space x/Space Alt-x |
Close view / save and close it |
Space z/Space Alt-z |
Open another window / copy this view's web URL |
Space ,/Space . |
Application settings (soft wrap, font sizes, …) / this workspace's (roots, projects) |
Space v c |
Stop what this view is running — a shell's command, an agent's turn |
Space h/Space Alt-h |
Dismiss the current hint / turn hints off |
Space q/Space Alt-q |
Quit / save and quit |
Space y/Space ? |
Show keyboard shortcuts / about this build |
Space t and Space a switch between them, Space Alt-t and Space Alt-a make new ones. Both
views are a transcript with an input at the bottom, and that input is a real editor element —
every motion, edit and selection key works in it. Two keys mean something different while the
caret is there:
| Key | Action |
|---|---|
Enter |
Run the command / send the prompt, from either mode |
Alt-Enter |
A newline, for a multi-line command or prompt |
Up/Down recall earlier commands while the input is a single line. Tab/Shift-Tab move the
caret out to the transcript and back, where Enter opens the file the line under the cursor names
and edits are refused.
Navigation, reveals and views sit on the plain leader, beside their diagnostics counterparts; the
operations live behind the Space g sub-leader. There, a plain/Alt pair names one verb at two
scopes — plain takes the change under the cursor (or the selected lines), Alt the whole file.
| Chord | Action |
|---|---|
c/Alt-c |
Next/previous change (hunk) |
Space c/Space Alt-c |
Git changes in current file / across the workspace (hunks) |
Space m |
Blame commit details for the cursor line |
Space i/Space Alt-i |
Toggle inline diff, in a file or a patch view / choose what it diffs against |
Space g s/Space g Alt-s |
Stage the change / the whole file (also marks a conflict resolved) |
Space g u/Space g Alt-u |
Unstage the change / the whole file |
Space g r/Space g Alt-r |
Revert the change / the whole file |
Space g </Space g >/Space g = |
Resolve a conflict: keep the top (<<<<<<<), the bottom (>>>>>>>), or both sections |
Space g c/Space g Alt-c |
Commit staged changes / amend the previous commit |
Space g z |
Uncommit (keep the changes staged) |
Space g w |
Working changes — everything uncommitted, as one patch |
Space g l/Space g Alt-l |
History / this file's history |
Space g b |
Branches and worktrees |
Space g f |
Fetch from the remote |
Space g p/Space g Alt-p |
Pull from / push to the remote |
Space g x |
Stop the fetch, push or pull in progress |
Space g t/Space g Alt-t |
Stash the working tree / just the staged changes |
Space g a |
Stashes (preview, pop, apply, drop) |
Space g d |
Abandon a stopped merge or rebase (asks first) |
| Chord | Action |
|---|---|
Space n |
Hover (type & docs, or a link's target) |
Enter |
Follow what's under the cursor: the definition — or, in a patch or a shell's output, the file that line names. In a shell's input, run the command |
Space r |
Go to references |
d/Alt-d |
Next/previous diagnostic |
Space Alt-n |
Diagnostic at cursor |
Space d/Space Alt-d |
Diagnostics: this file / workspace |
Space o/Space Alt-o |
Document / workspace symbols |
Space l |
LSP servers (status, restart) |
Ctrl-f |
Format document |
Aether is a standard Cargo workspace.
cargo build --releaseThis produces a single binary:
ae— runs the server daemon, the terminal client, and (when built with theguifeature, on by default) the native GUI client. The build that ships the GUI is the default; dropping it withcargo build --release -p aether-ae --no-default-features(soiced/winit/wgpunever enter the dependency graph) is exactly the-no-guirelease artifact, for a box with no display libraries.
Just run ae — it opens a client and, if no server is already running, auto-starts one in the
background:
ae # open the workspace picker
ae src/main.rs # open a file (workspace inferred from its path)
ae src/ # open the file explorer at a directory
ae -w aether # open the "aether" workspace
ae -w aether src/main.rs # open a file in a named workspaceThe first client launches a background server and connects to it; later clients reuse it, and the
server idle-reaps itself once nothing has been connected for a while. To run a persistent server
yourself (e.g. to watch its logs), use ae server, and stop it with ae server stop.
With no --gui/--tui flag, ae picks a client automatically: a terminal on stdout means the
terminal client; no terminal but a display set (a desktop launcher) means the GUI. Pass --gui or
--tui to force one.
A path is resolved against the current working directory; if it falls outside every configured
workspace it opens as a standalone file. A directory opens the file browser there.
Opening a file that way — ae file, with no -w — tethers the client to that file's view: closing it
(Space x, or Space Alt-x to save first) exits the client, so ae works as an $EDITOR for git
and anything else that waits for the process to finish.
Workspaces are created and managed from the workspace picker (Space w); running ae with no
arguments opens it.
The web client is served by the same server process: with a server running, open
http://127.0.0.1:2384. There's no token to copy — the daemon is loopback-only and authorizes by
Host/Origin, so a browser on the same machine just connects.
Building from source needs its bundle built once (web/, TypeScript):
cd web
npm install # first time only
npm run build # tsc (typecheck + compile), then Vite bundles to web/distRelease builds embed web/dist in the binary, so a released ae is self-contained; debug builds
read it from disk, so a rebuilt bundle is served without restarting the server.
