38 Commits
Author SHA1 Message Date
Aram Drevekenin 333d7898a8 Run keybinding improvements (#5701)
* add ORIGIN_PANE_ID to Run commands started from a keybinding

* RunInBackground

* add pr
2026-10-09 16:14:47 +02:00
Aram Drevekenin 5586646d3f fix(plugins): ignore caller_cwd when matching aliased plugins in LaunchOrFocusPlugin (#5698)
* fix(plugins): ignore caller_cwd when matching aliased plugins in LaunchOrFocusPlugin

* rustfmt
2026-10-09 13:21:40 +02:00
Aram Drevekenin b1033be2a3 Improved mouse handling (#5697)
* configurable mouse bindings

* feat(bars): reorder tabs with mouse drag, clickable status-bar shortcuts with hover effects

* fix tests

* add pr
2026-10-09 11:59:23 +02:00
Aram Drevekenin 52710dcc41 Fix flaky tests (#5688)
* initial fixes

* rustfmt
2026-10-06 14:20:02 +02:00
Lucca HuguetandAram Drevekenin 7554d23b03 fix: preserve relative pane order when reapplying tiled layouts (#5687)
* fix: preserve relative pane order when reapplying tiled layouts

* fix: cli action timeout

* fix flaky test

* rustfmt

* add pr

---------

Co-authored-by: Aram Drevekenin <[email protected]>
2026-10-06 11:18:06 +02:00
Aram Drevekenin 201c1593da Interactive configuration, popups, notifications, right-click menu (#5685)
* ui components

* right click menu + popups

* settings screen

* various fixes

* presets in config

* zellij prompt - ui elements in the cli

* context menu shortcuts and toggle, keybindings in popups, info popups + zellij prompt notify

* smart config writing and some leftovers

* keybindings/right-click/config editors

* some wrapups

* feat(plugins): add prompt() plugin API for zellij:prompt, dialog forms, and Text labels in widgets

* theme editors

* upstream by-id action types, config env for new panes only, smaller saved menu config, web right-click, example config

* upstreamify

* rustfmt

* fix windows and theme editor layout

* add pr
2026-10-05 18:46:12 +02:00
Aram Drevekenin 1dbc292398 fix: screen surface stability (#5683)
* fix: tiled panes stability

* fix floating panes stability

* additional general fixes

* add pr
2026-10-05 16:47:26 +02:00
Aram Drevekenin 208a0da5e9 Resource usage optimizations (#5662)
* shared instance plugins

* reduce needless allocations and share memory

* fix: read buffer bug

* idle plugin fixes and optimizations

* trim allocator for glibc on pane close

* fix flaky integration tests

* refactor: naming

* rustfmt

* add pr
2026-09-28 10:58:12 +02:00
Tyler KellerandAram Drevekenin 2fce032cce fix(kitty-graphics): zlib-compress images forwarded to the host terminal (#5608)
* fix(kitty-graphics): zlib-compress images forwarded to the host terminal

`emit_kitty_transmit` sent every image to the host as uncompressed RGBA
base64 (`f=32,t=d`), about 20x the size of a PNG the application sent,
and re-sent it on every tab switch, pane split and resize step. Compress
the cached host payload with zlib and tag the transmit with `o=z`, which
the kitty protocol defines as part of its base feature set.

Measured with a headless client at 429x77 (8x17 px cells): a 121 KB PNG
went from 2.4 MB to 163 KB on the wire, a 943 KB PNG from 19.9 MB to
1.9 MB, with no measurable change in server CPU.

Fixes #5596

* fix: conditional zlib compression depending on outer terminal support

* rustfmt

* add pr

---------

Co-authored-by: Aram Drevekenin <[email protected]>
2026-09-25 10:33:28 +02:00
Aram Drevekenin 3e470a43dc fix: stop host terminal replies from leaking into the shell prompt (#5655)
* fix: stop host terminal replies from leaking into the shell prompt as text

* add pr
2026-09-24 18:52:13 +02:00
Myah MitchellandAram Drevekenin 0591ca5432 feat(nested-sessions): report a guest's input mode and key bindings to its host (#5589)
* refactor(plugin-api): share the keybinding protobuf conversions

The conversion between a keybinding table and its protobuf form was written
out four times: once each way for the ModeUpdate and InitialKeybinds events.
Collect them into `keybinds_to_protobuf` and `keybinds_from_protobuf`.

Decoding now drops a binding whose key is missing instead of unwrapping it,
so a malformed or foreign payload can no longer panic the conversion, and a
mode whose key fails to convert costs only that binding rather than every
binding in the mode.

* feat(nested-sessions): carry input mode and keybindings over the protocol

A session hosting a nested session has no way to learn what that session is
doing, so its plugins cannot show hints for the session the user is actually
typing into. Add the three messages that carry it:

- GuestModeUpdate, sent by a guest whenever its input mode changes, so a host
  always knows which of the guest's bindings currently apply.
- RequestGuestKeybinds and GuestKeybindsUpdate, a query and its answer, for
  the far larger keybinding table. Keeping the table behind a query means it
  is fetched once by whoever wants it rather than pushed at every host.

The table travels as an encoded plugin-API payload in an opaque bytes field.
Describing keybindings natively here would mean restating the whole Action
schema in this contract, which the codegen compiles with only its own include
path. Reusing the existing payload also means a host and a guest built from
different Zellij versions exchange whatever both understand and silently drop
the rest, which is the behavior this wire needs.

An input mode is written under the name InputMode::from_str reads, so adding a
mode needs no change to this contract and an unknown mode is rejected rather
than misread.

Peers advertise the new HintReporting capability, so each side can tell
whether the other can take part before asking it anything.

* feat(plugin-api): expose nested session mode and keybinding events

Plugins running in a host session can see that a pane holds a nested guest
session, but they have no way to learn what that guest is doing. A status bar
in the host therefore keeps showing the host's own hints while the user is
descended into the guest, which is the wrong keybinding table for the keys the
user is actually pressing.

Add two events and one command covering that gap:

  - Event::NestedSessionModeUpdate reports a guest's input mode as it changes.
  - Event::NestedSessionKeybinds delivers a guest's full keybinding table.
  - PluginCommand::RequestNestedSessionKeybinds asks a guest pane for that
    table, which arrives asynchronously as the event above.

Both events carry the pane the guest runs in and the guest's session name, so
a plugin watching several nested panes can tell them apart. Keybindings are
requested rather than pushed because the table is large and most plugins never
need it.

* feat(nested-sessions): report guest input mode and keybindings to the host

Wire the nested session hint events end to end.

A guest announces the HintReporting capability during the handshake and, from
then on, emits a GuestModeUpdate frame whenever its input mode changes. The
mode is reported on every change rather than only while the host is descended,
so the host already holds the right mode the moment focus arrives and the
status bar does not lag behind the descent.

The host turns each such frame into Event::NestedSessionModeUpdate. It answers
PluginCommand::RequestNestedSessionKeybinds by writing a RequestGuestKeybinds
frame into the guest pane; the guest replies with its keybinding table plus its
current mode, and the host forwards the table as Event::NestedSessionKeybinds.

Requests to guests that did not advertise HintReporting are dropped rather than
written, and frames from panes whose guest is not currently live are ignored,
matching how the other guest-to-host frames are handled.

Both events and the command require the ReadApplicationState permission, the
same gate ModeUpdate uses.

* test(nested-sessions): cover guest mode and keybinding reporting

Unit tests over the contract check that every input mode survives the round
trip under its own name, that a mode name the reading side does not know is
rejected rather than guessed at, and that a keybinding table keeps its modes,
keys and actions across the wire. The undecodable and empty payload cases are
covered too, since a host and a guest may be built from different versions.

Integration tests drive two real sessions bridged through a pane: both sides
advertise hint reporting during the handshake, the guest answers a keybinding
request with a populated table plus its current mode, and the guest reports
each mode change while the user is descended into it.

* test(nested-sessions): drop unknown capabilities without losing known ones

A peer built from a newer Zellij can advertise capabilities this side has
never heard of, so pin down that they are ignored individually rather than
invalidating the whole advertisement.

* feat(nested-sessions): carry the guest's base mode alongside its input mode

A host plugin that only knows a guest's current mode cannot tell which of the
guest's bindings are inherited from its base mode. Zellij's own hint rendering
leans on that distinction: bindings the base mode already advertises are
inherited by every other mode through `shared_except` groups, so repeating them
in each mode is noise. Without the guest's base mode a host plugin either
suppresses the wrong bindings or suppresses none.

A guest with a non-Normal base mode, such as an unlock-first config, is where
this shows: assuming Normal there hides the wrong half of its bindings.

The base mode rides along on the existing mode message, so a guest that has not
switched modes yet still reports one, resolved the way the rest of Screen
resolves it (the configured default mode is the base). It stays optional on the
wire, so a name the reading side does not recognize costs only the
inherited-binding distinction rather than the whole message.

* feat(nested-sessions): report the guest's mode when the handshake completes

A guest only pushed its input mode when that mode changed, so a host that
had just picked up a nested session learned nothing about it until the user
happened to switch modes inside it. A host plugin has no other way to tell
which of its panes holds a session worth asking for keybindings, which left
it unable to act on the feature at all in the common case of a guest sitting
in its starting mode.

Send the report once on contact as well, and reuse the same client mode
lookup the keybinding answer already did.

* docs(changelog): note the nested session hint reporting events

* fix(nested-sessions): drop guest keybindings on control characters

Nothing a guest says is authenticated. Its frames travel in the terminal
stream of the pane it runs in, so any program with that pane can write them,
including a keybinding table claiming a binding on a raw control character.
A host that draws those bindings puts their keys on its own screen, where a
control character is a terminal escape in the host's output rather than a
key anyone could press.

Drop them where the guest's payload is decoded, so no host plugin inherits
the problem. Zellij spells the control keys that do exist as their own
BareKey variants, so a Char holding one describes no binding worth keeping.

* test(nested-sessions): expect hint reporting in the announce ack

The host now advertises HintReporting alongside NestedControl when it
acknowledges a guest, so the assertion on the exact capability list had to
follow.

* fix(plugin-api): drop only what has no protobuf form when writing keybindings

keybinds_to_protobuf failed the whole table on the first key or mode it could
not represent, so one unrepresentable binding cost the caller every binding:
a ModeUpdate that failed to convert entirely, and a nested session's answer
that reached its host as an empty table indistinguishable from a session with
no bindings at all.

Drop the individual mode, key or action instead, which is what the reading
half already does and what the writing half already did for actions. A table
now survives the trip between builds minus whatever they do not have in
common.

* fix(nested-sessions): keep a host's view of the guest fresh across a reconfigure

A reconfigure rewrites a session's keybindings and base mode without going
through change_mode, and keybindings are otherwise only ever sent in answer
to a request. A host that had already asked once therefore kept drawing the
table the guest had before its config was reloaded, with no way of noticing
it had gone stale, and would not have picked up the new base mode until the
user happened to switch modes inside the guest.

Report both from reconfigure, next to the shortcut broadcast that already
happens there. Answer a keybinding request from the requesting client's own
table too, since a reconfigure with write_to_disk unset rebinds only the
client that asked: the mode in the same reply already came from that client,
so the two halves now describe the same thing.

* fix: adjust protocol + API

* Update CHANGELOG.md

---------

Co-authored-by: Aram Drevekenin <[email protected]>
2026-09-24 14:43:03 +02:00
Aram DrevekeninandLucca Huguet 81f56e1aed Yazelix fixes (sixel/kitty correctness, explicit-swap-layout change rather than toggle, border styling) (#5630)
* fix: sixel image reaping/id-reuse

* fix: kitty scaling issues

* fix: stacked pane ordering

* feat: apply tiled/floating swap layout by name

* border styling

* fix tests

* fix: complete Yazelix feature validation (#5631)

* fix: retire client-ids instead of reusing them

* distributions

* rustfmt

* fix tests

* update changelog

* fix tests and race

---------

Co-authored-by: Lucca Huguet <[email protected]>
2026-09-24 09:26:20 +02:00
Marcio Granzotto RodriguesandAram Drevekenin 474ea0cef6 feat: forward OSC 7 (working directory) to parent terminal (#4867)
* feat: capture OSC 7 working directory on Grid and expose via Pane trait

Add osc7_payload field to Grid, handle the b"7" OSC sequence in
osc_dispatch, expose it via a Grid accessor, add osc7_payload() to
the Pane trait (default None), and implement it on TerminalPane by
delegating to the Grid. Follows the has_bell/consume_bell pattern.

* feat: forward OSC 7 from focused pane to parent terminal on render

* fix: validate OSC 7 URI and clean up state on client disconnect

Reject URIs containing control characters (< 0x20 or 0x7f) to prevent
injection into the parent terminal when the URI is re-emitted via OSC 7
forwarding. Also remove per-client OSC 7 forwarding state in
remove_client() to avoid stale entries accumulating after disconnect.

* style: fix formatting in OSC 7 tests

* fix: add control char test, clear osc7 on reset, doc comment

- Add test for control character rejection in OSC 7 URIs
- Clear osc7_payload in reset_terminal_state() (RIS/\ec)
- Add doc comment on osc7_payload() getter

* fix: address PR review feedback

- Reject C1 control characters (U+0080..U+009F) in OSC 7 URIs using
  char::is_control() instead of byte-level check
- Reject entire OSC 7 if any param segment has invalid UTF-8 instead
  of silently dropping bad segments
- Avoid String allocation in render hot path by comparing borrowed
  &str, only allocating when the value actually changes
- Add test for C1 control character rejection

* fix: integrate OSC 7 forwarding with upstream CWD tracking

* add some more tests

* docs: update changelog

---------

Co-authored-by: Aram Drevekenin <[email protected]>
2026-09-14 18:26:14 +02:00
Aram Drevekenin 60f7aa7c51 Minor fixes for 45 patch (#5550)
* fix: stale theme and floating visibility issues, notification bounding

* fix: repaint excess tab surface when closing tab and moving to a smaller one
2026-08-28 10:21:03 +02:00
Aram Drevekenin a9bd448e66 feat: allow starting a session with an initial command (#5543)
* feat: allow starting a session with an initial command

* add pr
2026-08-26 15:00:45 +02:00
Aram Drevekenin 69954b5b6c fix: don't require nested reading of env var to detect nested sessions (#5522)
* fix: don't require nested reading env var to detect nested sessions

* add pr
2026-08-24 10:45:17 +02:00
Aram Drevekenin bf8d23a4f7 bump development version 2026-08-20 11:12:34 +02:00
Aram Drevekenin 070b9c3d1c Fixes before 045 (#5492)
* fix: keep single-pane tabs when serializing, stop the busy-spin on IPC disconnect, and make client-less CLI actions either work or fail loudly

* fix: some tab closing/ordering issues

* test: integration coverage for OSC 133 selection, scroll retention, paste-read opt-in, theme actions, and input fragmentation

* rendering-width regression tests

* fix: forward alt+mouse events into a guest pane the client is descended into

* fix: alt + [] delay in non-kitty

* allow disabling mouse hover tips while keeping the other effects

* more osc133 actions

* fix: base mode race when changing keybinding presets

* fix compilation warnings

* make releases drafts and remove diagnostic logging

* add pr
2026-08-20 08:04:12 +02:00
Aram Drevekenin 98a0837077 feat: allow opting-in to reading paste buffer (default false) (#5472)
* feat: allow opting-in to reading paste buffer (default false)

* add pr
2026-08-13 10:19:13 +02:00
Valentyn KitandAram Drevekenin c428ae93b9 fix(scroll): keep scroll position when leaving scroll mode (#5299)
* fix(scroll): keep scroll position when leaving scroll mode

Leaving Scroll mode for Normal or Locked snapped the active pane back to
the bottom. Switching panes requires leaving Scroll mode, so that reset
is what prevented keeping a pane scrolled while working in another.

It is also redundant: the scroll keymap already binds an explicit
ScrollToBottom on exit, so users who want to follow live output keep it,
while a plain exit now preserves the scroll position. Output is still
buffered while a pane is scrolled and replayed when scroll is cleared,
so the buffer-overwrite protection is unaffected.

* fix(scroll): re-enter scroll mode when focusing a scrolled pane

Focusing a scrolled pane now switches the client into Scroll mode, and
focusing an unscrolled one returns it to Normal. Only the Normal<->Scroll
pair is synced, so a client in another mode is left alone.

* fix(scroll): re-enter scroll mode on focus-last-pane too

Cover the FocusLastPane action added in #4241 with the same focus-to-scroll
sync as the other focus moves, so landing on a scrolled pane via focus-last
behaves like landing on it via MoveFocus.

* fix(scroll): sync the default mode with scroll, cover mouse focus

Follow imsnif's review on #5299. The focus sync now switches between Scroll
and the configured default mode read from default_mode_info instead of a
hardcoded Normal, so unlock-first sessions (default Locked) return to Locked
rather than Normal. It also fires on mouse focus changes (click, click-through,
focus-follows-mouse) by hooking the existing active-pane diff in
handle_mouse_event, not only keyboard focus moves.

Tests parameterize the focus-sync assertion over the default mode (Normal and
Locked) and add a mouse-click variant.

* cover some more cases

* sync also on mouse scroll

* rustfmt

---------

Co-authored-by: Aram Drevekenin <[email protected]>
2026-08-11 15:51:55 +02:00
ZrjaKandAram Drevekenin 1d1d5c1101 fix(input): realign raw-byte buffer with the keyboard parser to stop stale bytes eating keystrokes (#5446)
* fix(input): realign raw-byte buffer with the keyboard parser to stop stale bytes eating keystrokes

After a paste (e.g. via a clipboard manager like maccy), zellij's
current_buffer can hold up to a few stale bytes that termwiz's
InputParser has already consumed into events. Those stale bytes are then
attached to the raw payload of subsequent KeyEvent messages, desyncing
each keystroke from the bytes that produced it: keys go missing, come
out garbled, or drop into vi command mode.

The root cause is that parse_with_consumed reports consumption relative
to its internal self.buf, while stdin_handler drains a separately
accumulated current_buffer. The two can drift apart whenever a read
leaves a partial sequence that the parser holds under maybe_more.

Reconcile the two after every parse: trim current_buffer to the
parser's buffered length, so no byte the parser has already decoded is
ever forwarded with a later key event. Add InputParser::buffered_len to
the vendored termwiz for that purpose.

* fix: remove parsed bytes from front rather than back

* rustfmt

---------

Co-authored-by: Aram Drevekenin <[email protected]>
2026-08-10 14:17:09 +02:00
Aram Drevekenin 5254e4fc1d Fix tab close size (#5444)
* fix: properly resize tabs when closing another tab

* rustfmt
2026-08-05 18:54:59 +02:00
Aram Drevekenin 3239d37b40 Native web mobile UI (#5441)
* initial chrome

* mobile state

* feat(mobile-web): implement browser→server actions (fit toggle, single-pane fullscreen, pane/tab focus) with fullscreen-truth reconciliation

* panning

* remove mobile plugin

* fix first load race

* improve web handshake

* rustfmt

* cleanups

* moar cleanups

* add bundle asset check to ci

* fix(mobile-web): tab-scope co-presence, yield single-pane to desktop clients, fix render-mode desync

* make mobile use no-ui fullscreen

* client side welcome screen for mobile

* attach web clients to first tab on tiles surface

* fix: opening new pane in mobile single mode no longer exits mobile single mode

* mobile chrome light theme support

* fix server races and flaky tests

* rustfmt

* fix flakes

* add pr
2026-08-05 15:32:53 +02:00
Aram Drevekenin a7259350a8 fix: resize race when breaking a pane to a new tab (#5434)
* fix: resize race when breaking a pane to a new tab

* style: rustfmt
2026-08-03 15:35:02 +02:00
Aram Drevekenin 0e6e440402 Support the Kitty Image Protocol (#5428)
* initial implementation - kinda working

* tests and fixes

* fix bounds

* tests and compatibility fixes

* fix: cursor scroll, clears, deletes, key tolerance, and host id range

* fix: keep images alive across resize, relayout and history scroll

* anchor to lines, not pixels

* fix image/text alignments

* config to allow disabling

* fix pinned pane issue

* never let host graphics replies reach the keyboard parser

* fix nested session

* properly handle fullscreening a pane

* rustfmt

* cleanup of ignored test

* add pr
2026-07-31 19:19:49 +02:00
Aram Drevekenin cab75c58fe More dependency upgrades for debian (#5421)
* upgrade insta, rand, sha2, strum, thiserror, tokio-tungstenite, toml, which; drop unused semver and typetag

* upgrade sysinfo to 0.39.5, bump toolchain (msrv) to 1.95.0

* remote legacy yaml config converter and thus drop serde_yaml

* upgrade unicode-width to 0.2.2

* fix(tests): run ipc roundtrip test on a larger stack
2026-07-29 17:08:08 +02:00
Aram Drevekenin 9969ed10b2 Dep upgrades for debian (#5420)
* chore(deps): upgrade base64 0.22, colored 3.1, crossterm 0.29, dialoguer 0.11, directories 6.0, highway 1.2, prost 0.12.6, strip-ansi-escapes 0.2.1, suggest 0.5.1

* chore(deps): upgrade miette 7.6, nix 0.30, notify 8.2, notify-debouncer-full 0.5

* vte 0.15

* clap 4.6

* workspaceify plugin deps

* don't send empty fs watch events
2026-07-28 12:05:38 +02:00
Aram Drevekenin ea07e2d5b6 Nested session handling (#5417)
* fix: theme query and updated pixel dimensions

* add no-ui-fullscreen key/action/capability

* protocol core

* integration test harness

* fix integration tests

* fix flaky tests

* nested ui (dimming) and directional focus initial implementation

* integration tests for nested ui dimming and directional focus

* initial full screen nesteed implementation

* fix: keep hidden floating panes hidden across nested no-ui fullscreen

* fix integration tests

* no ui fullscreen integration tests

* hardening behavior/tests

* fix(nested): re-derive descend/dim on host tab switch and new-tab so clicking dimmed chrome ascends

* initial modal implementation

* initial ui improvements

* fix integration tests

* improve nested selection ui

* nested session modal refactoring and tests

* improve integration test speed somewhat

* some ui adjustments

* simplify full/auto nested session handling

* hints in compact-bar

* guest stdin leak fix

* allow floating panes to be fullscreen

* make nested session handling configurable

* protocol reannounce

* refactor: naming confusion

* improve ux somewhat

* rustfmt

* merge fixes

* improve integration test rate limiting (fix ci)

* add pr
2026-07-27 18:24:37 +02:00
Aram Drevekenin 4bfda976b1 Allow creating panes/tabs from the CLI without changing focus to them (#5346)
* feat: allow opening panes and tabs from the cli without focusing them

* rustfmt

* fix flake

* rustfmt

* add pr
2026-07-09 16:52:50 +02:00
Aram Drevekenin 8a35d678ee fix: focus last pane correctness issues (#5344)
* fix: correctness issues with focus-last-pane

* rustfmt

* add pr
2026-07-09 10:42:42 +02:00
Aram Drevekenin 70c65a9afd Stacked list fixes (#5342)
* clear padding line

* better stack ui

* fix tests

* add pr
2026-07-08 11:46:41 +02:00
Aram Drevekenin 5b310ada79 UI tweaks (#5337)
* remove dimmed

* clearer list ui

* fix integration tests

* rustfmt

* move hint to tab-bar

* redesign stack list

* rustfmt

* fix e2e

* add pr
2026-07-06 22:09:06 +02:00
Aram Drevekenin 82c4a24d70 Stacked lists (#5331)
* initial implementation

* improve ui

* fix: stacked resize interaction

* title list boundaries fix

* fix BEL

* mouse parity

* float/embed + bulk-op features

* fix in-place bug

* improve ui

* config live reload

* improve ui

* fix issues, add exit status

* fix for serialization

* fix tests

* integration tests

* comments

* refactor: duplicate title logic

* refactor: consolidate logic

* fix: flaky tests

* add a stacked swap layout

* rustfmt

* fix e2e

* add pr
2026-07-04 16:27:08 +02:00
Aram Drevekenin 0dd324bdef Reduce compilation time (#5321)
* perf: speed up dev builds

* rustfmt

* fix flake
2026-06-30 21:18:58 +02:00
Aram Drevekenin 6a6376cebb fix: occasional garbage on attaching through slow connections (#5320)
* fix: occasional garbage on attaching through slow connections

* rustfmt

* add PR
2026-06-30 16:48:37 +02:00
Aram Drevekenin 245f5141c9 Title frames (#5318)
* initial implementation

* improve single line title design

* hint text plugin infra

* add proto regen task

* display alt text in status bar

* don't display text with full frames

* style alt hover text

* fix + style control own pane hover

* make multiplayer indications responsive

* update snapshots

* plugin api

* single pane as tab

* better scroll styling

* fix tests

* tab-bar plus hover

* plugin surface tests

* integration tests

* adjust all integration tests

* reduce hover noise

* add pane id to in place

* more integration tests

* style: rustfmt

* update plugin assets

* update assets and snapshots

* add pr
2026-06-29 18:10:59 +02:00
Aram Drevekenin 27291bea28 tests: add more integration tests (#5308)
* test all the things

* consolidate shared harness

* rustfmt
2026-06-25 17:09:26 +02:00
Aram Drevekenin 8c7e41c9aa chore: new test infra (#5269)
* initial implementation

* refactoring and cleanups

* port basic e2e tests

* fix tab rotation

* migrate client and mouse tests

* migrate the rest of the tests

* remove old e2e tests

* rustfmt

* add e2e note

* fix stale test

* fix: cross platform locking/cleanup

* fix: change mode race discovered by tests

* rustfmt

* fix: attach/detach race in tests

* fix plugin test assertion

* add pr
2026-06-16 15:44:22 +02:00