vadimdemedes/ink
54.9
Adequate · 28 September 2026
10.5k
lines of production code
TypeScript
primary language
4
measurements over time
What this system is
This system is a library for building interactive terminal user interfaces using React. It provides a rendering engine that translates React components into terminal output, supporting features like layout management, input handling, and accessibility. The system enables developers to create dynamic CLI applications with capabilities such as routing, animations, and concurrent rendering.
How it got here
2017–2020 — v2 rewrite and modernization
10 changes.
The project underwent a major v2 rewrite, migrating to TypeScript, ESM, and React hooks while replacing the custom virtual DOM with a Yoga-based layout engine and a custom React reconciler. This period introduced comprehensive accessibility features, new hooks for input and focus management, and significantly expanded test coverage to support the new architecture and modern Node.js requirements.
2023–2024 — Comprehensive example suite expansion
8 changes.
This period focused on expanding the library's documentation and reference materials by adding a wide variety of React-based example applications. These additions covered core rendering features, state management, layout controls, and advanced patterns like Suspense and incremental updates to demonstrate Ink's capabilities in terminal environments.
2025–2026 — comprehensive examples expansion
14 changes.
This period focused on significantly expanding the project's example suite to demonstrate advanced terminal UI capabilities. New examples covered accessibility, concurrent rendering, routing, animations, and complex input handling, while also adding new features like border background colors and terminal suspension support.
Features
Add ARIA accessibility example
Added a new example demonstrating screen reader and ARIA support, featuring a toggleable checkbox with aria-role and aria-state attributes, as well as text hidden from screen readers via aria-hidden.
examples/aria · high confidence
Add Box background color example
The examples/box-backgrounds directory now includes a demonstration of the Box component's backgroundColor prop, showcasing support for named colors, hex codes, and RGB values, as well as background inheritance in nested structures.
examples/box-backgrounds · high confidence
Add Suspense example demonstrating React Suspense with Ink
The examples/suspense directory now includes an entry point and a component that demonstrates how to use React Suspense with the Ink library. The example implements a data-reading pattern that throws a promise to trigger a loading state, rendering a 'Loading...' fallback via React.Suspense before displaying the resolved 'Hello World' message.
examples/suspense · high confidence
Add accessible select-input example with screen reader support
The examples/select-input location now includes a new interactive component that allows users to select from a list of items using arrow keys. This example specifically implements accessibility features by detecting when a screen reader is enabled and providing appropriate ARIA roles (list, listitem), states (selected), and labels to ensure the component is usable for assistive technology users.
examples/select-input · high confidence
Add alternate-screen example demonstrating terminal screen buffer usage
A new example application has been added to the \examples/alternate-screen\ directory, showcasing the use of the \alternateScreen\ option. This example implements a playable Snake game using React components (\Text\, \Box\, \useInput\, etc.) that leverages the terminal's alternate screen buffer for a dedicated game view, complete with state management, collision detection, and rendering logic.
examples/alternate-screen · high confidence
Add border background color support for Box component
The Box component now supports a \borderBackgroundColor\ prop, allowing users to render a colored background behind the border itself. This example demonstrates the feature with solid colors, per-side variations (e.g., different colors for top, bottom, left, and right borders), and dimmed RGB/hex color support.
examples/border-backgrounds · high confidence
Add borders and counter example applications
New example applications have been added to demonstrate library capabilities. The borders example showcases various box border styles (single, double, round, bold, singleDouble, doubleSingle, classic) using the Box and Text components. The counter example demonstrates state management and side effects using React hooks (useState, useEffect) to display a live-updating test count.
examples/borders, examples/counter · high confidence
Add examples for concurrent rendering features
New example files have been added to demonstrate React's concurrent rendering capabilities. The \use-transition\ example shows how to keep the UI responsive during expensive computations by deferring state updates with \useTransition\, while the \concurrent-suspense\ example illustrates how \Suspense\ boundaries work with concurrent mode to handle asynchronous data fetching gracefully.
examples/use-transition · high confidence
Add incremental rendering example
Added a new example in the \examples/incremental-rendering\ directory that demonstrates incremental rendering capabilities. The demo application (\incremental-rendering.tsx\) showcases live UI updates, including a dynamic log viewer, progress bars, and service status indicators, while utilizing the \useWindowSize\ hook to adapt to terminal dimensions.
examples/incremental-rendering, examples/subprocess-output · high confidence
Add interactive table example using React and Ink
The examples/table directory now includes a new demonstration of rendering a tabular layout using the Ink library and React. This example showcases how to structure data with Box and Text components to display a list of users with ID, Name, and Email columns, providing a concrete reference for building complex, multi-column terminal interfaces.
examples/table · high confidence
Add maxFps option to render throttle example
The render-throttle example now demonstrates how to limit the rendering frequency by passing a maxFps option to the render function, allowing users to see how throttling works at a specific frame rate (e.g., 10fps) rather than the default.
examples/render-throttle · high confidence
Add terminal chat example application
Introduced a new interactive chat example in the \examples/chat\ directory. The \chat.tsx\ file implements a terminal-based UI using the library's \Box\, \Text\, and \useInput\ components, allowing users to type messages that are displayed in a scrollable list, with support for backspace and grapheme-segmented input handling. The \index.ts\ file serves as the entry point to run this example.
examples/chat · high confidence
Add terminal routing example using React Router's MemoryRouter
A new example in the router directory demonstrates how to implement client-side routing within a terminal-based React application. It utilizes React Router's MemoryRouter to manage navigation between Home and About views, allowing users to switch pages by pressing Enter and quit the application by pressing 'q'.
examples/router · high confidence
Add terminal-resize example demonstrating dynamic window size updates
A new example has been added to the examples/terminal-resize directory that demonstrates how to use the useWindowSize hook to display and react to terminal resize events. The example renders the current number of columns and rows, updating them in real-time as the terminal size changes, and includes instructions for users to resize their terminal or press Ctrl+C to exit.
examples/terminal-resize · high confidence
Added React-based benchmark examples for simple and static rendering
New benchmark scripts have been added to the \benchmark/simple\ and \benchmark/static\ directories to measure rendering performance. The simple benchmark repeatedly rerenders a static component tree, while the static benchmark demonstrates the \Static\ component by incrementally adding items to the output. These examples utilize the library's React integration, importing \render\, \Box\, \Text\, and \Static\ from the source to validate behavior under load.
benchmark · high confidence
Added SVG and React demo assets for the media directory
The media directory now includes a new SVG file (demo.svg) and a React component file (demo.tsx). The SVG provides an animated, static-image representation of a terminal session showing test results, while the TSX file implements the interactive React logic for that demo using the project's Box and Text components. These assets serve as visual and code examples for the library's capabilities.
media · high confidence
Added example demonstrating space-evenly justification
The examples/justify-content directory now includes a demo that renders a layout using the space-evenly value for the justifyContent attribute, illustrating how child elements are distributed with equal spacing before, between, and after them.
examples/justify-content · high confidence
New React hooks for animations, focus management, and input handling
This change introduces a suite of new React hooks in the \src/hooks\ directory to enhance application interactivity and state management. The \useAnimation\ hook provides a consolidated timer for driving animations with frame, time, and delta metrics. Focus management is expanded with \useFocus\ for per-component focus state and \useFocusManager\ for global navigation (next/previous/programmatic focus). Input handling is significantly upgraded with \useInput\ (supporting arrow, page, home/end, and modifier keys), \usePaste\ for bracketed paste mode, and \useCursor\ for precise cursor positioning. Additionally, \useBoxMetrics\ exposes layout dimensions for DOM elements, \useWindowSize\ tracks terminal resize events, and \useIsScreenReaderEnabled\ exposes accessibility state. Supporting hooks \useApp\, \useStdin\, \useStdout\, and \useStderr\ provide access to application lifecycle and stream contexts.
src/hooks · high confidence
New accessibility, focus, and context infrastructure
The component layer now includes dedicated React contexts for accessibility, focus management, animations, and I/O streams, enabling screen-reader support, programmatic focus navigation, and structured error reporting. New components like \<Static\> for permanent output, \<Transform\> for string-level text effects, \<Spacer\> for layout, and \<Newline\> for spacing are introduced, while \<Box\> and \<Text\> gain ARIA attributes and background-color inheritance to improve accessibility and styling consistency.
src/components · high confidence
New cursor-ime example for handling IME input and wide characters
Added a new example demonstrating correct cursor positioning and input handling for Internationalized Input Method Editors (IME) and wide characters (such as Korean, CJK, and emoji). The example uses grapheme segmentation to ensure backspace and text entry work correctly with multi-byte characters, and manually manages cursor placement to prevent display issues at terminal edges.
examples/cursor-ime · high confidence
New example demonstrating terminal suspension for child processes
Added a new example in the \examples/suspend-terminal\ directory that showcases the \suspendTerminal()\ API. This demo illustrates how an Ink application can temporarily release control of the terminal to a child process (such as an external editor or a shell prompt) and then resume, preserving the application's internal state like the counter value.
examples/suspend-terminal · high confidence
New example demonstrating the useAnimation hook for built-in animation support
An example application has been added to the examples/use-animation directory that showcases the new useAnimation hook. This demo renders a terminal-based animation featuring a moving unicorn with a rainbow trail, sparkling text effects, and a loading spinner, all driven by the hook's frame counters at different intervals. It also includes input handling to pause and resume the animations, illustrating how to integrate the hook into a React component for interactive visual updates.
examples/use-animation · high confidence
New scroll example demonstrating content offset and metrics
Added a new example in the \examples/scroll\ directory that demonstrates scrolling capabilities using \contentOffsetX\ and \contentOffsetY\ props along with client and scroll size metrics. The example implements a \ScrollView\ component that handles vertical and horizontal scrolling via arrow keys, clamps scroll positions to content bounds, and displays real-time metrics for scroll offsets and dimensions.
examples/scroll · high confidence
New stdout and stderr usage examples
Added new example applications demonstrating the use of the \useStdout\ and \useStderr\ hooks. The \use-stdout\ example shows how to write to standard output and access terminal window dimensions, while the \use-stderr\ example demonstrates writing to standard error.
examples/use-stdout · high confidence
New terminal UI examples for testing, static rendering, and focus management
Added new example applications demonstrating core library capabilities: a Jest-style test runner simulation using concurrent queues and dynamic updates, a static list rendering example, and interactive demos for keyboard input handling and focus management (including named focus IDs). These examples serve as practical references for building terminal-based React interfaces.
examples/jest · high confidence
Removals
Removal of core virtual DOM and component runtime libraries
The \lib\ directory has been completely removed, deleting all source files that implemented the virtual DOM diffing engine, component lifecycle management, and rendering logic. This eliminates the ability to create, mount, update, or unmount virtual DOM trees and renders the library non-functional for its primary purpose of UI rendering.
lib · high confidence
Removal of legacy string component modules
The \colors\, \group\, \indent\, and \newline\ modules in \lib/components\ have been deleted. This removes the previous implementations for applying chalk styles, grouping children, adding indentation, and inserting OS-specific end-of-line characters, indicating a shift away from these specific string-component abstractions in the current version.
lib/components · high confidence
Behavioural changes
Major v2 release with React hooks, ESM, and TypeScript
Ink has been upgraded to version 2, introducing a significant behavioral change for users: the API now requires React hooks (such as useState and useEffect) and functional components instead of the previous class-based Component pattern. The library has been migrated to ESM and TypeScript, requiring Node.js 18 or later, and the entry point has changed from 'vadimdemedes/ink' to 'ink' with 'react' as a peer dependency. The 'mount' function has been replaced by 'render', and the project now uses the standard 'h' JSX pragma rather than a custom one.
(repo-wide) · high confidence
Rewrite of core rendering engine and introduction of Yoga-based layout
The library has been rewritten in TypeScript and now uses the Yoga layout engine for layout calculations, replacing the previous text-measurement approach. This change introduces a new DOM-like node structure (ink-root, ink-box, ink-text) and a custom React reconciler to manage the virtual tree. The rewrite also brings support for React Concurrent Rendering, Suspense, and React DevTools integration, while removing the previous app, stdin, and stdout contexts in favor of hooks.
src · high confidence
Test coverage
Expanded test coverage for terminal rendering, styling, and input handling; Expanded test fixtures for rendering, input, and lifecycle behaviors.
Dependencies
Major version 7.1.1 release with Node 22 requirement and React 19 support
The package has been upgraded to version 7.1.1, shifting the minimum Node.js engine requirement from version 4 to 22 and adopting an ESM module structure with TypeScript compilation. React support has been updated to version 19, with React and its types moved to optional peer dependencies to allow flexible versioning. The dependency list has been significantly modernized, replacing older utilities with newer versions of packages like Chalk (v6), wrap-ansi (v10), and the reconciler (v0.34.0), while dev dependencies such as Ava (v7) and XO (v2) have also been upgraded to their latest major versions.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 45 → 55 (+9.4)
- Rubric changed (rubric-2026.08.15 → rubric-2026.09.16) — scores are not directly comparable.
Lenses
- Code Health 74 → 71 (-2.6)
- Architecture 78 (new)
- Maturity 42 → 42 (-0.6)
- Readiness 32 → 54 (+22.2)
- Security 87 → 96 (+9.5)
- Performance 85 (new)
Resolved (18)
- Boundary-crossing change coupling: StdinContext.ts ↔ use-input.ts (src/components/StdinContext.ts)
- Change coupling: get-max-width.ts ↔ render-node-to-output.ts (src/get-max-width.ts)
- Change coupling: get-max-width.ts ↔ styles.ts (src/get-max-width.ts)
- Change coupling: ink.tsx ↔ renderer.ts (src/ink.tsx)
- Change coupling: reconciler.ts ↔ renderer.ts (src/reconciler.ts)
- Change coupling: render-border.ts ↔ styles.ts (src/render-border.ts)
- Change coupling: render-node-to-output.ts ↔ renderer.ts (src/render-node-to-output.ts)
- Dimension evaluation failed
- High: security finding (details withheld)
- High: security finding (details withheld)
- Hotspot: src/ansi-tokenizer.ts (src/ansi-tokenizer.ts)
- Hotspot: src/hooks/use-input.ts (src/hooks/use-input.ts)
- Hotspot: test/helpers/reconstruct-terminal.ts (test/helpers/reconstruct-terminal.ts)
- No automated tests
- No exposed public API
- No tests found
- Scanner failed to run — not a clean result
- Test reliability not included
New (60)
- App.App (cognitive 112) (src/components/App.tsx)
- App.App (cyclomatic 95) (src/components/App.tsx)
- ClassTooLong: App (src/components/App.tsx)
- ClassTooLong: Ink (src/ink.tsx)
- Dependency hygiene PARTLY measured — npm pinning read, dependency currency not (no committed lockfile, so no resolved version to grade)
- ErrorOverview.ErrorOverview (cognitive 28) (src/components/ErrorOverview.tsx)
- ErrorOverview.ErrorOverview (cyclomatic 20) (src/components/ErrorOverview.tsx)
- FileTooLong: components/App.tsx (src/components/App.tsx)
- FileTooLong: src/ink.tsx (src/ink.tsx)
- FunctionTooLong: App.App (src/components/App.tsx)
- FunctionTooLong: ansi-tokenizer.tokenizeAnsi (src/ansi-tokenizer.ts)
- High: security finding (details withheld)
- High: security finding (details withheld)
- Hotspot: src/components/App.tsx (src/components/App.tsx)
- Hotspot: src/components/Text.tsx (src/components/Text.tsx)
- Hotspot: src/output.ts (src/output.ts)
- Hotspot: src/parse-keypress.ts (src/parse-keypress.ts)
- Hotspot: src/render-node-to-output.ts (src/render-node-to-output.ts)
- Hotspot: src/wrap-text.ts (src/wrap-text.ts)
- Ink.renderFrame (cognitive 26) (src/ink.tsx)
- …and 40 more
Changes since last survey
- 77 commits — 59 feature/other, 18 fixes
By area
- src/ink.tsx — 14 commits
- src/components — 13 commits
- src/dom.ts — 6 commits
- src/output.ts — 6 commits
- (root) — 5 commits
- test/fixtures — 5 commits
- src/render-to-string.ts — 4 commits
- src/sanitize-ansi.ts — 4 commits
- src/parse-keypress.ts — 3 commits
- src/squash-text-nodes.ts — 3 commits
- src/hooks — 2 commits
- src/log-update.ts — 2 commits
- src/wrap-text.ts — 2 commits
- examples/scroll — 1 commit
- src/colorize.ts — 1 commit
- src/cursor-helpers.ts — 1 commit
- src/input-parser.ts — 1 commit
- src/reconciler.ts — 1 commit
- src/styles.ts — 1 commit
- test/clear-rerender.tsx — 1 commit
Notable commits
- fix: Fix Static rendering
- fix: Fix renderToString error handling
- fix: Fix wrapText cache key collision between different texts and widths (#998)
- fix: Fix and improve examples
- fix: Fix background color inheritance
- fix: Fix color parsing
- fix: Fix error reporting
- fix: Fix focus management
- fix: Fix keyboard input parsing
- fix: Fix layout style handling
- fix: Fix multi-line <Text> vanishing when it starts above the top of the output (#1001)
- fix: Fix node visibility and text measurement updates
- fix: Fix overflow clipping
- fix: Fix screen-reader output
- fix: Fix text output edge cases
- fix: Fix unbounded text caches
- fix: Fix useWindowSize missing resizes before subscription
- fix: Fix: Clear viewport with home + erase-down instead of clearTerminal to preserve scrollback (#994)
- change: Add scrolling primitives: contentOffsetX/contentOffsetY props and client/scroll size metrics (#988)
- change: Align minWidth and maxWidth types with supported values (#1033)
- …and 57 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
vadimdemedes/ink was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 28 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 7cd7fd94eeaf018d6acaeac82a562f5785fb1c4e — the exact code this score is about.
- Scored under rubric-2026.09.16 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-24a00d372a4b.