You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Press ctrl+h/j/k/l anywhere and go the direction you meant — between nvim's own splits while you're inside it, between Macterm panes when you reach nvim's edge or you're at a shell prompt. The vim-tmux-navigator experience, without tmux.
Requires Macterm v1.23.0 or later.
How it works
Two halves, because a terminal can't tell whether a program used a key.
Macterm declines the chord when a program you've named is running in the pane, so the key reaches nvim instead of firing Macterm's action — the Pass to TUI checkbox.
nvim hands focus back when it has nowhere left to go, by calling macterm pane focus --direction left.
A program that doesn't call back can't participate: btop and less will swallow the chord rather than move panes, so don't list them.
1. Macterm
Settings → Keymaps.
In Passthrough Programs, name the programs that should get these keys:
nvim
Commas or spaces both work. Match the name shown in the tab title — that's what Macterm compares against. Paths are fine (/opt/homebrew/bin/nvim matches nvim).
Rebind Focus Left / Down / Up / Right from their defaults (⌘⌃H etc.) to ⌃H, ⌃J, ⌃K, ⌃L.
Check Pass to TUI on those four rows.
An empty Programs list means nothing yields — the checkbox is inert until you name something.
Binding bare ctrl chords costs you their shell bindings at a prompt:
Chord
What you give up
⌃H
delete-char-backward — Backspace still works (macOS sends DEL 0x7F, not ^H)
⌃J
accept-line — Enter still works
⌃K
kill-to-end-of-line
⌃L
clear-screen — the one people miss; use clear
If ⌃L matters more than vertical navigation, bind only Focus Left/Right and leave ⌃J/⌃K alone.
2. nvim
-- ~/.config/nvim/init.lualocalfunctionnavigate(wincmd, direction)
localbefore=vim.api.nvim_get_current_win()
vim.cmd.wincmd(wincmd)
ifvim.api.nvim_get_current_win() ~=beforethenreturnend-- nvim had nowhere to go, so hand focus out at its own edge.vim.system({ "macterm", "pane", "focus", "--direction", direction })
endforchord, moveinpairs({ h="left", j="down", k="up", l="right" }) dovim.keymap.set("n", "<C-" ..chord..">", function() navigate(chord, move) end)
end
wincmd h fails silently at the edge, leaving the window handle unchanged — that's the whole detection. Handles are unique identities, so two windows showing the same file at the same cursor position still compare unequal.
vim.system() needs nvim 0.10+ and spawns without a shell, so nothing needs quoting. On older nvim use vim.fn.jobstart.
No --session flag needed: every pane exports MACTERM_SESSION, so a bare pane focus --direction moves from the pane it ran in.
Floating windows: wincmd h from a float does nothing, so you'd jump out of nvim from inside a picker. If you live in floats, bail early with if vim.api.nvim_win_get_config(before).relative ~= "" then return end.
<C-h> vs Backspace: in legacy terminals both are byte 0x08, the classic vim-tmux-navigator footgun. Ghostty speaks the Kitty keyboard protocol and nvim 0.10+ enables it, so they arrive distinguishable here.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Press ctrl+h/j/k/l anywhere and go the direction you meant — between nvim's own splits while you're inside it, between Macterm panes when you reach nvim's edge or you're at a shell prompt. The vim-tmux-navigator experience, without tmux.
Requires Macterm v1.23.0 or later.
How it works
Two halves, because a terminal can't tell whether a program used a key.
macterm pane focus --direction left.A program that doesn't call back can't participate:
btopandlesswill swallow the chord rather than move panes, so don't list them.1. Macterm
Settings → Keymaps.
In Passthrough Programs, name the programs that should get these keys:
Commas or spaces both work. Match the name shown in the tab title — that's what Macterm compares against. Paths are fine (
/opt/homebrew/bin/nvimmatchesnvim).Rebind Focus Left / Down / Up / Right from their defaults (
⌘⌃Hetc.) to⌃H,⌃J,⌃K,⌃L.Check Pass to TUI on those four rows.
An empty Programs list means nothing yields — the checkbox is inert until you name something.
Binding bare ctrl chords costs you their shell bindings at a prompt:
⌃H0x7F, not^H)⌃J⌃K⌃LclearIf
⌃Lmatters more than vertical navigation, bind only Focus Left/Right and leave⌃J/⌃Kalone.2. nvim
wincmd hfails silently at the edge, leaving the window handle unchanged — that's the whole detection. Handles are unique identities, so two windows showing the same file at the same cursor position still compare unequal.vim.system()needs nvim 0.10+ and spawns without a shell, so nothing needs quoting. On older nvim usevim.fn.jobstart.--sessionflag needed: every pane exportsMACTERM_SESSION, so a barepane focus --directionmoves from the pane it ran in.wincmd hfrom a float does nothing, so you'd jump out of nvim from inside a picker. If you live in floats, bail early withif vim.api.nvim_win_get_config(before).relative ~= "" then return end.<C-h>vs Backspace: in legacy terminals both are byte0x08, the classic vim-tmux-navigator footgun. Ghostty speaks the Kitty keyboard protocol and nvim 0.10+ enables it, so they arrive distinguishable here.All reactions