npm / ink
ink
What changed in ink 6 to 8, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-17.
15 breaking32 new APIs and options2 performance11 behavior and defaults1 tooling56 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initink 853 changes
Breaking changes 11
Components sharing a focus ID are treated as one Tab stop, automatically generated IDs no longer collide, and an empty string is a valid focus ID.
The <Box> prop now only accepts numbers; use a number for a relative width calculated from window or parent metrics.
The <Box> prop now only accepts numbers; use a number for a relative width calculated from window or parent metrics.
onRender is called after the frame is written.
React 19.3 or later is now required.
<Static> output is no longer replayed on full-clear frames and is replayed when resuming re-enters the alternate screen.
The render() option and useStdout() expose generic Node.js streams; TTY-only properties such as columns are no longer part of the types.
Multiline text truncates each line separately, remains at natural width when there is no room to wrap, and no longer vanishes when it starts above the output.
Control characters other than tab and newline are stripped; tabs expand, and CRLF and zero-width spaces no longer overwrite nearby output.
Unrecognized terminal control sequences, including mouse reports and focus events, are dropped instead of being delivered to input handlers.
React DevTools now uses the native WebSocket instead of the ws dependency.
New APIs and options 6
A new <Box> prop supports building scrollable views when combined with overflow="hidden".
A new <Box> prop supports building scrollable views when combined with overflow="hidden".
measureElement() now provides clientHeight, the element's content-available height excluding borders.
measureElement() now provides clientWidth, the element's content-available width excluding borders.
useBoxMetrics() now provides clientHeight, the element's content-available height excluding borders.
useBoxMetrics() now provides clientWidth, the element's content-available width excluding borders.
Performance 1
Incremental rendering skips unchanged line prefixes and writes only the changed part of a line, reducing output and flicker.
Behavior and default changes 7
Application keypad Enter is now recognized as key.return.
render() accepts any Node.js stream for stderr, including PassThrough or other Writable streams.
render() accepts any Node.js stream for stdin; raw mode is used only when stdin is a TTY with setRawMode().
render() accepts any Node.js stream for stdout, including PassThrough or other Writable streams.
Enabling reportAssociatedText now automatically enables reportAllKeysAsEscapeCodes.
The render() option and useStderr() expose generic Node.js streams rather than TTY-specific types.
The render() option and useStdin() expose generic Node.js streams rather than TTY-specific types; raw mode is used only for a TTY with setRawMode().
Fixes and other changes 28
Styles are preserved across explicit newlines and combining marks across nested text styles; colon and C1 SGR sequences are normalized before layout.
Background colors now inherit correctly for <Static> and nested <Text>.
Terminal history is preserved after clear(), and rerendering restores the unchanged frame.
Invalid color names no longer crash rendering, and whitespace in RGB colors is handled correctly.
Ctrl+C is handled when it arrives together with ordinary input.
disableFocus() blurs the focused component as documented and prevents new components from auto-focusing when disabled.
Incremental rendering is corrected for single-line updates, new blank rows, and changed rows.
Legacy keyboard modifiers, modified SS3 keys, and Kitty keyboard parsing and detection are fixed.
Fractional percentages are no longer truncated in layout sizes, and layout defaults are restored when style props are undefined.
Parsing Meta keys no longer mutates the caller's buffer.
The callback remains stable across rerender() calls.
Clipping works when the overflow shorthand and an explicit axis are both set, and <Transform> line indices are preserved.
render() uses defaults for options that are undefined.
Error source excerpts work for file URLs and multiline messages, non-Error throws are treated as rendering failures, and renderToString() no longer swallows thrown undefined.
renderToString() no longer swallows a thrown undefined, and effect cleanup runs when output rendering fails.
Screen-reader output fixes cover semantic text and labels, empty <Transform> labels, rewrapping when the terminal widens, and restoring output after console writes.
<Static> output now handles repeated padding, margins, hidden ancestors, abandoned concurrent renders, identity changes, blank rows, and indirect subtree removal correctly.
Input-hook side effects are deferred while the terminal is suspended; suspension handles are idempotent and no longer restore released or unmounted-app input modes.
Cursor placement is corrected for output without a trailing newline, skipped component renders, and application exit.
The frame is redrawn when the terminal loses rows, and content above it is kept when rows shrink while the cursor is shown.
Clearing the viewport preserves scrollback and terminal history.
Output is preserved during non-interactive terminal suspension.
Text is remeasured when its wrapping mode or <Transform> wrap points change, and truncated-text measurement preserves available width.
useAnimation() values reset while paused.
Box metrics are tracked when a child attaches the ref after mount.
useWindowSize() no longer misses resizes that happen before it subscribes.
Visibility is preserved across Suspense transitions.
Styles and columns are preserved for clipped or overwritten wide characters.
ink 738 changes
Breaking changes 4
Pressing Backspace now sets key.backspace instead of key.delete; use key.backspace to detect physical Backspace presses.
Plain Escape no longer sets key.meta; key.meta is reserved for actual Alt/Meta modifier combinations.
Ink now requires Node.js 22.
Ink now requires React 19.2 or later.
New APIs and options 19
Adds suspendTerminal() to hand the terminal to a child process.
Adds the alignContent layout prop to Box.
Adds the aspectRatio layout prop to Box.
Adds borderBackgroundColor and per-side variants to Box, allowing border background color to be set independently from the box content background.
Adds the bottom layout prop to Box.
Adds the left layout prop to Box.
Adds the maxHeight prop to Box.
Adds the maxWidth prop to Box.
Adds position="static" as a Box layout prop.
Adds the alternateScreen option to render into the terminal's alternate screen buffer and restore previous terminal content on exit.
Adds the interactive option to override automatic interactive-mode detection when the built-in heuristic does not fit.
Adds the right layout prop to Box.
Adds the top layout prop to Box.
Adds built-in animation support with a frame counter, configurable interval, pause/resume support, and automatic cleanup on unmount.
Adds a hook for measuring box dimensions at runtime.
Adds activeId, which returns the ID of the currently focused component or undefined if nothing is focused.
Adds a hook for clipboard paste events that enables bracketed paste mode so pasted text arrives as a single string.
Adds a hook that returns terminal columns and rows and re-renders automatically when the terminal resizes.
Adds wrap="hard" to Text; it fills each line to the full column width, breaking words mid-word as needed.
Behavior and default changes 2
Also returns position coordinates.
Auto mode now queries all terminals instead of relying on a hardcoded allowlist.
Fixes and other changes 13
Preserves the last <Static> line that was erased after a full-clear frame.
Fixes stale frames on Windows when output exactly fills the terminal.
Handles incomplete stack frames in the error overview.
Full static output no longer retains stale <Static> output when identity changes.
A <Static> remount caused by a key change no longer drops new items.
Accepts ref objects whose initial value is null.
Defers disabling raw mode to prevent the process from hanging when a component is swapped.
Escape handling now respects disableFocus().
Restores the exit typing for useApp.
Fixes CJK text truncation that exceeded the Box width.
Fixes incremental rendering when output ends with a trailing newline.
Fixes a crash when useInput receives unmapped key codes.
Fixes splitting emoji and CJK wide characters when overlapping writes occur.
ink 626 changes
New APIs and options 7
Adds synchronous string output through renderToString().
Allows exit() to pass a result value to waitUntilExit().
Adds opt-in support for the kitty keyboard protocol.
Adds opt-in support for React concurrent rendering.
Adds an API for positioning the cursor for IME input.
Adds the incrementalRendering option.
Adds the onRender hook.
Performance 1
Improves performance by caching some expensive calls.
Behavior and default changes 2
Adds support for the end key in useInput.
Adds support for the home key in useInput.
Tooling 1
Adds support for react-devtools v7.
Fixes and other changes 15
Fixes handling of colored output from child processes.
Fixes support for hyperlinks.
Prevents keypresses from being dropped when multiple inputs arrive in one readable tick.
Fixes duplicated Static output on exit.
Handles stdout ending during unmount.
Fixes wrapping with nested Text components.
Fixes the trailing newline on the initial fullscreen render.
Fixes handling of Option+Return, or soft return, on macOS.
Adds synchronized updates, fixing flickering in many modern terminals.
Improves terminal size detection for piped processes.
Unmount now flushes pending renders and waits for stdout to drain.
Fixes MaxListenersExceededWarning when many useInput hooks are used.
Fixes some flicker during incremental rendering.
Fixes handling of terminal resize.
Fixes the color of
.dim.bold.