A native terminal for Linux and macOS
Tabs, split panes, shell integration, and plugins in any language. Drawn on the GPU, not in a webview.
Everything a terminal should do, done properly
- Tabs and split panes
- Drag tabs to reorder them and drag the gaps to resize splits. Focus Mode zooms one pane. Every window, tab and split comes back next launch.
- A quick terminal
- It drops down from the top of the screen on one key, from any app, and hides again with its shells still running. How to set it up
- Your shell, understood
- Jump between commands, copy the last command's output, and spot failed commands by their red mark. Get a notification when a long command finishes while you're elsewhere. Works in bash, zsh and fish. Shell integration
- Select and copy without the mouse
- Move over the screen and scrollback with vi keys, then select by character, line or block. Keyboard select mode
- Plays well with your tools
- CJK input methods, the kitty keyboard protocol for Neovim and Helix, mouse reporting for vim and tmux, clickable links, and colour emoji. Everything Lumen does
- A config file that applies on save
- One commented
config.toml. Change a line, save, and every open pane follows, no restart. Five themes recolour the whole window, chrome included. Config
Make it yours
Settings, scripts and plugins are all plain text. Here's one of each.
theme = "Tokyo Night"
font-family = "JetBrains Mono"
font-size = 14
background-opacity = 0.92
cursor-style = "beam"
quick-terminal-key = "f12"
notify-after = 10
plugins = ["git-branch", "pomodoro"]
[keys]
ctrl-t = "none" # back to the shell
alt-g = "plugin:git-branch:switch"
~/shop ❯ p=$(lumen msg split right --run 'npm run dev')
~/shop ❯ lumen msg tab-style --badge dev --color green
~/shop ❯ lumen msg read-screen --pane $p --lines 2
VITE v5.4 ready in 312 ms
Local: http://localhost:5173/
~/shop ❯ lumen msg watch command-finished
{"event":"command-finished","command":"npm test","exit":0}
from lumen_plugin import Plugin
app = Plugin()
@app.command("Switch Branch", keys="alt-b")
async def switch(pane):
branch = await app.pick(["main", "dev"])
if branch:
await pane.run(["git", "switch", branch])
app.run()
Try it in your next session
Copy the command for your system and paste it into a terminal. Run it again any time to update.