kterm 1.5.10
kterm: ^1.5.10 copied to clipboard
kterm is a fast and fully-featured terminal emulator for Flutter applications, with support for mobile and desktop platforms.
1.5.10 - 2026-09-20 #
Bug Fixes #
- Null-check
focusNode.contextbefore shortcut dispatch:TerminalViewState._handleKeyEventforce-unwrappedfocusNode.context!before callingShortcutManager.handleKeypress; a detached node could crash key handling. Now mirrors the framework's ownShortcutswidget null-check, and documents why the protected-member call follows the framework pattern. —lib/src/terminal_view.dart eraseRange(0, 0)no longer crashes at column 0: When the cursor sat at column 0,EL 1/ED 1passedend == 0and the wide-char boundary check readgetWidth(-1), throwing a RangeError on a plainESC[1J. Fix adds the missingend > 0guard at the choke point, mirroring the existingstart > 0guard. Found by the new chunk-split fuzz. —lib/src/core/buffer/line.dart
Chores #
- Dependencies:
image 4.9.2 → 4.10.1(minor). Verified with analyze + graphics/kitty tests + full suite. —pubspec.lock,example/pubspec.lock
Tests #
- Chunk-split monkey testing extended to buffer/render stress:
test/stress/buffer_stress_test.dartandtest/stress/render_stress_test.dartnow feed escape-heavy payloads in random 1–7 char chunks (pty-style arbitrary boundaries), with split==one-shot equivalence and wide-char cases; wide-char payloads are built by code point (runes) so emoji surrogate pairs are never split. The stress suite now runs in CI (flutter test test/stress/), plus amake stresstarget. —test/stress/*,.github/workflows/dart-ci.yml,Makefile - Input handler coverage:
CascadeInputHandlerordering/decline/empty-chain,CtrlInputHandlerrange + modifier guards,AltInputHandlermacOS guard, and all 8insertModifiersSGR codes. —test/src/core/input/handler_test.dart - Charset/tab/reflow gaps:
Charset.reset(),TabStops.setAt/clearAt/clearAll/resetbounds safety, and reflow edge cases (no-op same-width, 1-column, multi-line merge, wide-char boundary, resize cycles). —test/src/core/charset_test.dart,test/src/core/tabs_test.dart,test/src/core/reflow_test.dart
1.5.9 - 2026-09-18 #
Bug Fixes #
graphicsCommandEndsignature corrected toFuture<void>: TheEscapeHandler.graphicsCommandEnd()method was declared asvoidbut bothTerminalandTerminalDebuggerimplemented it asFuture<void> async(image decoding is inherently asynchronous). The parser was calling it synchronously withoutunawaited, risking unhandled async exceptions. Updated the handler interface, parser call site, and regenerated mocks. —lib/src/core/escape/handler.dart,lib/src/core/escape/parser.dart
Tests #
- Golden files updated for Flutter 3.44: The
colors.pnggolden was severely stale (6 colors vs 994 in current rendering). All four golden tests (colors,htop_80x25_3s,text_scale_factor@1x,text_scale_factor@2x) regenerated against current Flutter 3.44.4 rendering. —test/src/_goldens/*
1.5.8 - 2026-09-17 #
Bug Fixes #
reset(1)now actually resets the terminal:ESC c(RIS) andCSI ! p(DECSTR) were silently swallowed, so runningresetleft the screen, modes and tab stops untouched and could leave the display in a broken state. The parser now decodes both into newEscapeHandler.fullReset()/softReset()hooks;Terminalimplements them per xterm semantics (RIS = clear screen + home cursor + reset rendition/charset/tabs/margins/modes; DECSTR = same minus screen/cursor/tabs). —lib/src/core/escape/parser.dart,lib/src/core/escape/handler.dart,lib/src/terminal.dart,lib/src/core/charset.dart,lib/src/utils/debugger.dart- HTS (
ESC H) was a no-op:setTapStop()called theTabStops.isSetAt()query instead ofsetAt(), so afterreset'sTBCcleared all stops, no stop was ever re-installed and Tab behaved erratically. Now it really sets the stop;setAt/clearAt/isSetAtare also bounds-safe so a stray HTS on ultra-wide (>1024 col) terminals can't crash. —lib/src/terminal.dart,lib/src/core/tabs.dart - Split escape sequences no longer leak as text:
Terminal.writefast-pathed any chunk without an ESC byte straight into the buffer, even while the parser held an incomplete sequence from the previous chunk (pty output splits at arbitrary boundaries). The continuation (;5;244m,c[!p…,H, …) printed as literal text and desynced the shell's cursor model, wrecking prompt redraws. The fast path is now skipped whileEscapeParser.hasPendingis true. —lib/src/terminal.dart,lib/src/core/escape/parser.dart - Tests: new
test/src/core/escape/reset_test.dart(9 cases, incl. a byte-exact capture of macOS/usr/bin/resetoutput for xterm-256color) andtest/src/terminal_write_split_test.dart(7 cases: SGR/RIS/HTS/OSC/CSI split across chunks).
1.5.7 - 2026-08-24 #
Bug Fixes #
- Search bar focus no longer crashes:
TerminalSearchBarused the sameFocusNodefor both its outerKeyboardListenerand innerTextField, triggeringTried to make a child into a parent of itselfwhen shown insideTerminalView'sFocus/CallbackShortcutstree. It now uses a dedicatedFocusScopeNodeto isolate the search bar focus tree and separateFocusNodes for the listener vs the text field.KeyboardVisibility.didChangeMetricsandRenderTerminal._onTerminalChangealso guard against detached/View.maybeOflookup duringresetPhysicalSizein tests. —lib/src/ui/search_bar.dart,lib/src/ui/keyboard_visibility.dart,lib/src/ui/render.dart - Kitty encoder keeps Enter fix across
withFlags:_KittyKeyboardEncoderWrapper.withFlagspreviously returned a bareKittyKeyboardEncoder, bypassing theEnter 8/28 → 13HID fix; now it stays wrapped._updateKittyKeyboardEncoderalso syncs_kittyEncoderto avoid stale flags on subsequent push/pop. —lib/src/terminal.dart - Dart format for stress tests: Two test files had stale formatting. —
test/stress/*
Chores #
- Dependencies:
image 4.9.1 → 4.9.2(patch), dropspetitparser/xmltransitives. —pubspec.lock - Package hygiene:
reasonix.toml,plans/,script/,tool/,run_test.shexcluded from pub.dev package via.pubignore(previously leaked, inflating compressed size).AGENTS.mdkitty_protocol version/doc typo fixes. —.pubignore,AGENTS.md
1.5.6 - 2026-08-12 #
Bug Fixes #
- Kitty KeyUp encoding only when
reportAllKeysAsEscapeis enabled: Previously, pressing a modifier (e.g. Cmd+V) and releasing it sent a Kitty KeyUp sequence even withoutreportAllKeysAsEscape, causing cursor jumping in the remote shell. The view layer now only encodes KeyUp when the application explicitly requested full key reporting. —lib/src/terminal_view.dart
Tests #
- Kitty KeyUp encoding behavior tests: Two cases verify that KeyUp with modifiers is NOT encoded in basic mode but IS encoded when
reportAllKeysAsEscapeis true. —test/kitty_flags_test.dart
Docs #
- Kitty keyboard protocol modes documentation: README now includes a table summarizing Basic vs Flags modes and their trigger sequences. Detailed protocol reference added at
doc/kitty_keyboard_protocol.md. —README.md,doc/kitty_keyboard_protocol.md
1.5.5 - 2026-08-06 #
Features #
- VT52 mode support: DECANM (
CSI ? 2 h/l) now switches the terminal between ANSI and VT52 modes, exposed asTerminalState.ansiMode.Keytab.find()accepts anansiflag and matches-Ansi(VT52) records: VT52 arrow keys emitESC A-ESC D, Shift+Tab falls back to plain tab — matching xterm behavior. ANSI mode remains the default, so existing keytab lookups are unchanged. —lib/src/core/input/keytab/keytab.dart,lib/src/core/state.dart,lib/src/core/escape/parser.dart,lib/src/terminal.dart
Tests #
- Plain-text fast path semantic equivalence tests: 8 cases verify
Terminal.write()'s fast path matches the parser path for ASCII, CJK wide chars, surrogate pairs, zero-width chars, last-column wrapping, charset translation, and REP consistency after wide/astral chars. —test/src/terminal_test.dart - Example app widget smoke tests: Two end-to-end tests pump the
mock.dartapp (pure-Dart MockRepl) verifying the welcome banner renders and Enter echoes back through the full input chain. —example/test/widget_test.dart - Kitty OSC query tests strengthened from no-crash guards to value assertions. —
test/kitty_*_test.dart
Docs #
terminal.dartrefactor re-evaluation recorded: Four minimal experiments confirm Dart classes cannot be split acrosspartfiles, but show mixin-chained splitting is technically feasible; refactor remains deferred (zero functional gain, high regression risk). —TODO-quality.md
Bug Fixes #
- Keytab parser no longer crashes on truncated input: A keytab ending mid-record previously null-checked with
!and threwTypeError; it now throwsParseErrorconsistently. —lib/src/core/input/keytab/keytab_parse.dart Observable.notifyListenersiterates a snapshot: Adding/removing listeners from inside a notification callback no longer throwsConcurrentModificationError(mirrorsChangeNotifiersemantics). —lib/src/base/observable.dartCellAnchordetached access throwsStateError: The guards wereasserts that vanish in release builds, leaving a raw null-check crash. —lib/src/core/buffer/line.dartIndexAwareCircularBuffer.swapbounds-checked: Out-of-range index now throwsRangeErrorlikeoperator []. —lib/src/utils/circular_buffer.dart- ZModem session race hardened:
_session!dereferences could crash when a timeout or user callback reset the session while an async chain was mid-flight; all paths now null-check or verify session identity. —lib/zmodem.dart TerminalController.searchno longer swallows real errors: The catch now wraps onlyRegExpcompilation; an invalid pattern still returns no results, but bugs in offset conversion surface instead of being silently ignored. —lib/src/ui/controller.dart
API #
- Export
GraphicsManagerfromcore.dart:Terminal.graphicsManager's type was previously unnameable outside the package (dark API). —lib/core.dart
Docs #
- Full dartdoc for
EscapeHandler: All 130+ interface methods now documented; staleTerminal.resizedoc corrected (reflow has shipped). —lib/src/core/escape/handler.dart,lib/src/terminal.dart - dartdoc for
GraphicsManagerfields,TerminalControllerandBuffer: Completes the public API documentation pass;Bufferclass doc now clarifies screen-relative vs absolute coordinates. —lib/src/core/graphics_manager.dart,lib/src/ui/controller.dart,lib/src/core/buffer/buffer.dart
Refactor #
- Merge
renderBelowImages/renderAboveImages: ~60 duplicated lines collapsed into one_renderImageswithoverlay+filterQualityparameters (behavior unchanged; below-text keepsFilterQuality.none, above-text keepsmedium). —lib/src/ui/painter.dart - Extract
_requestKeyboardFocusinTerminalViewto remove the duplicatedhardwareKeyboardOnlybranch in tap handling. —lib/src/terminal_view.dart
Testing #
- New direct tests for
Keytab.defaultKeytab(the ~700-line default table previously had zero coverage) and 5 truncated-input parse cases. —test/src/core/input/keytab/ - New image-rendering tests for the merged painter path (overlay filtering, out-of-range placements, no-manager case). —
test/src/ui/painter_test.dart - Merged the duplicate
cell_flagstest files, keeping both files' unique assertions. —test/src/core/buffer/cell_flags_test.dart
Publishing #
.pubignorekeepsexample/(lib + pubspec) so pub.dev scores the example, while excludingbuild/and platform directories to keep the package slim. —.pubignore
1.5.3 - 2026-07-10 #
Performance #
- Plain-text fast path in
Terminal.write(): BypassEscapeParserfor data chunks without escape sequences (\x1b). Plain text throughput improved from ~5 MB/s to ~18 MB/s (3.5x), significantly reducing CPU usage during high-throughput output (e.g.cat,tail -f, log streaming). —lib/src/terminal.dart - Add
writeString()toEscapeHandler: New interface method with default fallback to per-characterwriteChar(), enabling batch text writing for future optimizations. —lib/src/core/escape/handler.dart
1.5.2 - 2026-07-10 #
Bug Fixes #
- Fix reflow crash from CircularBuffer null pointer:
IndexAwareCircularBuffer.insert()silently returned no-op whenindex == 0 && _length >= _array.length, leaving null slots that causedNull check operator used on a null valueinreflow()—lib/src/utils/circular_buffer.dart - Fix eraseDisplayAbove RangeError from negative cursorX:
eraseLineToCursor()anderaseLineFromCursor()used raw_cursorXwithout clamping, causingUint32Listnegative-index crash whencursorXwas negative —lib/src/core/buffer/buffer.dart - Fix restoreCursor without bounds check:
Buffer.restoreCursor()assigned saved cursor values directly without clamping, allowing out-of-range cursor after terminal resize —lib/src/core/buffer/buffer.dart - Defensive padding after reflow: Ensure
Buffer.resize()always produces at leastnewHeightlines after reflow —lib/src/core/buffer/buffer.dart
Testing #
- Expand stress test coverage: Add multi-seed random fuzz (8 seeds), data integrity checks (all lines recoverable), cursor-bounds assertion after resize, and buffer cycling correctness —
test/stress/
1.5.1 - 2026-07-04 #
Bug Fixes #
- Fix input lag on key press / delete:
RenderTerminal._onTerminalChangedeferredmarkNeedsPaint()to a post-frame callback, adding a 1-frame delay (~16ms at 60Hz) on every visual update. NowmarkNeedsPaint()/markNeedsLayout()is called immediately, while the post-frame callback is only used to reset the coalescing guard —lib/src/ui/render.dart
1.5.0 - 2026-06-24 #
Bug Fixes #
- Fix htop-style apps showing spurious underlines on letters:
_flushRunparagraph cache key was missing theunderlineflag, causing cache collisions between underlined and non-underlined runs with identical text/color/weight/italic —lib/src/ui/painter.dart - Remove dead code:
paintCellUnderlinehad an unreachableCellAttr.underlineStyleSingleswitch case (single underline is handled by FlutterTextStylevia_flushRun) —lib/src/ui/painter.dart
1.4.2 - 2026-06-24 #
Performance #
- Coalesce notifications:
Terminal.write()defersnotifyListeners()via microtask, coalescing rapid data chunks (e.g.tail -f) into a single notification pass —lib/src/terminal.dart - Coalesce layout/paint:
RenderTerminal._onTerminalChangeusesaddPostFrameCallbackto merge multiple content changes within one frame into a single layout/paint pass —lib/src/ui/render.dart - Batch drawParagraph calls:
TerminalPainter.paintLinenow does two-pass rendering (background per-cell, foreground batched by style-run) so consecutive same-style characters produce onedrawParagraphinstead of one-per-cell —lib/src/ui/painter.dart - Skip unnecessary layout:
_onTerminalChangecallsmarkNeedsPaint()instead ofmarkNeedsLayout()when not scrolled to bottom;_onControllerUpdateusesmarkNeedsPaint()since selection/search changes are visual-only —lib/src/ui/render.dart
1.4.1 - 2026-06-23 #
Bug Fixes #
- Fix paste shortcut (Cmd+V/Ctrl+V) broken on Linux/Windows —
PasteTextIntenthandler now reads clipboard directly instead of depending on macOS-only IME path - Fix macOS IME paste duplicate: skip IME text when shortcut already handled paste
1.4.0 - 2026-06-22 #
Bug Fixes #
- Fix Kitty Graphics Protocol chunked transmission:
m=1(non-final) chunks now properly parse and accumulate payload data instead of leaving raw base64 in the parser queue - Fix X10 mouse protocol row coordinate encoding: remove extra
+1that caused CellOffset y to be reported as 2-based instead of 1-based - Fix tertiary (middle) mouse button gesture:
onTertiaryTapUpwas usingTerminalMouseButton.rightinstead of.middle, inconsistent withonTertiaryTapDown - Fix
KeyboardVisibiltyclass name typo: renamed toKeyboardVisibility(missing 'i')
Code Quality #
- Upgrade
kitty_protocoldependency from^1.2.3to^1.3.1 - Fix unused local variable warnings in
keyboard_visibility_test.dart
Tests #
- Add APC parser tests:
m=1with payload verifies dataChunk without commandEnd (2 tests)
1.3.0 - 2026-06-22 #
Bug Fixes #
- Fix Ctrl+letter combinations (Ctrl+U/A/E/C, etc.) being silently dropped in Kitty Keyboard Protocol mode — sends raw ASCII control characters for shell backward compatibility
- Fix Kitty Keyboard Protocol push/pop flag stack:
CSI > + n uandCSI > - usequences now correctly parse intermediate bytes (+/-) instead of stripping them - Fix
_KittyKeyboardEncoderWrapper.flagsreturning default values (wrapper now delegatesflagsto the inner encoder via super constructor) - Fix
_updateKittyKeyboardEncoderlazy init skipping the first push/pop call - Fix KeyUp events sending empty strings to
onOutputwhen Kitty encoder cannot encode the key - Fix modifier+letter keys (Alt+A, Meta+U, etc.) being dropped when Kitty encoder returns empty — fall back to standard keytab input
- Fix copy/paste/select-all shortcuts not working in Kitty mode (checked before Kitty dispatch now)
- Fix unknown CSI intermediate bytes in
>+sequences accidentally triggeringsetKittyMode
Code Quality #
- Refactor
_handleKeyEvent(180+ lines) into clean dispatcher: extract_handleKittyKeyEventand_tryKeyInputhelper, eliminating 3 duplicate keyInput patterns - Add
.pubignoreto exclude test, example, media, docs from published package
Documentation #
- Update AGENTS.md with comprehensive Kitty Keyboard Protocol architecture, test commands, and known limitations
- Fix README: correct Flutter version requirement to
>=3.19.0, fix screenshot URLs pointing to oldxterm.dartrepo, remove misleading "What's new in 3.0.0" section from fork - Fix README: merge duplicated "Key Features" and "Features" sections
Tests #
- Add CSI parser tests: push/pop with
+/-intermediate bytes (5 tests) - Add Terminal integration tests: push/pop flag stack, Ctrl+letter control codes via keyInput (9 tests, all 26 Ctrl+A–Z verified)
1.2.0 - 2025-07-11 #
Bug Fixes #
- Fix
_evictIfNeededmemory eviction loop: while condition now checks future memory state (current + required > target) instead of current memory, preventing leaked memory under 50% threshold - Fix
OverlayPortal.targetsRootOverlaydeprecation: replace withOverlayPortal(Flutter 3.33+) - Fix
handleTextSizeQuerydead code: remove unreachablecommand == 133branch
Code Quality #
- Migrate lint config from
package:lints/recommended.yamltopackage:flutter_lints/flutter.yaml(+30 Flutter-specific rules) - Fix 12 info-level lint issues:
unnecessary_library_name,unintended_html_in_doc_comment,avoid_print,sort_child_properties_last,prefer_const_constructors_in_immutables,sized_box_for_whitespace,avoid_unnecessary_containers - Add DCS (Kitty Remote Control), text size query, and shell integration test coverage (+19 tests)
- Add
_evictIfNeededLRU eviction edge-case tests: count limit, memory threshold, 50% target stop, LRU ordering (+4 tests) - Add
pointer_input_test.dartcompleting 100% test coverage for all 73lib/src/source files (+14 tests) - Fix
analysis_options.yaml: remove staledeprecated_member_use: ignore - Sync
AGENTS.mdCI command list with.github/workflows/dart-ci.yml
Bug Fixes #
- Fix SGR 38/48/58 malformed color recovery: incomplete color spec no longer causes subsequent params to be misparsed
- Add CSI params size limit (256) to prevent OOM from malformed sequences
- Remove dead code
case 10061000in DECSET handler
1.1.10 - 2026-05-18 #
Bug Fixes #
- Fix
Future.delayedzombie callback in graphics manager test: replace withtester.pump - Fix
gesture_detector.dartdouble-tap timer disposal on widget dispose
Code Quality #
- Fix test isolation: eliminate async callback leaks across test files
- Add
run_test.shunified test runner with smoke/full/golden/fuzz modes - Add
Makefilewith convenient targets:make test,make smoke,make golden,make fuzz - Add gesture detector timer cleanup verification (already had
dispose, confirmed correct)
1.1.9 - 2026-05-15 #
Bug Fixes #
- Fix example imports: replace removed
xterm.dartwithkterm.dartacross 6 files - Fix
withOpacitydeprecation: migrate towithValues(alpha:)(Flutter 3.27+)
Code Quality #
- Add
publish_to: 'none'to suppress invalid_dependency warning (zmodem_lbp git dep) - Add ZModem protocol decoding tests: ZMPHDR frame type parsing, file info header (29 new assertions across 7 tests)
- Clean up
AGENTS.mdwith accurate test commands
