You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Native Android terminal jumps upward when the keyboard opens #14464
Open a running terminal in the native Android T3 Code app.
Tap the terminal to open the software keyboard.
Repeat hiding and opening the keyboard, including while a full-screen agent CLI is running.
Expected behavior
The terminal and keyboard accessory move with the keyboard, keeping the current input visible without an abrupt upward jump.
Actual behavior
The terminal suddenly jumps upward as the keyboard opens. This is user-observed on native Android. I could not verify the animation on a device because device access is disabled in the current agent environment.
Impact
Major degradation during terminal input on a phone.
Version and investigation
The installed mobile version is unknown. Source inspection used main at c2fa9fc.
ThreadTerminalRouteScreen.tsx computes terminalBottomInset from useKeyboardState and immediately applies it as paddingBottom to the terminal container. In the pinned keyboard-controller source, that hook updates on keyboardWillShow and keyboardDidHide, whereas KeyboardStickyView follows animated keyboard height. Applying the final inset before the keyboard animation is an investigation lead, not a confirmed root cause. I have not patched it without native animation evidence.
Please check opening, closing, interactive dismissal, orientation changes and a second desktop view attached to the same PTY. This report concerns the native Android terminal, not the mobile web scrolling bug #2141. Android terminal input lag is already tracked in #12756 and software Backspace in #8253.
This is a real Android layout bug, and it's still there on main at c2fa9fc. It's not a duplicate of #2141 (open issue, mobile-web terminal scrolling), #12756 (open issue, per-keystroke echo delay), or #8253 (open issue, Backspace with FUTO). There's no device recording and the app version is unknown, but the jump follows directly from how the keyboard inset is applied today.
Opening the keyboard.ThreadTerminalRouteScreen makes room by adding useKeyboardState().height plus the 52 px accessory into terminalBottomInset and applying that as paddingBottom on the terminal container. In react-native-keyboard-controller 1.21.13, useKeyboardState only updates on keyboardWillShow and keyboardDidHide. On Android, keyboardWillShow fires at the start of the show animation with the final keyboard height, so the terminal snaps to its final size on the very first frame. In that same frame the Android bottom bar unmounts and the navigation-bar padding goes away. The accessory toolbar, on the other hand, lives in KeyboardStickyView and follows the animated keyboard height. So the toolbar glides up with the keyboard while the terminal has already jumped. Because KeyboardProvider is edge-to-edge, the window doesn't resize by itself; this padding change is the only thing making room, and it happens all at once.
Knock-on effect on the PTY. That snap also resizes the terminal. T3TerminalView.onSizeChanged reports the new row count and handleResize calls terminal.resize, so a full-screen CLI reflows immediately, and any other client attached to the same PTY gets the size change too (see #14463).
Closing the keyboard. This is jumpy in the other direction. keyboardWillHide dismisses the accessory right away, so the toolbar disappears at the start of the animation, but useKeyboardState ignores that event. The padding stays at the open height until keyboardDidHide, then snaps back and the bottom bar remounts. With an interactive dismiss, KeyboardStickyView follows your finger while the terminal padding stays stuck until the gesture ends.
How the chat screen avoids it.ThreadDetailScreen keeps the composer inside KeyboardStickyView and doesn't position it from useKeyboardState height. The keyboard-controller's Android callback also defers its animated start event specifically because a synchronous layout change at that moment can cancel the keyboard animation, and the terminal padding update is exactly that kind of change.
Fix direction. Move the terminal viewport with the animated keyboard inset, and send the PTY resize once the animation has settled rather than on every size change. On a device, it's worth checking open, close, interactive dismiss, orientation changes, and a second client attached to the same PTY.
Activity
juliusmarminge commentedon Sep 30, 2026
Triage
This is a real Android layout bug, and it's still there on
mainatc2fa9fc. It's not a duplicate of #2141 (open issue, mobile-web terminal scrolling), #12756 (open issue, per-keystroke echo delay), or #8253 (open issue, Backspace with FUTO). There's no device recording and the app version is unknown, but the jump follows directly from how the keyboard inset is applied today.Opening the keyboard.
ThreadTerminalRouteScreenmakes room by addinguseKeyboardState().heightplus the 52 px accessory intoterminalBottomInsetand applying that aspaddingBottomon the terminal container. Inreact-native-keyboard-controller1.21.13,useKeyboardStateonly updates onkeyboardWillShowandkeyboardDidHide. On Android,keyboardWillShowfires at the start of the show animation with the final keyboard height, so the terminal snaps to its final size on the very first frame. In that same frame the Android bottom bar unmounts and the navigation-bar padding goes away. The accessory toolbar, on the other hand, lives inKeyboardStickyViewand follows the animated keyboard height. So the toolbar glides up with the keyboard while the terminal has already jumped. BecauseKeyboardProvideris edge-to-edge, the window doesn't resize by itself; this padding change is the only thing making room, and it happens all at once.Knock-on effect on the PTY. That snap also resizes the terminal.
T3TerminalView.onSizeChangedreports the new row count andhandleResizecallsterminal.resize, so a full-screen CLI reflows immediately, and any other client attached to the same PTY gets the size change too (see #14463).Closing the keyboard. This is jumpy in the other direction.
keyboardWillHidedismisses the accessory right away, so the toolbar disappears at the start of the animation, butuseKeyboardStateignores that event. The padding stays at the open height untilkeyboardDidHide, then snaps back and the bottom bar remounts. With an interactive dismiss,KeyboardStickyViewfollows your finger while the terminal padding stays stuck until the gesture ends.How the chat screen avoids it.
ThreadDetailScreenkeeps the composer insideKeyboardStickyViewand doesn't position it fromuseKeyboardStateheight. The keyboard-controller's Android callback also defers its animated start event specifically because a synchronous layout change at that moment can cancel the keyboard animation, and the terminal padding update is exactly that kind of change.Fix direction. Move the terminal viewport with the animated keyboard inset, and send the PTY resize once the animation has settled rather than on every size change. On a device, it's worth checking open, close, interactive dismiss, orientation changes, and a second client attached to the same PTY.