
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
opentui-rescript
Advanced tools
ReScript bindings for OpenTUI - Build terminal user interfaces with type-safe functional programming
ReScript bindings for OpenTUI - A TypeScript library for building terminal user interfaces.
✅ Full Type Safety - Leverages ReScript's powerful type system
✅ React Components - All OpenTUI React components available
✅ Hooks Support - Complete bindings for all OpenTUI hooks
✅ Functional Style - Natural functional programming patterns
✅ Pattern Matching - Use ReScript's pattern matching for event handling
# Install the package
npm install opentui-rescript
# Or with yarn/pnpm/bun
yarn add opentui-rescript
pnpm add opentui-rescript
bun add opentui-rescript
# You also need the peer dependencies
npm install @opentui/core @opentui/react react rescript
// App.res
open OpenTUI
@react.component
let make = () => {
<Box style={padding: 2, flexDirection: #column}>
<Text
content="Hello from ReScript!"
style={fg: Core.Colors.brightCyan}
/>
</Box>
}
// Start the app
render(<App />)->ignore
Container component with flexible layout options:
<Box
title="My Box"
style={
border: true,
borderStyle: #double,
padding: 2,
flexDirection: #column,
}>
{children}
</Box>
Display styled text:
<Text
content="Hello World"
style={
fg: Core.Colors.green,
attributes: Core.TextAttributes.bold,
}
/>
Text input field with event handlers:
<Input
placeholder="Enter text..."
value=inputValue
focused=isFocused
onInput={value => setInputValue(_ => value)}
onSubmit={value => handleSubmit(value)}
/>
Dropdown selection component:
let options = [
{label: "Option 1", value: "1"},
{label: "Option 2", value: "2"},
]
<Select
options
selectedIndex=0
focused=isFocused
onChange={(index, option) => handleChange(index, option)}
/>
Scrollable container:
<ScrollBox
focused=isFocused
style={height: 10, overflow: #scroll}>
{/* Long content */}
</ScrollBox>
Large ASCII text rendering:
<ASCIIFont
text="TITLE"
font="Standard"
style={fg: Core.Colors.brightYellow}
/>
Handle keyboard events:
Hooks.useKeyboard(key => {
switch key.name {
| Some("up") => moveUp()
| Some("down") => moveDown()
| Some("return") => submit()
| Some("c") when key.ctrl => exit()
| _ => ()
}
})
Access the renderer instance:
let renderer = Hooks.useRenderer()
switch renderer {
| Some(r) => // Use renderer
| None => ()
}
Get terminal size:
let (width, height) = Hooks.useTerminalDimensions()
Handle terminal resize:
Hooks.useResize((width, height) => {
Js.log2("Terminal resized to:", (width, height))
})
The package includes helpful custom hooks:
// Focus management
let (focusedIndex, isFocused, getFocusedItem) =
Hooks.useFocusManager(["input1", "input2", "button"])
// Input state management
let (value, handleInput, handleSubmit, clear) =
Hooks.useInput(~initialValue="", ~onSubmit=submitForm)
// Select state management
let (selectedIndex, handleChange, getSelectedOption) =
Hooks.useSelect(~options, ~defaultIndex=0)
Use predefined colors:
open OpenTUI.Core.Colors
let styles = {
fg: brightCyan,
bg: black,
borderColor: green,
}
Combine text attributes:
open OpenTUI.Core
let style = {
attributes: combineAttributes([
TextAttributes.bold,
TextAttributes.italic,
TextAttributes.underline,
])
}
Use helper functions for styled text:
open OpenTUI.Core
let styledText = bold(italic(fg(Colors.cyan, "Styled!")))
<Text content=styledText />
Complete style options:
let myStyle: OpenTUI.style = {
// Colors
fg: "#00ff00",
bg: "black",
// Layout
width: 40,
height: 10,
padding: 2,
margin: 1,
// Border
border: true,
borderStyle: #double,
borderColor: "blue",
// Flexbox
flexDirection: #row,
justifyContent: #center,
alignItems: #center,
gap: 2,
// Position
position: #absolute,
top: 5,
left: 10,
}
// examples/Counter.res
@react.component
let make = () => {
let (count, setCount) = React.useState(() => 0)
Hooks.useKeyboard(key => {
switch key.name {
| Some("up") => setCount(prev => prev + 1)
| Some("down") => setCount(prev => prev - 1)
| _ => ()
}
})
<Box>
<Text content={`Count: ${Int.toString(count)}`} />
</Box>
}
See examples/LoginForm.res for a complete login form implementation with:
# Build the ReScript code
bun run build
# Run examples
bun run example:basic
bun run example:counter
bun run example:login
The bindings expose all necessary types:
type style = { /* all style properties */ }
type keyInfo = { name: option<string>, ctrl: bool, alt: bool, shift: bool }
type selectOption = { label: string, value: string, disabled?: bool }
type renderer
# Install dependencies
bun install
# Build ReScript code
bun run build
# Watch mode for development
bun run watch
# Clean build artifacts
bun run clean
packages/rescript/
├── src/
│ ├── OpenTUI.res # Main module
│ ├── OpenTUI_Types.res # Type definitions
│ ├── OpenTUI_Core.res # Core utilities
│ ├── OpenTUI_Components.res # React components
│ └── OpenTUI_Hooks.res # React hooks
├── examples/
│ ├── Basic.res # Basic example
│ ├── Counter.res # Counter app
│ └── LoginForm.res # Login form
├── package.json
├── rescript.json
└── README.md
->)Contributions are welcome! Please feel free to submit issues or pull requests.
MIT - See the main OpenTUI repository for details.
FAQs
ReScript bindings for OpenTUI - Build terminal user interfaces with type-safe functional programming
We found that opentui-rescript demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.