Every release, as it shipped.
0.25.0
LatestAdded
A font's own rules now run: ligatures, alternate letters and hiding secrets.
In a code font such as JetBrains Mono,
->,!=and===are one shape, each cell keeping its own colour, and the cursor on one opens it into its characters. Obel Mono Masked can draw API keys and tokens as dots, including a key the terminal wrapped onto a second row. Settings ▸ Font has an Options group, and the command palette the same switches, for what the selected font offers (Ligatures, Hide Secrets, its alternate letters, Slashed Zero); the choices are kept per font under[font.features."Family"], and a tag the font does not have is named in the title bar. A font with no rules, Menlo included, looks exactly as before.Eight code fonts come with bateri.
JetBrains Mono, Fira Code, Cascadia Code, Monaspace Neon, Geist Mono, Maple Mono, IBM Plex Mono and Obel Mono are in the Font list in Settings and the command palette, and
family = "Fira Code"works on a Mac that has never had it installed. They are loaded for bateri alone, so they do not appear in Font Book or in any other app, and a copy you installed yourself comes first. They add 9.3 MB to the app. Each font's license is in the app next to its files, and the About window andTHIRD-PARTY-LICENSES.txtcredit them.Icons in your prompt are drawn in any font.
The git branch, a folder and the arrows of a powerline prompt came out as empty boxes unless the font was a Nerd Font. bateri now draws them from a Symbols Nerd Font that comes with it, in one cell, whichever font you use; a font that has the icons itself keeps its own.
A switch for heavier text.
With
smoothing = trueunder[font], or Bolder text in Settings ▸ Font and Bolder Text in the command palette, text is drawn the way macOS thickens it in Terminal.app, where the default is the font's own thinner weight. It is off unless you turn it on, it needs no restart, and it is macOS only.A program's view is set in your font.
The web page a program shows in a pane used SF Mono or Menlo whatever
familysaid, and a font that comes with bateri, one you never installed, fell back to SF Mono there while the terminal showed it. The page now gets your family, JetBrains Mono when you chose none, and changes with it when you save. In a page Fira Code's italic is slanted by the web engine, where the terminal draws it upright.
Changed
bateri starts in JetBrains Mono.
If you never chose a font, text is now drawn in JetBrains Mono, with its ligatures (
->,!=,===), where it used to be SF Mono or Menlo. Choose Menlo in Settings or writefamily = "Menlo"to go back; a font you chose stays as it was.Lists and text in a program's view stop at their ends
, as the terminal's history does, so a file tree or an editor no longer bounces past its end and squeezes its scroll bar. To have them bounce as macOS's own windows do, turn on Bounce at the Ends (
[motion] scroll_bounce = "on").The Settings window is organised by page.
Nine pages in a sidebar (General, Appearance, Font, Tabs and Panes, Cursor, Motion, Shell, Keyboard, Servers) replace the six, and each row has a name, a line saying what the current value does, and its control. Choices that change how something looks are pictures in your theme's colours, the Font list is sectioned, themes are a gallery of cards each drawn in its own colours, a search field finds any row, and a row that depends on another setting stays in place, dimmed, with the reason. Five pages open with an example drawn by the terminal's own renderer, as a small window with its name in a title strip, which stays at the top while the page's rows scroll under it, and the cursor's options are drawn by it too, so a theme, a font option or a cursor shape shows as it will look; the window itself is drawn in your theme's colours, its light or dark included, and the Font page shows a font's alternate letters as tiles, each before and after. A settings file that cannot be read shows a strip with Open settings.toml.
Fixed
The command palette's font list shows only the monospaced families this Mac has, so choosing one no longer ends in
font "JetBrains Mono" not found.A monospaced font that macOS does not flag as one, such as Obel Mono, is in the Settings font list and the palette's, and no longer gets the
is not monospacedwarning in the title bar.A program with a lot of output keeps what bateri knows about it through later updates of kablo: its folder, its blocks and that a command is running. The first update to this version cannot do that yet, and 0.24.1's check covers it.
The number of tabs on a closed group in the sidebar is no longer cut off on its left.
The
+on a group's header says New Tab in Group when you point at it, not Close group.
0.24.1
Fixed
A tab of this computer no longer shows up as a server, with a dot and another name (
zsh MacBookPro). A computer's name can follow the network it is on, and bateri took the old name in a shell's title for another computer. Only a real connection says a pane is on a server now.A program that ran through an update no longer gets a dock over it when its window comes back. When a program had printed so much that the start of its output was gone, the new kablo could not tell a command was running, and bateri took the pane for a shell waiting at its prompt. It now asks the system what is in front of the terminal.
0.24.0
Before you update
bateri newis gone, and a terminal's name isp9, nott9.A program that ran
bateri newopens a tab (bateri tab, which does not take the keyboard) or a pane (bateri split) instead; the terminals it started before this update keep their old names and still run, but cannot be named in a command. Scripts that readbateri lsshould read theid:it prints.The question "close this?" is gone.
What the
batericommand may do is a level for each machine now,ownby default: see[commands]in the settings file. Raise it where you want an agent to see or close more.The saved window layout remembers the numbers of windows, groups and tabs.
An older bateri cannot read a layout this version saved; your programs keep running in kablo.
Added
The
batericommand on this computer, too.A program in a local pane can open and drive panes, tabs, groups and windows the way it does on a server, and
bateri ls,focus,close,send,captureandwaitwork on it.Windows, groups and tabs have numbers you can type
(
w1,g1,t3, andp9for a pane);bateri lsshows them with the labels and titles. New commands:bateri tab,window,focus,zoom,swap,move,resize,renameandclose tab|group|window.A pane for a shell or for a program.
bateri splitopens your shell.bateri split -- zsh(alsofish, andbash4.4 or newer) opens that shell, with its dock and thebatericommand in it, and it comes back as that shell after a restart. Anything else, likebateri split -- makeor-- sh, is a program: no dock, and the pane goes with it.bateri movemakes tabs and groups.bateri move pane p9 --new-tab webmakes a tab of a pane and prints it;--group g1,--new-group apiand--window w1say where.move pane p9 --tab t3puts a pane in a tab,move tab t3 --new-group apimakes a group for a tab, and--jsonon anymovesays where it now stands.Four levels for the command, per machine:
off,own(this machine's own panes),screen(everything bateri has open) andfull(also start terminals on other machines and type into or read them). Set it in Settings,[commands] levelfor this computer andcommands = …in a[remote] hostsentry for a server.fullis never given to a pattern likeprod-*, only to a host's exact name.A command cannot move the keyboard from where you are typing.
A
focus,zoom,swap,moveorresizethat would change where your keys go only works when it is run from the pane you are typing in.Other machines.
bateri split -S prod -- make teststarts the terminal on a server, andp9@prodnames a pane of another machine (this computer isp3@local) insend,send-key,capture,wait,focus,zoom,swap,move,resizeandclose. A server you gavefullcan do the same to your other machines and to this computer (-S @local): bateri runs the command for it, which is whyfullon a server is a decision about your other machines too.
Changed
The
batericommand is kablo's now, the same program on this computer and on every server.It was a long shell script that each machine ran for itself; it is now
kablo bateri(the filebaterion yourPATHonly starts it), and bateri on your computer tells it where it runs. A terminal an agent opens on a server is started the same way as on this computer, a number is still never given twice, and a server is set up with the new kablo the first time a program reaches it.What bateri does on a server goes over the one connection kablo keeps to it.
Previews and listings, the load indicator, files dropped on a server pane and downloads, open ports, and what a program on a server asks of your other machines (
bateri split -S prod,bateri send p9@prod) each started ansshof their own. They share the terminal's connection now: no second login, no second password question, andsshis started only to sign in and to put kablo on a server.A server whose administrator forbids forwarding opens no port
, and bateri says why when you try; the file is
/etc/kablo/no-forwarding. To know that before the browser opens, clicking a port this computer cannot reach connects to it once, so a listener that takes a single connection (nc -l) spends it there.bateri capture p9@prodthat prints more than 4 MiB ends with an error that says so, as it already did for a program on a server. What bateri runs on another machine for a program on a server (
bateri wait p9@prod) lasts as long as the job and ends with the program that asked: no hour limit, and nothing is left running on the server when you press ^C.A program that prints a lot reaches the screen faster.
Text, colored output and wide characters cost less on the way from a program to the window.
A program's view scrolls more smoothly.
A picture a program draws is no longer drawn again with every frame, and text with thousands of colored words takes no longer to draw far down than at the top.
A shell's name instead of
user@host:dir.A pane's header says
zsh, the tab's row sayszsh bateri-termwith the folder a step quieter, and the dock's folder row writes your home as~.Tabs have a new look.
Rows are a little taller, their corners and their icons' follow a softer curve, the selected tab has a light edge and a soft shadow, and the buttons at the top of the column are larger and finer. The close button and a group's
+have no ground of their own.A running tab's line has a fading tail and keeps one pace
, however long the command has run.
[appearance] tab_running("Running tab") also offers the same line over a faint ring, or a whole line that breathes.⇄is gone.A server's name now says it is a server by its color:
zsh prodin the tab's row,prod /srv/appin the dock, as it stands in Show All Tabs. A program running on a server has a dot on its icon's corner, and the server's name in the row's tooltip. The icon of a remote session is a globe.
Fixed
bateri splitwith no program, run where the bateri app does not answer (a terminal that belongs to no pane of this computer, a plain ssh shell), is an error now: it used to open a terminal nobody could see.bateri split -S @localfrom a program on a server, with no program to run, is an error that says to name one.The line round a running tab no longer whips backward at the end of every turn.
A tab title about as wide as its room no longer shakes and flickers at its fade. Every title in the tab list also starts at the same place now, whether it fits or not.
A program's view on a server comes back by itself after the connection drops, as when the computer sleeps. It used to leave an empty pane with the program still running behind it, until you quit the program and started it again.
If the program ended while the connection was gone, its view closes and nothing is typed at the prompt that took its place.
After the computer sleeps and wakes, a server terminal is no longer reported as opened on this same computer, with its keys dead until you brought it back.
Ctrl-C pressed while a program on a server prints faster than the connection carries now reaches the program. It could be lost, and the program went on. What was already on its way still shows first, so on a slow connection the prompt can take seconds to come back.
0.23.0
Before you update
This update ends the programs in your local tabs, once.
A tab's shell now runs in a terminal kablo keeps on this Mac, and the helpers the previous bateri kept programs in cannot hand them over. Windows, tabs and splits come back from the saved session (not under
restore_windows = "off") as new shells with their history; tabs on a server come back with their programs. From now on an update, a crash and ⌘Q underkeep_running = "quit"leave programs running, and the next bateri shows them where they were. Whatkeep_runningdecides has not changed. Where kablo cannot be had, a tab opens as a plain terminal, which does not survive an update or a crash and asks before it closes.Programs with a web view written for the previous draft have to be updated.
MCP is gone: a web view speaks pencere's one protocol, the same messages as a view bateri draws itself.
Added
All your tabs at once.
Show All Tabs (⇧⌘\) covers the window with a picture of every tab's real screens. Search them by name, program and folder, go with the arrows or the pointer and ↵. The window's machines stand beside them with each server's load, its background terminals are listed with their pictures, and a terminal another computer has open moves here with ↵.
Activity: what your agents are doing.
Show Activity (⇧⌘A, or the eye at the head of the side column) lists every program that reports its state, as Claude Code does: its work, what it is doing and for how long, and what it asks while it waits for you. ⌘1–9 count agents while it shows.
The side column counts what waits for you, and can hide.
Its end says how many tabs ask, failed or finished while you were elsewhere; click a count to go to the one that waited longest. View ▸ Hide Sidebar (⌃⌘S) leaves one row over your panes, and each window keeps its choice.
Tab details.
[appearance] tab_detailssays beside a row's name where its program stands and what an agent asks:"smart"(the default) in Activity only,"always", or"off".A focus frame.
[appearance] focus_frame(off by default) draws a line in the theme's accent round the focused pane of a split tab.Every pane has a header.
The program's mark and the pane's title, with Split Right, Split Down, Open in New Tab and Close Split under the pointer. Click it to give the pane the keyboard.
Carry panes and tabs with no key held.
Drag a pane by its header to another pane, onto a tab, between two tabs or out of the window. Drag a tab into the panes on screen, or onto another tab to join it. Undo Move (⌘Z) puts it back.
The line you type on a server is in the dock.
In a terminal the server keeps, in zsh, bash and fish, you click, select, edit and paste in it as you do locally.
A program's notification reaches you.
OSC 9andOSC 777;notifymark the tab unless you are looking at it, and come as a macOS notification while bateri is in the background.Programs can show a view bateri draws itself.
Beside the web view, a program that speaks [pencere](https://github.com/bateri/pencere) can open a native view: a Lua script in a sandbox with no files, network or clock of its own, drawn in your font and theme and as large as your text (⌘+, ⌘−). It can hold code editors (carets, find, folding, your input method), menus, dialogs, charts and pictures, and take files you drop, paste or choose. VoiceOver reads it, its commands are in View ▸ Page Commands ▸ and the palette, a link it opens asks you first, and a tab's card shows it. A view that hangs, asks for too much memory or has an error closes, and its program is told why.
A view's files move beside the terminal, not through it.
A file you give a program's native view, or one it hands back to be saved, goes through a named pipe in a folder only you can open (
~/.cache/pencere-stage/), on this Mac and on a server whose terminal kablo keeps. A big file no longer holds the terminal, closing the view or pressing ⌃C stops the transfer, and a half-saved file is deleted. A plainsshyou started yourself is left as it was.
Changed
bateri's words over a program's view stand in the pane's header.
The strip above a view is gone: the header says where the program runs, its name and the view's title, with Quit ⌃C at its right.
Cards for every tab, on one flat ground.
Under
split_style = "cards"a tab with one pane is a card too, on a flat tone drawn from your theme instead of the coloured gradient.The title row is quieter.
Its buttons are bare until the pointer is over them, and tabs at the top read like the rows of the column.
A theme file takes its missing colours from a theme of its kind:
bateri-lightfor a light background,baterifor a dark one, and a built-in theme for a file named after it.Option-Command no longer lifts the panes.
Both of its jobs are done with no key held now.
A program's output is taken in faster,
images and Chinese, Japanese and Korean text several times so.
⌃\ and ⌃Z reach the program over a view,
as ⌃C does, of either kind.
A web view stays on the page it opened.
A link, a script or a form cannot take it to another page, and it still opens addresses in your browser after you say yes. Your answer is remembered for the program run from that place, so a second program with the same name asks again.
A view whose program stops reading is closed,
once more than 16 MiB waits for it.
A view written against another version of the interface says which,
to its program.
A launch that crashes while it brings your tabs back does not crash the next one too.
The next launch shows a picture of each screen; if that crashes as well, the one after opens a fresh window and leaves the programs running, as holding ⇧ while bateri opens does.
A terminal a tab keeps remembers as many lines as
scrollbacksays,at a cost in kablo's memory.
Fixed
A program's view can no longer take the keyboard from a pane you are typing in.
It asks only while its own pane has the keyboard; clicking the view gives it the keyboard as before.
bateri split --focustakes the keyboard only from the pane you are typing in.A program on a server could take it from wherever you were. Otherwise the new pane opens behind.
A web view cannot reach the network on its own.
A page with no
accesscould still open a WebRTC connection or have the engine connect or look up names ahead of time. bateri switches those channels off; where the engine has no switch for one, as may be on an older macOS, the view does not open and says so.A line a program prints can no longer close a view.
On your own computer the shell's "command ended" mark closes a view only once the shell has the terminal back. Over ssh it never does by itself: a program that ends normally closes its view and so does the end of the
ssh, and the view of a program that crashed stays until you press ⌃C, which takes you back to the terminal.A program cannot put a menu in front of you that pastes your clipboard.
A view's menu opens only for something you did, and its Paste line is on only in the menu a right-click opens. It shows ⌘V, and no key of the view's choosing picks it.
osc52 = "off"holds for a native view too.Only your own copy reaches the clipboard: ⌘C or ⌘X, your press, your pick of a menu line. A plain key does not, nor does a Copy button that waits for its program's answer, whatever the view then says.
"copy"lets all of it through as before.A long paste, or a file a program receives, in a terminal on a server no longer loses what it typed.
Input now goes a window at a time and waits for the server. Until the server's kablo is renewed, a flood it cannot hold ends the terminal with the server's words in it instead of stalling it.
A terminal shown again after a lot of output keeps its commands and its prompt,
marks and dock included.
A large image
kitten icatsends through ssh is shown.A server behind a
ProxyCommandstays reachable after its connection drops.The ssh bateri starts itself now has your shell's
PATH, socloudflaredortshis found, and one it gives up on no longer leaves its proxy running.Native views look right while they change.
They no longer flicker when resized, words fade all the way with their part, fields open with their text and stay in their box, and a filter field says the view's own hint.
0.22.0
Added
A program on a server can open panes and tabs in bateri, look at what is open and close what it opened.
Claude Code, Codex or a script on a server types
bateri split --below --ratio 30 -- npm run devand the program starts on the server —bateri send,captureandwaitreach it from there — and its pane appears beside the terminal that asked, in that terminal's tab or, when there is no room left, in a tab of its own next to it (bateri tabasks for one). Nothing the user was looking at moves: the keyboard stays where it was (--focustakes it), a pane that fills its tab keeps filling it (the new one waits behind), and a new tab opens beside the asker's without being selected. The pane closes when its program ends, unless--keep-openasked it to stay. When bateri is not connected the terminal starts anyway and its pane takes its place the moment bateri connects; one notification says so (“Claude opened 3 terminals on rasp”) rather than one for each.bateri lstells the program what is open — the windows, the tabs, each tab's splits as they are — and lists the server's terminals with what each is doing and who opened it;bateri closecloses what the program opened (or the terminal it runs in) at once and asks you before closing any other, and a no is a refusal it can read;bateri notify "tests failed"shows a notification when bateri is behind, or when no tab shows the program, and marks the program's tab with a tick unless you are on it. The terminals bateri itself opens on a server (⌘T, ⌘D) are numbered the same way, so the program sees them inbateri lsand can usecaptureandsendon them; terminals opened before this update keep the names they had.A program can open its own window in the pane it runs in.
A program that speaks the [pencere](https://github.com/bateri/pencere) protocol — a tool for an agent, a dashboard for a server — asks, and the pane shows a web view of its own where the terminal was, the way vim takes the screen; when the program ends the terminal is back as it was. The program may run here, behind a plain
ssh, or in a terminal a server keeps. A strip of bateri's own stays above the view and says, once each, where the program runs, which program it is and what the view shows (“⇄ rasp Docker UI Containers”, in the words the program gives itself and its tool), with one button, Quit ⌃C. When the program gives itself an icon, the strip shows it beside the program's name, and the tab wears it on its tile — in the tabs menu and on the tab's card too — instead of the mark of what runs the program (Node, Python): in the program's colours, in bateri's frame, an icon with a background of its own as the whole tile and a bare shape on the tile like bateri's own marks; the one made for a dark or a light theme as yours is. bateri never fetches an icon from the network, it draws only a small picture the program sends with its name. The program can also close its view and keep running. The view has the keyboard but for your shortcuts — ⌘T, ⌘D, ⌘W, ⌘P and the rest, as you set them in[keys]— and the commands that work on the terminal's text, which are grey meanwhile; ⌘C, ⌘V, ⌘F and ⌘Z are the view's while the keyboard is in it (⌘Z undoes a pane move again wherever it is not). The view reaches nothing on its own: a program that wants other sites, the camera or the clipboard is asked about in a sheet on the pane (the answer is kept until bateri quits, per program and tool — for anodeorpythonprogram the script it runs, so another script of the same interpreter is asked again, and a program bateri cannot tell from another, such as a plainsshor a terminal a server keeps, is asked every time — and asked once when several panes of a restored window open the same tool), and a link the view opens is asked about and opens in this Mac's browser; the question goes when its view does. A request the view passes on to the program that goes unanswered for a minute fails for the view. The view can ask the program what tools, resources and prompts it offers and is told when they change, follows a long request's progress, and can give up a request it no longer waits for (the program is told). The tab's card shows what the view shows. After an update, or when the connection to a server's terminal comes back, the program is told to open its view again and it comes back in the same pane; one that does not within half a minute loses the token it was offered. Words that reach the pane while the shell itself holds the terminal (its prompt is being drawn) are not answered into the shell's input, on macOS too.A terminal on a server shows that it is waiting when the connection is gone.
The pane keeps its last screen, veiled, with no caret, and the line at the bottom says
⇄ rasp Reconnecting… · ⏎ try now: keys are not sent (a line typed into the wait would run where nobody looks, and the system beeps), ⏎ tries again at once instead of waiting out the pause, scrolling still works, and the Mac waking up tries too. A key, an agent or a password saved in the Keychain logs in by itself; a password nobody saved (or a second factor) makes the line sayNeeds your password · ⏎ log in, and ⏎ opens one sheet for the server — whichever of its panes asked — that brings every terminal on it back. When the connection returns the pane goes on from where it was.sshto a server now opens a terminal the server keeps.Type
ssh raspas before — the password, the second factor and the question whether to trust the server's key are asked in the pane — and the pane shows a terminal that runs on the server under kablo, bateri's companion program. The firstsshto a server puts kablo there (one file under~/.local/share/kablo/, a line above the prompt says so once); after that a secondsshto the same account asks for nothing and the connection is shared. Where the connection drops, the program you left running (npm run dev, a build) is still running, and the pane goes on from the byte it was at when the connection is back, with no line shown twice. If the connection was gone so long that the server cannot replay all you missed, the pane redraws from the server's picture of the screen and keeps its scrollback: what you could scroll back to stays (a few lines may show twice there) and only the screen is redrawn. Servers kablo cannot be kept on, hosts you turned integration off for, andproductionhosts get the plainsshas before.⌘T and ⌘D in a pane that shows a terminal on a server open another one there, and closing the pane ends it.
The new tab or split opens straight on the server — no local prompt flashes and no
sshline is typed — in the folder you were in, asks for no password again, and is a server pane like the one you typedsshin (the line under it names the server, the commands are blocks, the tab shows it); when its terminal ends, the pane's own shell starts. ⌘W, a tab's ×, closing the window or a split pane ends the terminal on the server (and the question before it says what is running there: “npm on rasp” is still running), where closing used to leave it running with nobody to see it; a terminal that is still there a few seconds after it was asked to hang up is killed. Closing a pane while the connection is down cannot reach the server, and the terminal stays.A terminal on a server follows
keep_running, and comes back with bateri.The terminals kept on servers are local terminals that do not die with the connection, so what you chose for the programs here is what they get: ⌘Q ends them after the usual question (the question names “npm on rasp”), except under
"quit", where ⌘Q leaves them running and the reminder names them, and ⌥⌘Q ends them; an update never does, and a crash leaves them running unlesskeep_runningis"update", which ends them at the next launch. When bateri opens again — after an update, a crash, or the Mac restarting — each pane that showed one shows it again, from where it was, and logs in the way a lost connection is mended. A pane whose terminal is gone comes back as a shell with itssshline ready and a line saying so. A terminal that was to end while the server could not be reached is ended the next time bateri connects to it.⌘P finds the terminals a server keeps that no pane shows, and opens them.
A terminal an agent started on
rasp, one you started there withkablo new, or one a crashed bateri left running keeps running with nobody looking at it; typingclaudeorraspnow lists it under *Running in the background*, with the directory it is in and, when a program is running in it, for how long. ⏎ opens it in a new tab, ⌥⏎ beside the pane you are in (below it, or in a new tab, when there is no room), from where it was — nothing is typed and nothing starts again. A server's row says how many are waiting (“ssh config · 3 tabs · 2 in the background”) and → opens its page: *Open All in New Tab* (two side by side, three with one tall, four as a grid, up to six in a tab and the rest in the next, the one that wrote last at the top left with the keyboard), the ones running in the background, your own panes on that server with their tabs (⏎ goes there, nothing moves), and *New Tab on rasp*. The same *Open All in New Tab* is in the Shell menu, grey unless the pane you are in is on a server that keeps some. A plainsshhas none of this. When you open a new terminal on a server that keeps others running in the background, a dim line above the prompt says how many, once for the same ones.Click
⇄ raspfor the server's card.In a terminal on a server, the server's name at the left of the status bar is a click (the hand cursor says so) that opens a small card: the server's CPU and memory as a bar each and the processes using the most, and under them *Running in the background · 3* — the terminals the server keeps that no tab of this Mac shows, each with its directory and how long a program has been in front (
running 12m 00s) or since when the shell waits (idle since 09:40). A click on a row opens that terminal in a new tab, from where it was (the pointer on a row says *Open in New Tab*; ↑, ↓ and ⏎ do the same), *Open All in New Tab* in the heading opens them together, and a right click offers *End Terminal*, which asks first, in the words closing a pane does. Six rows show and “and 3 more” says the rest; an empty list says so. The dim line that tells you about the waiting terminals when you open a new one now has something to click. A plainsshhas no card and its name is only a name.Close a pane and leave what runs on the server running.
When ⌘W (or a tab's ×, or the window's red button) closes a terminal on a server with a program in front, the question has a third button between *Cancel* and *Close*: *Leave Running*. The pane goes, the terminal and the program in it stay on the server, and they wait under *Running in the background* in the server's card and in ⌘P, where a click opens them again from where they were. Closing several tabs or the window offers it for every terminal on a server among them; local panes close as they do under *Close*. Quitting bateri does not end a terminal you left running, whatever
keep_runningis, and neither does a crash — ending it is *End Terminal* on the card or opening it and closing it with *Close*. A shell waiting at its prompt closes without a question, as before.Move a terminal from one Mac to another.
A terminal on a server that is open on another of your Macs is no longer under *Running in the background* — it is under *On other Macs · 1* in the server's card and under *On other Macs* on its page in ⌘P, with that Mac's name at the right (the name you gave it in System Settings). A click on its row, or ⏎ on it in ⌘P, says *Move Here*: it opens in a new tab on this Mac, from where it was, and the pane on the other Mac goes dim, with the line at its bottom saying
⇄ rasp Opened on MacBook · ⏎ bring back. ⏎ in that dimmed pane takes the terminal back, from where the pane was, and the other Mac's pane goes dim in turn; a terminal is live on one Mac at a time, so the two never fight over the window's size. A Mac that was asleep or offline when the terminal was taken finds out when it connects again, and its pane comes back dimmed instead of joining in. Closing the dimmed pane ends nothing on the server — the terminal is the other Mac's now — and neither does quitting bateri. The terminals on other Macs are on the server's page and in its card only: typingclaudein ⌘P never takes a terminal from the Mac that is using it. When the other Mac lets go of the terminal (*Leave Running*, sleep, quitting bateri) it goes back under *Running in the background*. A server whose kablo is older cannot say who has a terminal open, so its terminals stay under *Running in the background* and open beside whoever has them, until bateri has renewed it.A tab shows the program running in a terminal on a server.
In a pane that shows a terminal the server keeps, the tab's icon follows the program the server says is in front, the way it does for a program on this Mac: Claude Code, Codex, npm, cargo, vim, htop and the rest bateri has an icon for replace the server's
⇄while they run, and the shell at its prompt, or a program with no icon (node,python3), leaves⇄as it was. A server whose kablo is older names Claude Code by its version number, which has no icon. The question closing the pane names the same program. A plainsshhas no such word and keeps⇄, and ⌘V still pastes a screenshot only into an agent on this Mac — one on a server reads the server's clipboard, not yours.A newer bateri brings its kablo to the servers without ending anything.
The kablo that bateri puts on a server is the one that came in its package; an older one that is there stays where it is, and the terminals running under it are renewed with the new one while they run — the shell, the programs in it and the panes showing them go on as they were, so
npm run devstarted last week is still there after the update. The firstsshto a server does it, and so does a pane that comes back after bateri was updated. If the server cannot be reached at that moment (no connection, a password nobody saved), the pane comes back as before and the renewal is made the next time the connection is made.Programs can ask to be told the window's size in their output.
An app that turns on in-band resize reports (DECSET 2048, as kitty and Ghostty offer it) now gets the rows, the columns and the size in pixels in one sequence whenever the pane changes size, and once when it asks, instead of only a signal it has to follow up on. The mode survives an update and a crash like the other modes, and the shell integration turns it off when a command ends, so a program that dies with it on cannot type size reports into your prompt.
Changed
sshis a terminal the server keeps or plain ssh, and plain ssh has nothing of bateri's on the server.What bateri did on a server — dropping a Finder file on the pane to upload it, downloading and previewing a file, the load indicator, the server's ports, ⌘ over a path to see whether it exists there — it now does in a terminal on a server (an
sshto a server kablo is on) and in no other. A plainssh—integrationoff for the host, aproductionhost, a server kablo cannot be kept on (a router, a machine it is not built for), a call that runs a command, mosh — is the ssh you know: no command blocks and no remote dock line on the server, none of the above, and bateri opens no connection of its own to the host. The dock and the tab still say⇄ host, and a file dropped on such a pane is refused instead of its path being typed into the server's shell. Shell ▸ Shell Integration on “{host}” brings it all back for a host, from the nextssh. A shell that was already running when bateri was updated has the previoussshfunction, whose nextsshis a plain one; a new shell (a new tab) has the new one.Sign In… is gone from a server's terminal.
The button that took the place of the load indicator when the load or a ⌘ check of a path could not log in by itself is no longer drawn. Those jobs ride on the connection the terminal's own
sshmade, so when that connection has no login the terminal says so once,Needs your password · ⏎ log in, and that is the one place to log in; until then the load stays hidden and nothing else is offered.The dock is quiet about a server that is fine, and a server is measured once.
The load indicator at the right of a server terminal's status bar now appears only when a value is past its threshold (CPU 70 %, memory 80 %, disk 85 %), in every terminal on that server at the same moment, and goes when the server is back under it; the little green dot of
stats = "alerts"is gone, andalertsis the default.stats = "sparkline"or"numbers"keeps the permanent gauge for whoever wants it. The load used to be measured once per pane; it is measured once per server, so four panes onraspcost it what one did, and a pane that opens on a server already being measured shows the numbers at once. The details moved to the server's card (above): it shows the CPU and the memory and the busiest processes, and no longer the swap, the disk, the load averages and the uptime.The command palette finds a tab by any of its server panes.
Typing a server's name in ⌘P found a tab only when the pane in focus was on that server; a split tab whose other pane is on
raspis found byrasptoo.
Fixed
An app that draws its whole screen as one picture now fills the pane to its edges.
Programs that render with the GPU and show the frame through the kitty graphics protocol (gpuix's terminal mode, for one) stood in a frame of the theme's colour, because the padding around the text only took the colours of painted cells. A picture that spans the grid from its first column to its last now lends its edge pixels to the padding beside it, and above and below when it reaches the top or the bottom row, the way a program that paints its own background already did.
A program's name leaves the tab when the program ends.
A program that names the window (vim, htop, an app drawn in the terminal) and quits or dies without putting the old name back left its name on the tab until something wrote another. The shell integration now puts back the name the tab had when the command started, before your own prompt hooks run, so a prompt that names the window itself still has the last word.
A full-screen program that dies no longer leaves the pane blank.
When a program on the alternate screen ended without giving it back — killed, crashed, or the vim behind an ssh whose connection dropped — the prompt came back on its empty page with the dock hidden, and the pane looked dead. The shell integration now gives the screen back when the command is over, so the pane shows what it showed before the program started, with your prompt. A program you stop with ⌃Z keeps its screen for
fg.A program that hands you a shell can show its view again when you leave it.
An app that steps aside for a shell of its own (an editor's “drop to a shell”) could not open its view once you came back: when that shell loaded the iTerm2 integration, or was fish, its prompt marks made bateri think your own prompt was up, and a view asked for at a prompt is ignored. Only your shell's own prompt counts now.
The selected tab no longer spreads over the tab beside it.
After a tab opened and closed in quick succession (a tab a server program asked for whose program ended at once, or ⌘T then ⌘W), the next tab to open beside the selected one without being selected — the one
bateri tabopens — showed the selected tab's background running across the new tab. A tab's background and lines now slide with the tab, however its slide is interrupted.
0.21.0
Added
⌘V pastes a screenshot into Claude Code, Codex, Gemini CLI and OpenCode.
A terminal pastes text, so an image on the clipboard did nothing until you pressed ⌃V. Now, when the clipboard holds an image and no text and one of these agents runs in the pane, ⌘V hands the agent ⌃V and it reads the image itself. Over ssh the agent runs on the server and cannot see this Mac's clipboard; it says it found no image.
Fixed
Moving the mouse after a dropped ssh no longer types
35;12;7M…into the prompt.A program that turned on mouse reporting and died without turning it off (a dropped connection, a killed full-screen program) left bateri sending every mouse move to the shell, which wrote it into the command line. When a command ends, the shell integration now turns off what it left on: mouse and focus reports and the kitty keyboard modes. The mouse selects text again at the next prompt.
A command line taller than the window no longer leaves a frozen copy in the dock.
In bash and fish the dock kept showing the line as it was when it last fit, under the line growing on the screen; the dock now steps aside while the line is taller than the window, and takes it back once it fits.
0.20.0
Added
Shortcuts are yours to change, in Settings ▸ Keyboard.
The new page lists every command of the menu bar with its shortcuts. Click a shortcut and press the new one (esc gives up, ⌫ removes it); a command with none has Add Shortcut, and a second shortcut is in the right-click menu. Search finds a command by its name or the word you would use for it, the filters show what you changed or what has no shortcut, and Find by Key finds the command a key runs. A key that is another command's asks first (Use Here), a key a program in the terminal uses (⌃R) or that types a character (⌥E) says what it would cost (Assign Anyway), and macOS's own keys and a bare letter are refused. Select Tab ▸, Select Group ▸ and the split commands are one line each: hold the modifiers you want and press a digit or an arrow. In the command palette, → on a command opens Change Shortcut…. The change takes effect at once in the menu bar, the palette, the number a tab shows while its modifiers are held and the numbers of ⌘P.
A modifier tapped twice can be a shortcut.
In Settings ▸ Keyboard tap ⇧, ⌃, ⌥ or ⌘ twice instead of pressing a key (the field says "⇧ once more…"), or write
command_palette = "shift+shift". Nothing has one until you give it. Typing a capital letter, holding ⌘ for the tab keys, a click or a scroll between the taps does not count. The menu bar cannot show it, so the command's row in Settings and its row in the command palette do; ⌃ ⌃ and ⌘ ⌘ ask first, because macOS can start Dictation on them, and fn fn is refused.Shortcuts live in a
[keys]table ofsettings.toml, by the command's fixed name:
copy_last_output = "shift+cmd+o", none ("") or two. Select Tab ▸, Select Group ▸ and the split commands take only the modifiers (select_tab = "option"makes ⌥1…⌥9 select a tab). A name no command has, or two commands on one key, is reported with its line. Edit ▸ Command History… and View ▸ Themes… are now in the menu too, so they can have a shortcut.Programs see the modifiers on arrows and the other function keys.
⇧←, ⌃→, ⌥↑, ⇧⌦, ⌃PgUp and the like reach a program in the terminal as xterm sends them, so Codex, vim, helix and fish can tell them from the plain key. At a prompt of zsh or bash 4.4+ with bateri's shell integration (
[shell] integrationother than"off") they still do what they did before, because they would type;2Dinto the line; fish 4 asks for every form and gets them, and a shell without the integration gets them as other terminals send them.Home, End and F1–F12 work.
fn+← and fn+→ (Home and End) move to the start and end of the line at the prompt and in programs; the F keys reach programs like htop and Midnight Commander. F13–F20 go as ⇧F1–⇧F8, the way xterm names them.
⌥⌦ deletes the next word
(fn+⌥⌫ on a laptop), the mirror of ⌥⌫.
⌥⏎ starts a new line without running it
in Codex, Claude Code, zsh and fish.
⇧⏎ starts a new line in Codex and Claude Code, and keys are told apart for the programs that ask.
bateri speaks the first level of the kitty keyboard protocol: a program that turns it on (Codex, Claude Code, fish 4) hears ⇧⏎ and ⌃⏎ apart from ⏎, Esc without waiting to see whether more of a sequence follows, and ⌃I, ⌃M and ⌃[ apart from ⇥, ⏎ and Esc. Programs that do not ask get every key as before.
Programs that ask to hear the focus get it.
vim, tmux and others that turn on focus events learn when the pane gains or loses the keyboard: switching windows, tabs or splits, or opening the search field.
Changed
The command palette fades out as it closes
, the way it came in and like the find panel, instead of vanishing at once. The keys and the pointer are the tab's from the moment it starts to go, so what you type or click right after ⏎ or esc is not lost. With Reduce Motion it still goes at once.
Fixed
"pane" finds every split command in the palette.
The menu calls a pane a split, and Select Split ▸ (⌥⌘ and an arrow), Resize Split ▸, Swap Split ▸ and Move Split to Previous/Next Tab were not found by the word people type.
A long run of combining marks no longer freezes the pane.
Output with a letter followed by tens of thousands of accents (a hostile file, a remote host) stalled the terminal for minutes. A cell now keeps at most 32 code points of a cluster and drops the marks past that, as other terminals do; the command line under the prompt cuts the run at the same place, so it stays aligned with the grid.
A program that opens an escape sequence and never ends it no longer grows bateri's memory without end.
Output like
printf '\eX'; cat /dev/zeroor an endless DCS, CSI or escape was held byte for byte for the update handover; bateri now keeps only what a new parser needs to pick the sequence up, and gives up an OSC past 64 MiB.A graphics query can no longer freeze a pane.
A query carrying a small compressed image that claims hundreds of megabytes of pixels is refused before anything is decoded, and each screen keeps at most 4096 images and 16384 placements, so output that repeats a placement millions of times no longer slows every frame or keeps growing memory.
Restored scrollback keeps its oldest lines when long lines had wrapped.
After an update or a crash, a pane whose history held lines wider than the window no longer silently loses the start of that history.
A cancelled or disk-full upload no longer deletes a file the server never reached.
The half-written file is removed only once the server's own tar has listed it; otherwise the result says “partial file may remain at …”. A cleanup that does not answer is given up after a few seconds instead of holding the queue.
The key that ends a composition is no longer lost.
With Korean 2-Set and a syllable pending, Return commits the syllable and runs the line, and an arrow or Tab commits it and still moves or completes, instead of needing the key a second time. An accent typed with a dead key (
^or´on a Turkish keyboard, ⌥E on a US one) works the same way: Return after it writes the accent once and runs the line, and an arrow writes it and moves.A split closing in a background tab no longer takes your keyboard.
When the focused split's shell exited (or the split was moved away) in a tab you weren't looking at, your next keystrokes went to that hidden shell. The tab you are typing in keeps the keyboard, and the background tab focuses the neighbouring split when you open it.
Security
A download whose item arrives as a link or a special file is refused.
A hostile server could send a previewed file as a link to a path of this Mac; the preview then made that path read-only (your home folder,
~/.ssh) and opened it. Only a file or a folder lands now, and the preview's seal never changes a link's target.⌘-clicking a symlink or a Finder alias no longer launches what it points to.
A
docslink or anotes.mdalias that leads to an app, or aREADME.txtthat leads to a.terminalfile, is shown in Finder instead of opened; a link to a real document or folder still opens it, and Show Folder in Finder shows an app instead of launching it.Servers behind different bastions are told apart.
A job never rides another server's connection, and a saved password goes only to the server it was saved for, never to its jump host. A password saved earlier for a server behind a jump host or a proxy command is asked for once more.
0.19.0
Added
A command palette.
⇧⌘P (View ▸ Command Palette…) opens one search field over the terminal and finds, by a few letters of each word — “spr” is Split Right, “side” is Tab Position — every command of the menus (with the shortcut, and greyed as the menu would be), every setting and theme, the tabs and groups of all windows, folders, servers, ports and the commands your open panes ran. ⏎ does it, → opens the row's menu or page, esc steps back and closes, and what you chose last comes first. A command from the history is never run for you: it is written on a prompt and waits for your own ⏎.
- Themes and settings try themselves out. A theme, and the font family and size, the line spacing, the cursor shape, the split style, the veil over a window that lost focus, where the tabs sit and the tab icons and colours, show on every window as the highlight reaches them, without touching
settings.toml; ⏎ writes the choice there (the rest of the file stays as it was) and esc puts everything back. The settings you type a number for stay in the settings window; the palette offers a list of values. - ⌘P goes to a tab. The list is in the order you looked at the tabs, with the one you just left highlighted, so ⌘P ⏎ goes back and forth between two tabs and another ⌘P goes one further. Groups are listed with their ⌃⌘ numbers (⏎ goes to the tab you were last on in the group), a tab of another window comes to the front, and → opens the menu its chip or its group header has.
- ⌘O goes to a folder. The folders your tabs have been in, newest first; type a path (
~/Pro) and it lists what is inside, ⇥ steps in. ⏎ opens a new tab there. Servers come from theHostlines of~/.ssh/configand the ones you reached: ⏎ connects in a new tab, ⌥⏎ in a split beside the pane you are in. Ports listed by the panes open in the browser. Shell ▸ Copy Folder Path and Show Folder in Finder are menu commands now. - Command History lists what the open panes ran, where and how each ended. ⏎ writes the command on the prompt of the tab in front when it is idle, and otherwise in a new tab in the command's folder; ⌥⏎ does it in a new split beside the tab; ⌘⏎ takes you to its output (Window ▸ Jump to Command… lists only those) and a row's menu copies the command or its output. A command that ran on a server is never opened in a new local tab (it would run on this Mac): it is copied. Edit ▸ Copy Last Command and Copy Last Output copy from the tab in front. When a program holds the whole screen (vim, a pager) the commands before it are still listed under a note that says so; their output can be copied from behind the program, and shows again when it closes. The palette reads only what your open panes ran — not the shell's own history file.
- The menu has Go to Tab… (⌘P), Go to Folder… (⌘O), Jump to Command…, Copy Last Command, Copy Last Output, Copy Folder Path, Show Folder in Finder and Open settings.toml.
- Themes and settings try themselves out. A theme, and the font family and size, the line spacing, the cursor shape, the split style, the veil over a window that lost focus, where the tabs sit and the tab icons and colours, show on every window as the highlight reaches them, without touching
0.18.0
Added
Tabs can be gathered into named groups.
Right-click a tab — a window's only tab too, where it is the window's title — and choose Move to New Group (or Move to Group ▸), or press ⇧⌘N for a new tab in a group of its own: in the side column the group gets a header — an arrow, its name and, with the pointer over it, a
+that opens a tab in it — and its tabs stand under it. Tabs that are in no group stay at the top of the column with no header, and a window with no group looks as it always did. A new group is named for the folder of its first tab (~ishome, a remote tab gives its host), with its name field already open. Click a header to close the group: it keeps its tab count, a dot when one of its tabs has a question, a failure or a finish you have not seen, and the tab on screen stays listed under it. Double-click a header, or right-click it, to rename the group, add a tab to it, ungroup it or close it. ⌘T opens a tab beside the one on screen, in its group; Shell ▸ New Ungrouped Tab opens one among the ungrouped tabs; ⌘1–9 count the tabs as the column lists them; ⌃⌘1–9 go to the nth group (⌃⌘9 the last), to the tab you were last on in it, and ⌃⌘0 to the ungrouped tabs; hold ⌃⌘ to see the keys on the headers. Moving a tab into or out of a group is undone with Undo Move, the groups come back with the windows when bateri restores them, and Merge All Windows brings every group along under its own name. The name you type in the field a new group opens with is part of the move — Undo Move still takes the move back — while renaming a group later is not. With the tabs in the title row the bar shows one group at a time: a button at its start names the group on screen (the ungrouped tabs have the stack alone), with a dot on its corner while another group has a question, a failure or a finish you have not seen. Click it to list the window's groups — choose one to go to it, or New Group — double-click it to rename the group, right-click it to ungroup or close it. Moving the tab on screen into another group leaves the window where it is, on the group's next tab. In the side column ⇧-click picks the rows from the tab on screen to the one you click and ⌘-click adds a row or takes it out, within one group (or among the ungrouped tabs) — the tab on screen stays where it is, and a plain click, a click on a row of another group or a click in the terminal lets the picks go. Right-click a picked row to move all of them into a group or a new one, out of their group, to a window of their own, or to close them; ⌘W closes the picked tabs and, unlike ⌘W on one tab, always asks first (confirm_close = "never"still does not). Tabs and groups can be dragged. In the side column a row slides as it always did, and the rows make room where it would stand: among the rows of a group, among the ungrouped tabs, or at a group's border — over the upper half of a header the gap opens above it, at the end of the group above, over the lower half under it, at the head of the group — and onto a closed group's header it joins that group; out of the window it becomes a window of its own (ungrouped), and over another window's column or title row it lands in the group it is let go on. The rows you picked are drawn as a stack with their count and carried to a line that marks the place the same way. A group's header carries the group: between two groups to put them in order (the ungrouped tabs stay first), out of the window for a window of its own under the group's name, or onto another window, where it comes up under that name (2when that window has a group of it already); in the title row the group's button is pulled out of the bar for the same, and in the list under it a group's row is carried to the line between two groups. A click on a header still opens and closes it, and every drag is undone with Undo Move. A tab's name in the title row or the side column, and a group button's name, no longer ends in "…" when it does not fit: its last stretch fades out, and the whole name is in the tooltip. Group headers and the lists keep their "…".
0.17.0
Added
The side column can be made wider or narrower.
With the tabs at the side, drag the column's right edge — the pointer turns into a resize cursor over the space between the rows and the content — anywhere from 136 to 400 pt; the terminal reflows as it moves, as it does while the window is resized, and with
resize_in_stepson the column moves a cell at a time so a lone pane keeps whole cells. A double click on the edge brings it back to 200 pt. In a narrow window the column gives way before the panes do, leaving them at least 300 pt, and widens again with the window. Each window keeps its own width: a new window, or one a tab is torn off into, starts as wide as the window it came from, and the width comes back when bateri restores its windows.The dock shows the Python environment you activated, and the Node version in a Node project.
The dock draws the prompt itself, so the
(.venv)thatactivateputs in front of a prompt used to be lost; the dock's bottom line now starts with it, asactivateprints it and in the line's brightest tone, with its Python version:(.venv) 3.12 ~/api | main. conda's environment shows the same way,(base)too when conda shows it in your prompt. In a folder with apackage.json,.nvmrcor.node-version(here or above, up to the repository's root) the Node version that runs follows the branch,node 22.11, and turns yellow with what is asked beside it when the project's.nvmrcor.node-versionasks for another (node 18.20 (.nvmrc 22)). bateri reads where Node is installed and never runs it; a shim that picks the version per folder (volta, asdf's) shows none. On a narrow line the path shortens first, then the Node version goes, then the Python version, and the environment's name goes last. Turn either off withpython_envornode_versionunder[shell], or in the settings window's General page.
Changed
A tab with one pane has the same summary card as a split one.
Its pane is a tile like each pane of a split tab: its program's mark, its name and what it is doing over its picture, outlined as the focused pane. The card's lines are a split tab's too — the title, the folder and a marked host — so "Running · npm run dev · 0:12" is now the tile's "Running".
Fixed
The line between the side column and a tab with one pane comes back.
In a window that opened on a split tab — reopened by bateri at launch — the thin line beside the column stayed away when a tab with one pane was shown.
Only the focused pane's cursor looks focused when a window opens with several panes.
A window restored at launch drew a filled, blinking cursor in every pane of its split tab, as if each had the keyboard, until you clicked into each one; the others now show the hollow cursor from the start.
Resizing a window with a split tab keeps up with the pointer.
Every step of a resize — the window's edge or the line between two panes — drew the shadows under the panes again, which took about 55 ms on a Retina display and held the resize to a handful of steps a second. The shadows are now drawn once and stretched to each pane, and look the same.
0.16.0
Added
Tabs can stand in a column down the window's left edge.
Choose View ▸ Tabs ▸ Side (or Tabs in the settings window,
tab_position = "side"in the file) and the tabs move, in every window at once, into a 200 pt column as tall as the window: the title row goes and the traffic lights sit at the column's head. A row is a tab's chip stood upright, with its icon, title, indicator, ⌘1–9 number, × and summary card, which opens to the right of the row; New Tab is at the foot with the ⚠ of a settings problem beside it, and a long list scrolls and fades at its ends. Drag a row to reorder it, out of the column to tear it off into a window, or onto another window's column or bar; carry a pane with ⌥⌘ onto a row to join that tab, or between two rows to open a new one. A tab with one pane is set off from the column by a thin line; a split tab's cards and the column stand on the same ground, and the first card keeps its 8 pt from the column. The window moves by the column's empty space. Tabs along the top stay the default and look as they did;content_edge = "line"draws no line along the window's top with the tabs at the side.A tab's summary card shows its panes.
Hovering over a tab shows a small picture of what its pane shows right now — the grid, the history above it, the dock, a program on the alternate screen like vim or htop as it looks in the pane — under the lines its card has always had. A tab that holds several panes shows each pane where it sits in the tab, with its program's mark, its name and what it is doing over its picture, the focused one outlined, in place of "N panes". The pictures are taken when the card opens and twice a second while it stays open, and only then; panes in tabs that are not shown give theirs too. A press on a pane selects the tab and focuses that pane, and the tab's icon follows to that pane's program; a press on the picture of a tab with one pane shows that tab. The card waits a moment as the pointer crosses from the tab to the card, so it does not close on the way.
Changed
A transfer fills its tab.
The tab's own ground fills from the left as an upload goes, at an even pace between reports, instead of a line under the tab that stepped and vanished. When it ends the fill runs to the end and fades and a tick (or, if it failed, a dot) stays on the tab until you look at it, so a transfer that finishes in a background tab is no longer missed.
Badges and the running line move.
A question, tick, dot or arrow on a tab's icon grows onto the tile's corner and shrinks away, one badge turning into another keeps its circle, and the line round a running tile fades in and out. A tick or a dot rests for a moment after you look at the tab, then goes. With Reduce Motion on they only fade.
A tab's summary card eases in from the tab
and fades out, instead of appearing and vanishing at once.
An
sshsession on another port shows its port.When the port is given on the command line (
ssh -p 2222 host,-o Port=2222or anssh://host:2222address), the context line, the window and tab title, the reconnect prompt and the transfer line read⇄ 10.0.0.5:2222instead of⇄ 10.0.0.5, so two sessions on the same machine,localhost:2222andlocalhost:2223, are no longer the same label. Marks, saved passwords and Shell Integration still go by the host alone; aPortset only in~/.ssh/configis not shown, nor is port 22 or a mosh session's.
Fixed
The input source balloon appears at the cursor.
Pressing fn (🌐) or switching keyboard layouts showed macOS's input source indicator in the pane's top-left corner, far from where you type; it now opens at the cursor, in the prompt and in programs that hide the cursor to draw their own.
0.15.0
Added
Programs can show images.
Anything that speaks the kitty graphics protocol draws in the window:
kitten icat,chafa --format=kitty,timg -p kitty, yazi's previews and terminal-browser. An image sits in the cells where the program put it, scrolls with the text around it (and back into view when you scroll up), stays under or over the text as the program asked, and goes when the program deletes it or you clear the screen. A program that asks for it also gets the pointer's exact position, not just the cell, so a click on a small button in a page lands on it. A program can hand a picture over through a file or shared memory, so big images and pages that redraw often need not pass through the terminal's input; bateri reads only ordinary files (never/dev,/procor/sys), deletes only a temporary file named for the purpose, removes the shared memory object the program hands over, and never writes a name a program gave back into its answers. In an interactivesshormoshsession the names a program sends are not read (they would be the server's files), so a program there sends the picture itself. A program that asks what the terminal can draw and then for its attributes (terminal-browser does) hears the answers in the order it asked. Images do not survive an update or a crash of bateri; the text does, and a program that redraws when its window is signalled draws its images again.Programs can change the mouse pointer.
A program that asks for a pointer shape (OSC 22) gets it while the pointer is over its text: the hand over a link in terminal-browser, a text beam over a field, a crosshair, a resize arrow. The shape belongs to the screen the program drew it on, so the arrow comes back when a full-screen program exits, and again when your shell's prompt returns after a program left a shape behind. The dock, the scroll bar and a link under ⌘ keep their own pointers. A shape a program asks for while the mouse is still shows as soon as the mouse moves.
bash gets the command blocks and the dock.
When your login shell is bash 4.4 or newer, the stripe beside each command, the duration of a long one and the directory you are in show, the
sshintegration reaches servers from bash too, and the line you type moves to the dock at the bottom of the window while bateri draws the prompt, as it does for zsh and fish. Clicking in the dock moves the caret there, and selecting text and typing over it replaces it. To keep your ownPS1, set[shell] integration = "blocks": the blocks stay and the dock goes. bateri starts bash as a login shell, sologout,~/.bash_logoutand your history work as before, and nothing is written to your bash files. macOS's own/bin/bashis version 3.2 and stays exactly as it was; install a newer one (for examplebrew install bash) to get this.fish gets the dock.
When fish is your login shell, the line you type now moves to the dock at the bottom of the window, in fish's own colors with its gray suggestion, and bateri draws the prompt, as it does for zsh. The stripe beside each command, the duration of a long one and the directory you are in come with it, and the
sshintegration reaches servers from fish too. Nothing is written to your fish files. To keep your own fish prompt, set[shell] integration = "blocks": the command blocks stay and the dock goes. With fish 4.1 or newer, clicking in the dock moves the caret there, as it does in zsh; selecting text in the dock and typing over it does not work in fish yet.Resize in steps.
A new setting, Resize in steps (
[appearance] resize_in_steps, off by default), resizes a window a whole cell at a time while you drag its edge, as Terminal does: a tab with one pane then keeps exactly the same margin on both sides and the thinnest strip at its top, and the window snaps to that size as soon as you turn it on. Split tabs, full screen, windows macOS tiles or fills, and the moment after ⌘+ or ⌘− keep resizing freely until the next drag.
Changed
The text keeps the same margins as the dock, on every side.
The right edge of the text used to run almost to the window's edge, a few points from it and a different amount at every width, while the dock's own text stopped well inside; now the text stops where the dock's text does, and whatever the width leaves under a column stays inside that margin. The bottom row also keeps the dock's breathing room above the dock instead of touching it, and where the dock steps aside — Claude Code and other programs that read the keyboard themselves, full-screen programs such as vim or htop, vim on a server over ssh — the last row now stands that same margin above the window's bottom or the status bar's line, so the window's rounded corner no longer clips the last column. Programs that paint their own background still reach the window's edges. The cost is a column or two and sometimes a row fewer in the same window.
Fixed
A full-screen program's row no longer slips one column to the left.
When a program's output arrived split in the middle of a character such as
·,ğor│, the character or space right after it could be lost, so the rest of that row was drawn one column too far left — in htop, a game or a program's own frame, the right border of a single row stepped in, and it stayed that way until the program redrew the row. Text shown in the usual way could lose a letter the same way. It depended on how the output happened to be split, so it came and went with the window's size and the moment.fish on a server keeps its own directories.
Over ssh, a server whose fish had no
XDG_DATA_DIRSof its own lost/usr/local/shareand/usr/sharefrom its search paths for the session, so completions and functions installed there went missing; they stay now.
0.14.0
Changed
A new tab from an ssh tab opens in the same remote folder.
⌘T (and the tab bar's
+, and a split) on a tab connected over ssh already connected the new tab to the same host; it now also lands in the folder that tab was in — the one its dock shows — instead of your home folder there. This works on hosts where bateri's remote integration is on. If the folder is gone by then, the new tab starts at home as before, and a latersshyou type in that tab starts at home as usual.
Fixed
Tabs keep their program icons when bateri reopens.
After bateri was quit, updated or crashed with programs left running, the tabs it took back showed the terminal icon (or the server's, over ssh) instead of the program's: the command you typed had long scrolled away, and bateri often recognized the program only from it. Now each tab carries the icon it showed over to the reopened bateri, which keeps it for as long as that program runs. Claude Code is also recognized again in a reopened tab on its own: its installer starts it from a file named after its version, and bateri now reads the name it was started by as well.
0.13.0
Changed
The dock stands a step above the text.
The line over the input row is gone: the dock is now a raised plate, a shade lighter than the terminal, with a soft shadow falling on the last lines of output and a lit edge. The shadow lies under the text, so nothing you read gets darker. On a pure black theme, where a shadow cannot show, the lit edge carries it. When the edge has something to say it still says it: over ssh and under a program's guide bar it is a line in the host's or the bar's color, with no shadow on the line you are typing just above it, and an upload's progress fills along it and glows. While a new tab's shell starts, the rippling line now has the input row's color under it.
0.12.0
Added
24 well-known themes, built in.
View ▸ Theme ▸ and the settings window now list Catppuccin (Frappé, Latte, Macchiato, Mocha), Dracula, Everforest, Flexoki, GitHub, Gruvbox, Kanagawa Wave, Night Owl, Nord, One Dark, Rosé Pine (with Dawn and Moon), Solarized and Tokyo Night (with Day), dark and light ones in their own groups. Each keeps its authors' colors exactly; what bateri needs beyond them — the selection, the search highlights, the dim text — is drawn from the same palette, so a theme looks like itself and everything on it stays readable. Pick one from the menu, or write its name in
[appearance] theme(theme = "catppuccin-mocha");light_themeanddark_themetake them too.Ultraviolet, a new theme of bateri's own.
Vivid colors on a deep violet ground, with an amber cursor; every color reads clearly on it, comments included.
A tab tells which program runs in it.
Before its title a tab now draws a small icon: the mark of the coding agent in it (Claude Code, Codex, OpenCode, Antigravity, Gemini CLI, Pi, Herdr, Cursor CLI, Copilot CLI, Qwen Code, Kimi CLI), or a drawing for what else a pane spends its time in — the shell, an ssh session's server, an editor, a language prompt, a database, a container, a system monitor, git, a build or test run, a pager, a file manager, a root shell. The mark stands on a tile, like an application's icon; while a command runs a line runs round the tile's edge, and a question, a finished command, a failure or a transfer sits on its corner. A tab split into panes shows a deck: the focused pane's program on the front tile and a smaller tile behind it for each other pane, the front ones turned a little, like cards laid down by hand. A command that ends while you look at another tab leaves its icon with the tick or the dot until you come back, so you can read what finished.
Turn tab icons off, or give them brand colors.
Settings ▸ Appearance ▸ Tab icons (
tab_icons) turns the icons off and brings back the small indicator tabs had before. Icon colors (tab_icon_colors) lets Claude Code, Antigravity, Gemini CLI and Qwen Code keep their own brand colors on their tiles instead of the theme's. Show All Tabs lists each tab with its icon too. A change applies at once.
Changed
Text stays clear of the window's rounded corner.
On macOS 26 the bottom corners of a window are generously round, and the folder line and the prompt sat right against the curve. The left margin now follows the corner, so the first letter keeps the same distance from the curve as from the straight edge — in a window, in a card of a split tab and beside a window corner in a lined split. Full screen, whose corners are square, keeps the margin it had.
The ports and buttons on the folder line stay put at the right edge.
The listening ports, the load indicator and the upload buttons used to end anywhere between the window's right edge and a few points short of it, depending on the window's width, and they hugged the rounded corner just as the path did on the left. They now end the same distance from the right edge as the text starts from the left one, at every width; the path keeps its place beside the prompt's ›, and a click or hover lands on what is drawn.
The folder row has a tone of its own.
The line between the input row and the row with the folder, branch, ports and buttons is gone; the folder row now stands on a slightly lighter (on a light theme, darker) ground than the input above it, running to the window's bottom edge, and the two rows read as two surfaces without a rule. On a remote session, where the dock is only that row, the whole dock takes the tone. A new tab brings the tone in from the left, the way the line used to be drawn.
The dock's line is a point thick.
The line above the input row was a single pixel, which looked faint on a Retina display; it now keeps the same weight at every scale.
The running ring in a tab now turns smoothly.
It used to jump a twelfth of a turn every second, which read as stuttering; it now goes round at an even pace (twelve seconds a turn, twelve minutes once a command has run for an hour), and picks up at the right angle when a minimized or hidden window comes back. It still stands still under Reduce Motion.
Fixed
Text inside a search match stays readable.
The highlight of a match (⌘F) used to leave the text on it in its own color, so a theme whose highlight was close to a text color could hide the very word you searched for. Text inside a match is now held to the minimum contrast against the highlight, the way selected text already is against the selection.
An ssh prompt no longer sits on the dock's line.
On a remote session the dock is only the folder row, and the screen came down to fill the room the input row left — all the way, so the remote prompt and its cursor touched the line above the dock. The screen now stops the dock's own margin short of that line, the same space that lies below it, and gives up no row for it.
Letters no longer turn into boxes after a long session.
A tab that had shown many different characters — hours of Chinese, Japanese or Korean text, say — could start drawing every character it met for the first time as an empty box, and kept doing so until the font size changed or bateri was restarted. When the tab runs out of room for new characters it now makes room and draws the screen again, so every character keeps its shape.
0.11.0
Added
Move a split anywhere with Option-Command.
Hold Option-Command for a moment and the panes of the tab lift, each with a small bar on top. Grab the bar — or, with the keys held, any point of a pane — and drop it beside another pane, on any side of it, or in its middle to swap the two; along the window's edge it becomes a full-height column or a full-width row. Before you let go, the place it would take is painted with its name (Left, Right, Above, Below, Swap). If it does not fit, room is made by shrinking the panes around it, none below 20 columns by 5 rows; a place that is still too small says so and shows the edges where it would fit. Esc puts it back. The bar also splits the pane right or down, opens it in a tab of its own and closes it.
Across tabs and windows.
Drop a pane on another tab's chip to add it to that tab, or hold it over the chip for a moment to open the tab and place it yourself. Drop it between two chips to make it a tab of its own. Drag it out of the window and it opens in a new window where you let go; drop it on another bateri window's panes or tabs and it moves there. The program in the pane keeps running — a build, vim, an ssh session — and is resized once, when it lands.
Pull a tab into the one in front.
With Option-Command held, drag a tab's chip down onto the open panes: the whole tab comes in as splits and keeps its own layout. Without the keys, dragging a chip down still opens it in a new window. A tab's right-click menu does the same with Merge into Current Tab ▸ Split Right / Split Down.
From the menu and the keyboard.
Window ▸ Swap Split (Shift-Option-Command-arrow), Move Split to New Tab, Move Split to Tab ▸, Move Split to New Window, and Move Split to Previous / Next Tab (Shift-Option-Command-[ and ]).
Undo Move.
Edit ▸ Undo Move (Command-Z) takes back the last move, swap, merge or split-off, and a tab name lost in a merge comes back with it.
A tab says what the program in it is doing.
Programs that report their status (the
OSC 7501protocol, which Claude Code speaks) now drive the tab's chip: the ring turns only while the program works and stands still while it waits for you, a question mark shows on a tab you are not looking at when the program is blocked on you — a permission, a question — and a green tick or red dot waits for you when it finishes or fails. Before, the ring turned for as long as the program was open. Progress bars printed withOSC 9;4(cargo, zig) turn the ring the same way, until a program starts reporting its own status. Works over ssh too.A choice of how split tabs look.
Settings ▸ Appearance ▸ Split style (
[appearance] split_style) keeps the new cards by default; "Lines" lets the panes touch with a one-pixel line between them, square corners and the plain background — the most room for text, as before this release.
Changed
Split tabs are cards.
Two or more panes in a tab now stand as cards on a ground of their own: a soft gradient drawn from your theme's accent and cursor colors, a gap round and between the cards, corners rounded to match the window's. No line draws them — each card's top edge catches a light, a dark theme's card has a faint sheen under its top, and its shadow is tucked under its foot. The focused card stands nearer, with a deeper shadow and, on a dark theme, a warm light. Panes without the focus are no longer dimmed, so every pane reads at once; Settings ▸ Appearance ▸ Dim unfocused splits (
[appearance] dim_unfocused_splits) brings the veil back. Going from one pane to two and back slides them into place, at once with Reduce Motion. A tab with one pane looks as it always has.Full-screen programs reach the pane's edges.
btop, vim and other programs that paint their own background now fill the margin round the text too, instead of standing in a frame of the theme's color that was a different width on every side. Your shell's own lines look as before.
0.10.0
Added
The ports your programs listen on, in the dock.
Start a dev server —
npm run dev,rails s,python -m http.server— and its port shows at the right of the dock's bottom line:↗ :3000. Every program started in the tab counts, not only the one in front: a job sent to the background, a server's worker that does the listening. Click the ports to list them with the program behind each; choose one to open it in your browser, or hold Option to copy its address. Command-click a port to open it at once. Shell ▸ Open Port lists the same ports, also while vim or an agent covers the dock. Turn it off in Settings ▸ General ▸ Show listening ports ([shell] portsinsettings.toml).The server's ports too, over ssh.
In an ssh session with the shell integration on, the ports that the programs you start on the server listen on show beside this Mac's. A port this Mac reaches as it is shows green and opens directly. One that listens only on the server itself — a dev server's usual
127.0.0.1— shows dim, and opening it forwards it through your ssh connection to the same port here first. The forward ends with the ssh session.
Fixed
The load indicator holds still.
In an ssh session the indicator moved sideways whenever a
cpuormemnumber gained or lost a digit (9%→10%). Each number now has a column of its own, so the line moves only when a value turns critical.Text stays readable on a light theme.
A program set up for a dark terminal printed its text white, which vanished on
bateri-lightandlinen; the light themes' own white and dim colors read poorly too. Text a program colors too close to its background is now drawn darker or lighter until it reaches a 3:1 contrast. Only the text changes: backgrounds a program paints keep their color, and box, block and Powerline characters are left as they are. Choose how strict it is, or turn it off, in Settings ▸ Appearance ▸ Minimum contrast ([appearance] minimum_contrastinsettings.toml).
0.9.0
Added
A new tab's dock now arrives instead of popping in.
Until the shell gives its first prompt the dock holds back its folder, branch, prompt mark and cursor, and when the prompt comes it arrives in one of three ways — pick it in Settings ▸ Motion ▸ Dock arrival (
[motion] dock_arrivalinsettings.toml).ripple(the default): the dock's top line ripples faintly while the shell starts, the prompt mark drops onto it and a ring spreads from where it lands.dust: specks of dust drift around the dock, then are drawn left to right onto the top line, which is woven behind them.type: the dock rises a little, its lines are drawn from the left and the folder and branch type themselves out.offkeeps today's dock. Nothing moves for the first moment, so a quick shell never flickers; a shell that takes longer than three seconds gets the arrival anyway; pressing a key, or leaving the window or tab, ends it at once; Reduce Motion turns it into a short fade and the cursor motion settingsnapturns it off.
Changed
No spinning ring beside full-screen programs.
vim, less, htop or an agent like Claude Code run for as long as they are open, so the ring that turns on a tab while a command runs no longer turns for them — it made a tab look as if it were still loading. Hover over the tab and the card still says how long the program has been open; when it ends while you are in another tab, the tab still shows a green tick or a red dot.
Fixed
Dragging a tab moves the tab, not the window.
Dragging a tab moved the whole window instead, so a tab could not be put in a new place, pulled out into a window of its own or dropped on another window's tabs. Now the tab follows the pointer; dragging the empty part of the title row still moves the window, and Window ▸ Move & Resize works as before.
The Dock icon's menu keeps a steady width.
A window is listed there, and in the Window menu, by the title of what runs in it, and a program can set a whole sentence as its title — the menu grew as wide as that sentence. A long title now ends in "…" at a fixed width; the tab still shows its full title.
0.8.0
Added
Choose what text does at the top of the window.
Settings ▸ Appearance ▸ Content edge (
[appearance] content_edgeinsettings.toml) keeps the new fade, cuts the text under a thin line in the dividers' color, or cuts it where the pane ends as before. The last two give back the line some window heights lose to the fade.A warm light theme,
linen.Warm ink on a cream background with a burnt-orange cursor and input mark. Pick it from View ▸ Theme ▸, or set
theme = "linen"(orlight_theme = "linen"to use it whenever macOS is in light mode).Name your tabs, and scroll through as many as you open.
Double-click a tab (or choose Window ▸ Rename Tab…) and type: Return keeps the name, Esc leaves it, and emptying the field gives the tab back the title its shell sets. The name is kept when you quit, relaunch or update. When the tabs no longer fit they stop shrinking and the row scrolls — with the wheel or the trackpad — fading out at the edges, and a button beside
+(Window ▸ Show All Tabs, ⇧⌘\) lists every tab, with the one you are on ticked and a dot for what is going on in it. Selecting a tab brings it into view.Drag a tab to put it where you want it, or to give it a window.
Drag a tab along the row and the others make room; let go and it stays there. Pull it down into the window, or out of it, and it becomes a window of its own where you let go; drop it on another bateri window's row and it joins that window at the place you point to, with a gap opening there as you come over. Nothing restarts: the tab keeps its shell, its running command and any question it was asking.
Move a tab to a window of its own, or gather your windows into one.
Right-click a tab for Close Tab, Close Other Tabs (one question for all of them), Move Tab to New Window and Rename Tab…. Window ▸ Move Tab to New Window does the same for the tab you are on, and Window ▸ Merge All Windows puts every window's tabs into the current one. Nothing restarts: the tab keeps its shell, its running command and any question it was asking.
Changed
Tabs in the title bar, in your theme's colors.
A window's tabs are now bateri's own: they sit in the title bar beside the traffic lights, drawn in the theme instead of the system's grey, with
+at the right end. A window with one tab looks as before — its title in the middle. Click a tab to switch to it; middle-click it or use the × that appears on hover to close it. ⌘1–⌘9, ⇧⌘[ / ⇧⌘] and ⌃⇥ switch tabs as before, and ⌘N follows the system's "Prefer tabs" setting. A question a background tab asks — a password, an upload's confirmation — waits until you switch to that tab instead of covering the one you are looking at, and a question that is open stays with its tab when you switch away: it is there as you left it, half typed, when you come back. A tab with a question waiting shows a ? in a ring. With several tabs a settings error shows as a ⚠ beside+; hover over it to read it.Each tab shows what goes on in it.
A ring turns while a command runs — on the far end of ssh too, where bateri's shell integration runs. A command that finishes while you are in another tab leaves a green tick, one that fails a red dot, until you look at that tab. An upload or download shows an arrow and fills a line along the tab's bottom, and a host you marked as production, staging or development colors a line along its top. Rest the pointer on a tab for a summary card: its folder, what its last command did and for how long, a transfer, the host. Hold ⌘ to see the key that reaches each tab. Tabs slide into place as they open and close; with Reduce Motion on everything changes at once and the ring stands still.
Text no longer gets cut in half at the top of the window.
Where the terminal meets the tab bar — or the divider above a split pane — a line scrolling up now fades out over a few pixels instead of being sliced through its letters, and lines from your history fade into that strip too. The first line of a screen at rest always stands fully readable below it. Full screen programs such as vim keep the strip empty. The strip is never shorter than the left margin, so at some window heights the terminal shows one line fewer than before.
0.7.0
Added
A scroll bar that shows up when you scroll and then gets out of the way.
A thin bar appears at the terminal's right edge while you scroll — the trackpad or the wheel, ⌘PgUp/⌘PgDn/⌘Home/⌘End, a jump to a search match — and fades out about a second after you stop. Output arriving below never brings it up. It runs from under the title bar to the top of the dock, and it is not drawn in full-screen programs such as vim or less, nor before anything has gone into the history.
Point at the right edge to take hold of it.
With the pointer over the bar it widens into a faint track: drag the thumb, or click the track to jump to that spot. The wide bar marks every command in your history in the colours of the marks beside the commands — success, failure, still running — and pointing at a mark tells you the command, its exit code, how long it ran and when it started; a click on it brings that command into view.
Search matches on the bar.
While a search (⌘F) is open, the bar shows where its matches are across the whole history, the current one brightest.
Jump to latest.
When output arrives below a window you have scrolled up, a Jump to latest button at the bottom right says how many new lines came; a click glides you back to the bottom.
[terminal] scrollbarchooses when the bar shows:
"system"(the default) follows Show scroll bars in System Settings ▸ Appearance,"auto"shows it while you scroll,"always"keeps a wider bar in a track of its own and the text makes room for it,"never"hides it. It is also in Settings ▸ Appearance ▸ Scroll bar.
Changed
While there is history to scroll, the narrow strip at the terminal's right edge where the bar lives belongs to the bar, even while it is hidden: a selection or a ⌘-click on a link does not start there.
Updating straight from 0.4.0 does not carry running programs over to this version: they end, and windows, tabs and history come back as after a quit. Updating from 0.5.0 or 0.6.0 carries them over as before.
0.6.0
Added
A REPL gets a one-line guide in the dock's place.
In the Python, Node, Bun, Deno and Ruby (
irb,pry) REPLs —ipythonandbpythontoo — the dock shrinks to a single line, like the ssh status bar, that says which interpreter you are in and where it comes from:Python 3.14.5 · venv ~/proj/.venv/bin/python3orNode v22.13.0 · nvm ~/.nvm/versions/node/v22.13.0/bin/node, with how to leave (⌃D exit) on the right. The version manager is named when the interpreter is one's — a venv, conda, pyenv, uv, nvm, volta, fnm, asdf, rbenv or mise. On a narrow window the exit hint goes first, then the path is shortened from the left. Programs that merely run on an interpreter (a script, a coding agent like codex or gemini) get no guide; the dock just steps aside for them.Database clients get the same guide, colored like the host they are on.
In
psql,mysqlandmariadb,sqlite3,redis-cliandmongoshthe line names the server the client was started with —postgres app@db.prod:5432/main, or the file for SQLite — with how to leave (\q to leave) on the right. Your[remote] hostsmarks now apply to the database's server too, so a production database is as red as a production machine, and Shell ▸ Mark “host” as marks it from there. A password is never shown, whichever way you passed it (an option, a connection URI or string). A wide pattern you wrote for ssh, like{ host = "*", mark = "development" }, now colors database clients as well.Containers and Kubernetes pods say where you are.
A shell opened with
docker run -it,docker exec -it,docker compose execorrun(and theirpodmanforms) gets the guide line with the image, container or service it runs in —container redis:alpine.kubectl exec -it,kubectl run -itandkubectl debug -itname the cluster's context, the namespace you gave and the pod —k8s prod-eu · payments pod/api-7f9c— and your[remote] hostsmarks color the guide by the context, so a production cluster is red too; Shell ▸ Mark “host” as marks the context from there. The context is the one--contextnames or your kubeconfig's current one (only that line of the file is read), and a context's name is matched whole: writekubernetes-admin@kubernetes, notkubernetes.A root shell is red, a nested shell says so.
After
sudo -i,sudo -sorsuthe guide line readsroot exit to leavein red, whatever your marks say, so a root shell is never mistaken for your own; a shell started from the prompt readsnested bash exit to return, and one a tool opened names the tool (nested poetry shell). Whilesudoasks for your password, and for the whole of asudocommand that is not a shell (sudo make install), the dock stays as it was.
Changed
The input dock steps aside for programs that read the keyboard themselves.
When a command such as
codex, Claude Code in its inline mode,python3ornodetakes the keyboard, the dock at the bottom goes away for as long as that program runs — the program sits at the bottom of the window and the recent history fills the top — and comes back when you return to the prompt, as it does after vim. The terminal's size does not change, so the program is never asked to redraw. Commands that only print (a build,ls -R,npm run dev) keep the dock as before.
0.5.0
Added
Your programs survive a crash.
If bateri crashes or is forced to quit (Activity Monitor,
kill -9), vim,npm run devand an ssh session keep running without a window, and the next bateri takes them back into their windows — the same processes, not restarted copies — with their screens and scrollback as they were at the crash, and whatever they printed while bateri was closed below. This is the new default; a small helper process (bateri hold) runs beside bateri to keep the programs somewhere while bateri is gone, and bateri keeps a record of each pane's recent output in memory it shares with that helper (nothing is written to disk). A pane that was already open when you switched away from"update"comes back with its program redrawing the screen — vim or htop at once, a plain shell's screen is gone — and the pane says so in a dim line.Programs can outlive ⌘Q too.
[terminal] keep_running(or Settings › General › Keep programs running) chooses"update"(only an update keeps them, as before),"crash"(the default) or"quit": with"quit", ⌘Q asks nothing and the programs run on until you open bateri again, which brings them back with their screens. A notification names what is still running a moment after you quit, so nothing is forgotten, and Quit and End Programs (⌥⌘Q, under the bateri menu with ⌥ held) is the quit that ends them. The setting applies the moment you save it, no restart needed. Restarting the Mac or logging out still ends the programs.Windows come back after a crash.
The layout — windows, tabs, splits, folders — is kept on disk while bateri runs (without the scrollback), so after a crash or a power cut the windows reopen even where no program was kept, each pane with a new shell (not with
restore_windows = "off").Hold ⇧ while opening bateri
to start with one empty window and skip everything saved; kept programs wait for the next launch. If bringing programs back ever crashes bateri, the next launch brings them back without their screens, and the one after gives them up and opens an empty window, so a bad restore cannot trap you in a crash loop.
Changed
restore_windows = "off"no longer ends running programs on an update: whether programs live on is nowkeep_running's alone, andrestore_windowsonly decides what is written to disk and how a pane whose program did not live comes back.
Fixed
A screen brought back after quitting or an update keeps its layout in three cases where it shifted: text after a tab stays in its column (it moved right by the tab's width), a line that wrapped onto a line erased since keeps its own row (the two came back as one), and a tab stop set in the last column is still there when the window grows wider.
bateri no longer crashes when a program redraws a progress bar under a fixed top line (apt does) while you are scrolled up in the history; the view now stops at the top of the history.
0.4.0
Added
Updates keep your programs running.
“Install and Relaunch” no longer ends what runs in your panes: shells, vim,
npm run devand an ssh session — Claude Code on a server included — carry on in the new version with their screens as they were. A file transfer or a password prompt in progress makes the relaunch wait (the status line says “Update waits for N transfers”; ⌘. cancels the transfer and lets the update go on). This starts with the next update: the version being replaced must already carry it, so updating to 0.4.0 itself still restarts your programs.Windows come back after quitting.
After ⌘Q or a restart, bateri reopens your windows, tabs and splits — each pane in its folder, at its font size and with its scrollback in colour. Shells start fresh; a pane that was on ssh comes back with the
ssh …line typed and waiting for ⏎.[terminal] restore_windows(or Settings › General) chooses"all","layout"(no scrollback is written to disk) or"off".Letter spacing.
[font] letter_spacinginsettings.toml(or Settings › Font) widens or narrows the space between letters, the horizontal twin of line spacing — iTerm2's “Horizontal spacing” divided by 100.Tighter spacing.
Line and letter spacing now go down to
0.5. Below1letters are no longer cut: accents and tails reach into the neighbouring line, as in iTerm2, while box-drawing lines stay joined.
Changed
line_height = 1.0is now exactly the font's own line spacing; lines were one pixel taller than the font asks for.
Fixed
The Settings window scrolls: the bottom rows of Remote Files were hidden under the button and could not be reached. The window can also be made taller or shorter.
0.3.0
Added
Folder tracking and command blocks over ssh, with nothing to install.
Type
ssh serveras usual: on the first prompt the status bar shows the remote folder (⇄ server ~/project) and followscd, remote commands get their success/failure stripe and duration, and ⌘-click opens relative paths. Works with zsh, bash and fish on the server; your rc files on the server are never touched (bateri keeps a small folder under~/.local/share/baterithere). Inside a local tmux, and for servers marked Production, it stays off.Servers without a shell (routers, Windows,
git@github.com) are detected on the first try: the connection quietly reopens as a plain ssh session and bateri remembers that server.Turn it off
in Settings › Remote Files, or per server with Shell › Shell Integration on “server”.
Password servers work for remote files.
Dropping a file, ⌘-click preview, downloads and the server load now work on servers that ask for a password. While your ssh session is open, they ride on it and ask nothing; otherwise bateri asks once in its own sheet and can remember the password in your Keychain (Shell › Forget Password for “server” removes it). The status bar shows Sign In… when a password is needed.
Remote programs can recognise bateri:
LC_TERMINAL=bateri,LC_TERMINAL_VERSIONandLC_BATERI_TAB_URLreach the server (servers that acceptLC_*, and every server bateri sets up).A second
sshto the same server in another tab doesn't ask for the password again while the first one is open.Server load in the ssh status bar.
While you're connected to a Linux server, the right side of the status bar shows its CPU and memory:
cpu ▂▃▅▇▅▃▂▁ 23% mem 61%, with the last eight CPU samples as a small graph. Values stay dim until they cross a threshold (CPU 70/90%, memory 80/92%), then turn yellow or red, with a▲when critical. Disk usage appears only once/is more than 85% full. In a narrow window the graph goes first, then all but the worst value; the host name is never cut.Click the load for details
: CPU cores, load average, memory and swap, disk, uptime and the three processes using the most CPU right now.
Settings › Remote Files › Server load
: graph, numbers only, alerts only (a green dot until something crosses a threshold) or off, and how often to sample (every 3 seconds by default).
Sampling uses the connection bateri already keeps open for remote files, so no extra login. It pauses while the tab is in the background or after two minutes without input, and stops when you leave the server. Servers that aren't Linux show no load. The load appears only after you've logged in.
Changed
The ssh status bar now shows the remote folder from the window title too (
⇄ host ~), not only from servers that report it (OSC 7). The title can also be in theuser@host:folderform, without a space.
0.2.0
Added
Clickable links.
Hold ⌘ and URLs, existing files and folders, and OSC 8 hyperlinks get an underline and a hand cursor; ⌘-click opens them. Works in the scrollback, in full-screen apps and in the input line. Paths with spaces and bare names from
ls(src,Makefile) are found too. Right-click a link for Open, Reveal in Finder and Copy. OSC 8 links show a dashed underline without ⌘ and their target in the bottom-left corner.Remote files over ssh.
In an ssh session, ⌘-hover a name in
lsoutput and bateri asks the server whether it exists:- ⌘-click previews a file: a temporary, read-only copy downloads and opens (scripts open as plain text). Larger files (100 MB by default) ask first.
- ⌘-drag a file or folder to Finder or the Desktop to download it there.
- Right-click for Download to Downloads, Download To…, Copy Path and Copy as scp Path.
- Downloads and uploads share one transfer list (“Show transfers”), with progress, cancel (⌘.) and a notification when bateri is in the background. Downloaded files carry the usual “downloaded from the internet” mark.
Settings › Remote Files
: preview size limit, preview and download folders, how long previews are kept, a size limit and Clear Now. Previews are cleaned up when bateri starts and once a day, never while you might be reading one, and a preview you edited is moved to Downloads instead of deleted.
Changed
The ssh status bar (
⇄ host) stays at the bottom while vim, htop or less runs on the server.When a server doesn't report its folder (OSC 7) but sets the usual
user@host: folderwindow title (Debian and Ubuntu do), bateri uses that folder for links and for uploads dropped from Finder, instead of the home folder.
Fixed
A wide character missing from the font could draw as two boxes instead of one.
0.1.1
Changed
Rendering now goes through wgpu (still Metal underneath on macOS). Nothing should look different; this is groundwork for a Linux version.
Fixed
Fast, continuous output (large logs,
seq 1 50000) no longer makes the screen jump back a screenful every other frame, and costs roughly half the GPU work it did.Short bursts of output that overflow a full screen (
seq 1 200,ls -la) now slide in every time, not only when they happened to arrive in one piece.The About panel shows the copyright line correctly (
©andÖwere garbled).
0.1.0
Added
A GPU-rendered terminal for macOS, drawn with Metal. An idle window draws nothing.
Command blocks: each command is marked in the gutter by how it ended, and commands that run longer than a second show their duration.
The input dock (zsh): the line you are typing sits at the bottom of the window with your directory and git branch, wraps and grows for multi-line input, and can be selected and edited with the mouse.
Native macOS tabs, and splits you can move between, resize, equalize and zoom from the keyboard.
Search in scrollback, with case-sensitive and regular-expression modes.
SSH awareness: over ssh or mosh the dock shows the host, colored by how you marked it, and files dropped from Finder are uploaded to the remote directory.
Emoji sequences, wide characters, and box-drawing, block and Braille characters drawn to fit the cell.
Themes, fonts and every setting in
~/.config/bateri/settings.toml, applied as soon as the file is saved, and a settings window that edits the same file.Automatic updates from GitHub Releases, signed and notarized.
Download bateri
Free and openly licensed. Open it and your zsh arrives as usual; bateri handles the rest.
Download for macOS