Terminal task list library for creating beautiful, interactive CLI interfaces with task management, rendering options, and error handling.
npx @tessl/cli install tessl/npm-listr2@8.3.00
# Listr2
1
2
Listr2 is a modern terminal task list library for Node.js that creates beautiful, interactive CLI interfaces. It provides multiple built-in renderers (default, verbose, silent, simple, test) with customizable themes and colors, supports nested task lists with concurrent and sequential execution modes, and includes comprehensive error handling and retry mechanisms with built-in progress indicators and spinners.
3
4
## Package Information
5
6
- **Package Name**: listr2
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install listr2`
10
11
## Core Imports
12
13
```typescript
14
import { Listr } from "listr2";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { Listr } = require("listr2");
21
```
22
23
Additional imports:
24
25
```typescript
26
import {
27
Listr,
28
ListrTaskState,
29
ListrError,
30
ListrEventManager,
31
ListrTaskEventManager,
32
EventManager,
33
DefaultRenderer,
34
SimpleRenderer,
35
VerboseRenderer,
36
PRESET_TIMER,
37
PRESET_TIMESTAMP
38
} from "listr2";
39
```
40
41
## Basic Usage
42
43
```typescript
44
import { Listr } from "listr2";
45
46
const tasks = new Listr([
47
{
48
title: "Installing dependencies",
49
task: () => {
50
// Simulate async work
51
return new Promise(resolve => setTimeout(resolve, 2000));
52
}
53
},
54
{
55
title: "Building project",
56
task: (ctx, task) => {
57
// Access task wrapper for output
58
task.output = "Compiling TypeScript...";
59
return new Promise(resolve => setTimeout(resolve, 3000));
60
}
61
},
62
{
63
title: "Running tests",
64
task: () => {
65
return new Promise(resolve => setTimeout(resolve, 1000));
66
}
67
}
68
]);
69
70
// Run the task list
71
try {
72
await tasks.run();
73
console.log("All tasks completed successfully!");
74
} catch (error) {
75
console.error("Tasks failed:", error);
76
}
77
```
78
79
## Architecture
80
81
Listr2 is built around several key components:
82
83
- **Listr Class**: Main orchestrator that manages task execution, context sharing, and renderer coordination
84
- **Task System**: Individual task management with state tracking, retry logic, and nested task support
85
- **Renderer System**: Pluggable rendering engines for different output formats (TTY, non-TTY, testing)
86
- **Event Management**: Observable-based event system for task state changes and lifecycle events
87
- **Context Sharing**: Type-safe context object passed between tasks for data sharing
88
- **Error Handling**: Comprehensive error collection and reporting with rollback capabilities
89
90
## Capabilities
91
92
### Core Task Management
93
94
Main Listr class for creating and executing task lists with context sharing, concurrent execution, and error handling.
95
96
```typescript { .api }
97
class Listr<Ctx = ListrContext, Renderer = ListrPrimaryRendererValue, FallbackRenderer = ListrSecondaryRendererValue> {
98
constructor(
99
task: ListrTask<Ctx, Renderer, FallbackRenderer> | ListrTask<Ctx, Renderer, FallbackRenderer>[],
100
options?: ListrBaseClassOptions<Ctx, Renderer, FallbackRenderer>,
101
parentTask?: Task<any, Renderer, FallbackRenderer>
102
);
103
104
add(tasks: ListrTask<Ctx, Renderer>[] | ListrTask<Ctx, Renderer>): void;
105
run(context?: Ctx): Promise<Ctx>;
106
isRoot(): boolean;
107
isSubtask(): boolean;
108
}
109
```
110
111
[Task Management](./task-management.md)
112
113
### Task Configuration and Lifecycle
114
115
Individual task definition, execution control, and lifecycle management including skip conditions, retry logic, and rollback functionality.
116
117
```typescript { .api }
118
interface ListrTask<Ctx, Renderer, FallbackRenderer> {
119
title?: string | any[];
120
task: ListrTaskFn<Ctx, Renderer, FallbackRenderer>;
121
enabled?: boolean | ((ctx: Ctx) => boolean | Promise<boolean>);
122
skip?: boolean | string | ((ctx: Ctx) => boolean | string | Promise<boolean | string>);
123
retry?: number | { tries: number; delay?: number };
124
rollback?: ListrTaskFn<Ctx, Renderer, FallbackRenderer>;
125
exitOnError?: boolean | ((ctx: Ctx) => boolean | Promise<boolean>);
126
}
127
128
type ListrTaskFn<Ctx, Renderer, FallbackRenderer> = (
129
ctx: Ctx,
130
task: TaskWrapper<Ctx, Renderer, FallbackRenderer>
131
) => void | ListrTaskResult<Ctx>;
132
```
133
134
[Task Configuration](./task-configuration.md)
135
136
### Rendering System
137
138
Multiple built-in renderers for different environments and use cases, with customizable options and TTY detection.
139
140
```typescript { .api }
141
type ListrRendererValue = 'default' | 'simple' | 'verbose' | 'test' | 'silent' | ListrRendererFactory;
142
143
interface ListrBaseClassOptions<Ctx, Renderer, FallbackRenderer> {
144
renderer?: Renderer;
145
fallbackRenderer?: FallbackRenderer;
146
rendererOptions?: ListrGetRendererOptions<ListrGetRendererClassFromValue<Renderer>>;
147
fallbackRendererOptions?: ListrGetRendererOptions<ListrGetRendererClassFromValue<FallbackRenderer>>;
148
fallbackRendererCondition?: boolean | (() => boolean);
149
silentRendererCondition?: boolean | (() => boolean);
150
}
151
```
152
153
[Renderers](./renderers.md)
154
155
### Event Management
156
157
Observable-based event system for monitoring task state changes, progress updates, and lifecycle events.
158
159
```typescript { .api }
160
class ListrEventManager extends EventManager {
161
// Inherits all EventManager functionality
162
}
163
164
class ListrTaskEventManager extends EventManager {
165
// Inherits all EventManager functionality
166
}
167
168
enum ListrTaskEventType {
169
TITLE = 'TITLE',
170
STATE = 'STATE',
171
ENABLED = 'ENABLED',
172
SUBTASK = 'SUBTASK',
173
PROMPT = 'PROMPT',
174
OUTPUT = 'OUTPUT',
175
MESSAGE = 'MESSAGE',
176
CLOSED = 'CLOSED'
177
}
178
```
179
180
[Event Management](./event-management.md)
181
182
### Error Handling and States
183
184
Comprehensive error handling system with task state management, error collection modes, and rollback capabilities.
185
186
```typescript { .api }
187
class ListrError<Ctx> extends Error {
188
public path: string[];
189
public ctx: Ctx;
190
constructor(error: Error, type: ListrErrorTypes, task: Task);
191
}
192
193
enum ListrTaskState {
194
WAITING = 'WAITING',
195
STARTED = 'STARTED',
196
COMPLETED = 'COMPLETED',
197
FAILED = 'FAILED',
198
SKIPPED = 'SKIPPED',
199
ROLLING_BACK = 'ROLLING_BACK',
200
ROLLED_BACK = 'ROLLED_BACK',
201
RETRY = 'RETRY',
202
PAUSED = 'PAUSED',
203
PROMPT = 'PROMPT',
204
PROMPT_COMPLETED = 'PROMPT_COMPLETED',
205
PROMPT_FAILED = 'PROMPT_FAILED'
206
}
207
208
enum ListrErrorTypes {
209
WILL_RETRY = 'WILL_RETRY',
210
WILL_ROLLBACK = 'WILL_ROLLBACK',
211
HAS_FAILED_TO_ROLLBACK = 'HAS_FAILED_TO_ROLLBACK',
212
HAS_FAILED = 'HAS_FAILED',
213
HAS_FAILED_WITHOUT_ERROR = 'HAS_FAILED_WITHOUT_ERROR'
214
}
215
```
216
217
[Error Handling](./error-handling.md)
218
219
### Presets and Utilities
220
221
Built-in formatting presets for timestamps and timers, plus utility functions for environment detection and UI formatting.
222
223
```typescript { .api }
224
// Timer preset for displaying elapsed time
225
const PRESET_TIMER: PresetTimer;
226
type PresetTimer = LoggerFieldFn<[number]>;
227
228
interface RendererPresetTimer {
229
/** Show duration for the tasks */
230
timer?: PresetTimer;
231
}
232
233
// Timestamp preset for displaying current time
234
const PRESET_TIMESTAMP: PresetTimestamp;
235
type PresetTimestamp = LoggerFieldFn;
236
237
interface RendererPresetTimestamp {
238
/** Show timestamp for each event that has been logged */
239
timestamp?: PresetTimestamp;
240
}
241
242
interface LoggerFieldFn<Args extends any[] = any[]> {
243
/** The value of the given field */
244
field: ((...args: Args) => string) | string;
245
/** Condition to display the given field */
246
condition?: ((...args: Args) => boolean) | boolean;
247
/** Formatting/coloring of the field */
248
format?: (...args: Args) => LoggerFormat;
249
/** Args to pass to other functions whenever this field is triggered */
250
args?: Args;
251
}
252
253
type LoggerFormat = (message?: string) => string;
254
255
// Utility functions
256
function getRenderer<Renderer extends ListrRendererValue, FallbackRenderer extends ListrRendererValue>(options: {
257
renderer: Renderer;
258
rendererOptions: ListrGetRendererOptions<Renderer>;
259
fallbackRenderer: FallbackRenderer;
260
fallbackRendererOptions: ListrGetRendererOptions<FallbackRenderer>;
261
fallbackRendererCondition?: boolean | (() => boolean);
262
silentRendererCondition?: boolean | (() => boolean);
263
}): SupportedRenderer<ListrRendererFactory>;
264
function getRendererClass(renderer: ListrRendererValue): ListrRendererFactory;
265
```
266
267
## Common Types
268
269
```typescript { .api }
270
type ListrContext = Record<PropertyKey, any>;
271
272
type ListrTaskResult<Ctx> =
273
| string
274
| Promise<any>
275
| Listr<Ctx, any, any>
276
| ReadableLike
277
| ObservableLike<any>;
278
279
interface ObservableLike<T> {
280
subscribe: (observer: ObserverLike<T>) => unknown;
281
}
282
283
interface ReadableLike {
284
readable: boolean;
285
read: (size?: number) => string | Buffer;
286
on: (eventName: 'data' | 'error' | 'end', listener: (data: Buffer | string) => void) => unknown;
287
}
288
289
enum ListrEnvironmentVariables {
290
FORCE_UNICODE = 'LISTR_FORCE_UNICODE',
291
FORCE_TTY = 'LISTR_FORCE_TTY',
292
DISABLE_COLOR = 'NO_COLOR',
293
FORCE_COLOR = 'FORCE_COLOR'
294
}
295
296
// Helper types for renderer-related generics
297
type ListrGetRendererClassFromValue<T extends ListrRendererValue> =
298
T extends ListrRendererFactory ? T :
299
T extends 'default' ? typeof DefaultRenderer :
300
T extends 'simple' ? typeof SimpleRenderer :
301
T extends 'verbose' ? typeof VerboseRenderer :
302
T extends 'test' ? typeof TestRenderer :
303
T extends 'silent' ? typeof SilentRenderer :
304
never;
305
306
type ListrGetRendererOptions<T extends ListrRendererFactory> =
307
T extends { rendererOptions: infer R } ? R : Record<PropertyKey, any>;
308
309
type ListrGetRendererTaskOptions<T extends ListrRendererFactory> =
310
T extends { rendererTaskOptions: infer R } ? R : Record<PropertyKey, any>;
311
312
type ListrRendererFactory = new (
313
tasks: Task[],
314
options: Record<PropertyKey, any>,
315
events?: ListrEventManager
316
) => ListrRenderer;
317
318
interface SupportedRenderer<Renderer extends ListrRendererFactory> {
319
renderer: Renderer;
320
options?: ListrGetRendererOptions<Renderer>;
321
selection: ListrRendererSelection;
322
}
323
324
enum ListrRendererSelection {
325
PRIMARY = 'PRIMARY',
326
SECONDARY = 'SECONDARY',
327
SILENT = 'SILENT'
328
}
329
330
// Renderer class declarations
331
declare class ListrRenderer {
332
static rendererOptions: Record<PropertyKey, any>;
333
static rendererTaskOptions: Record<PropertyKey, any>;
334
static nonTTY: boolean;
335
constructor(tasks: Task[], options: Record<PropertyKey, any>, events?: ListrEventManager);
336
render(): void | Promise<void>;
337
end(err?: Error): void;
338
}
339
340
declare class DefaultRenderer extends ListrRenderer {
341
static nonTTY: false;
342
}
343
344
declare class SimpleRenderer extends ListrRenderer {
345
static nonTTY: true;
346
}
347
348
declare class VerboseRenderer extends ListrRenderer {
349
static nonTTY: true;
350
}
351
352
declare class TestRenderer extends ListrRenderer {}
353
354
declare class SilentRenderer extends ListrRenderer {}
355
356
declare abstract class ListrPromptAdapter {
357
constructor(task: Task<any, any, any>, wrapper: TaskWrapper<any, any, any>);
358
protected reportStarted(): void;
359
protected reportFailed(): void;
360
protected reportCompleted(): void;
361
protected restoreState(): void;
362
public abstract run<T = any>(...args: any[]): T | Promise<T>;
363
}
364
365
// Core task classes
366
declare class Task<Ctx, Renderer, FallbackRenderer> {
367
public id: string;
368
public state: ListrTaskState;
369
public title?: string;
370
public output?: string;
371
public subtasks: Task<Ctx, Renderer, FallbackRenderer>[];
372
public retry?: ListrTaskRetry;
373
public message: ListrTaskMessage;
374
public prompt: ListrTaskPrompt;
375
public listr: Listr<Ctx, any, any>;
376
check(ctx: Ctx): Promise<boolean>;
377
isPending(): boolean;
378
isRunning(): boolean;
379
isCompleted(): boolean;
380
isFailed(): boolean;
381
isSkipped(): boolean;
382
isRetrying(): boolean;
383
isRollingBack(): boolean;
384
isRolledBack(): boolean;
385
pause(time: number): Promise<void>;
386
}
387
388
declare class TaskWrapper<Ctx, Renderer, FallbackRenderer> {
389
title: string | any[];
390
output: string | any[];
391
newListr(task: ListrTask<Ctx, Renderer> | ListrTask<Ctx, Renderer>[], options?: ListrBaseClassOptions<Ctx, any, any>): Listr<Ctx, any, any>;
392
report(error: Error, type?: ListrErrorTypes): void;
393
skip(message?: string): void;
394
isRetrying(): Task['retry'];
395
prompt<T extends ListrPromptAdapter = ListrPromptAdapter>(
396
adapter: new (task: Task<Ctx, Renderer, FallbackRenderer>, wrapper: TaskWrapper<Ctx, Renderer, FallbackRenderer>) => T
397
): T;
398
stdout(type?: ListrTaskEventType.OUTPUT | ListrTaskEventType.PROMPT): NodeJS.WritableStream;
399
}
400
```