@samyx/repl-tui
v0.0.2
Published
A TUI (Terminal User Interface) builder using Ink (React) based on repl-builder definitions
Maintainers
Readme
@samyx/repl-tui
A TUI (Terminal User Interface) builder using Ink (React for CLI) based on repl-builder definitions.
Features
- Tabbed Navigation: Switch between Commands, History, and Direct REPL views
- Dynamic Forms: Automatically generates input forms from command argument/flag definitions
- Command History: Track all executed commands with their outputs
- Direct REPL Access: Raw terminal-like input for power users
- Themeable: Customize colors and appearance
- Works with any Node.js runtime: tsx, node, bun, etc.
Installation
npm install @samyx/repl-tui @samyx/repl-builder
# or
bun add @samyx/repl-tui @samyx/repl-builderQuick Start
import { replBuilder } from '@samyx/repl-builder';
import { createReplTui } from '@samyx/repl-tui';
// Build your REPL with commands
const repl = replBuilder()
.command({
name: 'greet',
description: 'Greet someone',
args: [{ name: 'name', description: 'Name to greet', required: true }],
flags: [{ name: 'loud', alias: 'l', description: 'Shout the greeting' }],
execute(args, ctx) {
const name = args[0];
const loud = args.includes('--loud') || args.includes('-l');
ctx.print(loud ? `HELLO ${name.toUpperCase()}!` : `Hello, ${name}!`);
return 0;
}
})
.build();
// Launch the TUI
createReplTui(repl);Run with:
npx tsx your-app.tsx
# or
bun run your-app.tsxConfiguration
TUI Configuration
import { createReplTui, type TuiConfig } from '@samyx/repl-tui';
const config: TuiConfig = {
// Title displayed at the top
title: 'My App',
// Initial tab to show: 'commands' | 'history' | 'repl'
initialTab: 'commands',
// Whether to show built-in commands (help, exit, etc.)
showBuiltins: true,
// Custom theme (Ink color names)
theme: {
primary: 'cyan',
secondary: 'blue',
error: 'red',
success: 'green',
warning: 'yellow',
muted: 'gray',
},
};
createReplTui(repl, config);Using ReplConfig Directly
You can also pass a ReplConfig object instead of a Repl instance:
import { createReplTui } from '@samyx/repl-tui';
createReplTui({
prompt: 'myapp> ',
includeBuiltins: true,
welcome: 'Welcome to My App!',
});Tabs
Commands Tab
- Lists all available commands
- Select a command to see its form
- Fill in arguments and flags
- Execute and see output in real-time
History Tab
- Browse all executed commands
- View output and errors for each entry
- Clear history when needed
Direct REPL Tab
- Raw terminal-like interface
- Type commands directly
- Full command history within the session
Keyboard Shortcuts
This TUI uses Vim-like modal navigation with two modes:
- NORMAL mode: Navigate with simple keys (no modifier keys needed)
- INSERT mode: Type into text fields
Modes
| Key | Action |
|-----|--------|
| i / Enter | Enter INSERT mode (edit text fields) |
| Escape | Return to NORMAL mode |
Normal Mode - Global
| Key | Action |
|-----|--------|
| 1 | Switch to Commands tab |
| 2 | Switch to History tab |
| 3 | Switch to Direct REPL tab (auto-enters INSERT) |
| ? | Open help modal |
| q | Quit the application |
Normal Mode - Commands Tab
| Key | Action |
|-----|--------|
| Tab | Switch focus between list and form |
| j / ↓ | Move down in list or form |
| k / ↑ | Move up in list or form |
| Enter | Select command / Go to form |
| e | Execute current command |
| Space | Toggle boolean flags |
| c | Clear form values |
| Escape | Return to command list |
Insert Mode
| Key | Action |
|-----|--------|
| Tab | Move to next field |
| Escape | Return to NORMAL mode |
| (type) | Edit the focused text field |
History Tab
| Key | Action |
|-----|--------|
| j / k / ↑ / ↓ | Navigate history entries |
| c | Clear all history |
Custom Components
For advanced use cases, you can import individual components:
import React from 'react';
import { render } from 'ink';
import {
Layout,
HistoryPanel,
DirectRepl,
createAdapter,
} from '@samyx/repl-tui';
const adapter = createAdapter(myRepl);
render(
<Layout adapter={adapter} config={{ title: 'Custom App' }} />
);Custom Hooks
For building custom TUI layouts:
import { useCommandState, useHistoryState } from '@samyx/repl-tui';
function MyCustomTui({ adapter }) {
const commandState = useCommandState(adapter);
const historyState = useHistoryState();
// Use the state managers in your custom components
}TypeScript Configuration
Add to your tsconfig.json:
{
"compilerOptions": {
"jsx": "react-jsx"
}
}Dependencies
ink- React for CLIink-text-input- Text input componentink-select-input- Selection componentreact- React framework@samyx/repl-builder- REPL builder (peer dependency)
License
MIT
