New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

livelines

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

livelines

CLI spinners for long running async proccesses

latest
Source
npmnpm
Version
0.2.0
Version published
Maintainers
1
Created
Source

livelines

asciicast

Beautiful CLI spinners for long-running async tasks with nested subtask support. Built with Ink and React.

Features

  • 🎯 Nested Tasks — Create hierarchical task trees with unlimited depth
  • ⏱️ Elapsed Time — Automatic timing for each task with live updates
  • 🎨 Customizable Colors — Style each task with its own color
  • 🔄 60+ Spinners — Choose from all cli-spinners or define your own
  • 📜 Message History — Show recent log lines for tasks with frequent updates
  • Status Indicators — Visual success (✔) and error (✖) states

Installation

# bun
bun add livelines

# npm
npm install livelines

# pnpm
pnpm add livelines

# yarn
yarn add livelines

Quick Start

import LiveLine from 'livelines';

const ll = new LiveLine();

async function main() {
	const task = ll.task('Installing dependencies...');

	await install();

	task.success('143 packages installed');
}

main();

Nested Tasks

Create subtasks by calling .task() on any task handle:

import LiveLine from 'livelines';

const ll = new LiveLine();

async function build() {
	const build = ll.task('Building project...', { color: 'cyan' });

	const compile = build.task('Compiling TypeScript...');
	await compileTS();
	compile.success('42 files compiled');

	const bundle = build.task('Bundling for production...');
	await bundleCode();
	bundle.success('Bundle: 248kb');

	build.success('Build completed');
}

Output:

✔ Building project... [3s]
    ✔ Compiling TypeScript... [1s]
        42 files compiled
    ✔ Bundling for production... [2s]
        Bundle: 248kb
    Build completed

Updating Task Messages

Update a task's message while it's running:

const upload = ll.task('Uploading files...');

for (const file of files) {
	upload.update(`Uploading ${file}...`);
	await uploadFile(file);
}

upload.success(`${files.length} files uploaded`);

Message History

Show recent messages for tasks with frequent updates using logLines:

const deploy = ll.task('Deploying...', { logLines: 3 });

deploy.update('Uploading index.html...');
deploy.update('Uploading app.js...');
deploy.update('Uploading styles.css...');
deploy.update('Uploading assets...');

// Shows the last 3 messages above the current one

API Reference

new LiveLine()

Creates a new LiveLine instance and begins rendering to the terminal.

liveline.task(name, options?)

Creates a new top-level task.

Parameters:

  • name (string) — The task name/label
  • options (TaskOptions) — Optional configuration

Returns: TaskHandle

TaskOptions

OptionTypeDefaultDescription
spinnerSpinnerName | SpinnerObject'dots'Spinner style from cli-spinners or custom object
colorstring'green'Task name color (any Ink/Chalk color)
logLinesnumber0Number of previous messages to display
showElapsedbooleantrueShow elapsed time

TaskHandle

The object returned by .task() with the following methods:

.update(message)

Update the task's current message.

task.update('Processing item 5 of 10...');

.success(message)

Mark the task as successfully completed with a final message.

task.success('Completed successfully');

.error(message)

Mark the task as failed with an error message.

task.error('Failed to connect to server');

.task(name, options?)

Create a nested subtask.

const subtask = task.task('Subtask name...', { color: 'blue' });

Custom Spinners

Use any spinner from cli-spinners:

ll.task('Loading...', { spinner: 'aesthetic' });
ll.task('Downloading...', { spinner: 'arrow3' });
ll.task('Processing...', { spinner: 'bouncingBar' });

Or define your own:

ll.task('Custom spinner...', {
	spinner: {
		interval: 100,
		frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],
	},
});

Colors

Use any color supported by Ink / Chalk:

ll.task('Info', { color: 'blue' });
ll.task('Warning', { color: 'yellow' });
ll.task('Processing', { color: 'cyan' });
ll.task('Deploy', { color: 'magenta' });

Full Example

import LiveLine from 'livelines';

const ll = new LiveLine();

async function main() {
	// Build phase
	const build = ll.task('Building project...', { color: 'cyan' });

	const install = build.task('Installing dependencies...', { color: 'blue' });
	await sleep(1200);
	install.success('143 packages installed');

	const compile = build.task('Compiling source...');
	const typescript = compile.task('TypeScript files...');
	await sleep(800);
	typescript.success('42 files compiled');

	const styles = compile.task('Stylesheets...');
	await sleep(400);
	styles.success('12 files processed');
	compile.success('Compilation complete');

	build.success('Build completed in 3.7s');

	// Deploy phase
	const deploy = ll.task('Deploying to production...', { color: 'magenta' });

	const upload = deploy.task('Uploading files...', { logLines: 3 });
	for (const file of ['index.html', 'app.js', 'app.css']) {
		upload.update(`Uploading ${file}...`);
		await sleep(300);
	}
	upload.success('3 files uploaded');

	deploy.success('Deployed to https://app.example.com');
}

function sleep(ms: number) {
	return new Promise((resolve) => setTimeout(resolve, ms));
}

main();

Contributing

Please see CONTRIBUTING.md for contribution guidelines.

License

MIT

FAQs

Package last updated on 10 Jan 2026

Did you know?

Socket

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.

Install

Related posts