Get the FREE Ultimate OpenClaw Setup Guide →

ora-spinner-integration

Scanned
npx machina-cli add skill a5c-ai/babysitter/ora-spinner-integration --openclaw
Files (1)
SKILL.md
4.8 KB

Ora Spinner Integration

Integrate ora spinners for consistent CLI progress feedback.

Capabilities

  • Configure ora spinner styling
  • Create promise-based spinners
  • Set up spinner sequences
  • Implement status transitions
  • Create custom spinner types
  • Generate spinner utilities

Usage

Invoke this skill when you need to:

  • Add loading indicators to CLI
  • Show progress during async operations
  • Create consistent spinner styling
  • Implement status transitions

Inputs

ParameterTypeRequiredDescription
languagestringYesTarget language (typescript, javascript)
styleobjectNoSpinner styling options
spinnersarrayNoCustom spinner definitions

Generated Patterns

TypeScript Spinner Utilities

import ora, { Ora, Options } from 'ora';
import chalk from 'chalk';

// Spinner configuration
const defaultOptions: Options = {
  color: 'cyan',
  spinner: 'dots',
  prefixText: '',
};

// Create spinner with consistent styling
export function createSpinner(text: string, options?: Partial<Options>): Ora {
  return ora({
    ...defaultOptions,
    ...options,
    text,
  });
}

// Spinner with promise
export async function withSpinner<T>(
  text: string,
  fn: () => Promise<T>,
  options?: {
    successText?: string | ((result: T) => string);
    failText?: string | ((error: Error) => string);
  }
): Promise<T> {
  const spinner = createSpinner(text);
  spinner.start();

  try {
    const result = await fn();
    const successText = typeof options?.successText === 'function'
      ? options.successText(result)
      : options?.successText || text;
    spinner.succeed(successText);
    return result;
  } catch (error) {
    const failText = typeof options?.failText === 'function'
      ? options.failText(error as Error)
      : options?.failText || `Failed: ${(error as Error).message}`;
    spinner.fail(failText);
    throw error;
  }
}

// Sequential spinners
export async function withSequentialSpinners<T>(
  steps: Array<{
    text: string;
    fn: () => Promise<any>;
    successText?: string;
  }>
): Promise<T[]> {
  const results: T[] = [];

  for (const step of steps) {
    const result = await withSpinner(step.text, step.fn, {
      successText: step.successText,
    });
    results.push(result);
  }

  return results;
}

// Multi-line spinner status
export class TaskSpinner {
  private spinner: Ora;
  private tasks: Map<string, 'pending' | 'running' | 'done' | 'failed'>;

  constructor(title: string) {
    this.spinner = createSpinner(title);
    this.tasks = new Map();
  }

  addTask(id: string): void {
    this.tasks.set(id, 'pending');
    this.updateDisplay();
  }

  startTask(id: string): void {
    this.tasks.set(id, 'running');
    this.updateDisplay();
  }

  completeTask(id: string): void {
    this.tasks.set(id, 'done');
    this.updateDisplay();
  }

  failTask(id: string): void {
    this.tasks.set(id, 'failed');
    this.updateDisplay();
  }

  private updateDisplay(): void {
    const lines = Array.from(this.tasks.entries()).map(([id, status]) => {
      const icon = {
        pending: chalk.gray('○'),
        running: chalk.cyan('◐'),
        done: chalk.green('●'),
        failed: chalk.red('✗'),
      }[status];
      return `  ${icon} ${id}`;
    });

    this.spinner.text = '\n' + lines.join('\n');
  }

  start(): void {
    this.spinner.start();
  }

  stop(): void {
    const failed = Array.from(this.tasks.values()).some(s => s === 'failed');
    if (failed) {
      this.spinner.fail('Tasks completed with errors');
    } else {
      this.spinner.succeed('All tasks completed');
    }
  }
}

Usage Examples

// Simple spinner
const spinner = createSpinner('Loading...');
spinner.start();
// ... do work
spinner.succeed('Loaded!');

// Promise wrapper
const data = await withSpinner(
  'Fetching data...',
  () => fetchData(),
  { successText: (data) => `Loaded ${data.length} items` }
);

// Sequential steps
await withSequentialSpinners([
  { text: 'Installing dependencies...', fn: () => installDeps() },
  { text: 'Building project...', fn: () => build() },
  { text: 'Running tests...', fn: () => test() },
]);

// Task tracking
const tasks = new TaskSpinner('Processing files');
tasks.addTask('file1.ts');
tasks.addTask('file2.ts');
tasks.start();
tasks.startTask('file1.ts');
// ... process
tasks.completeTask('file1.ts');
tasks.startTask('file2.ts');
tasks.completeTask('file2.ts');
tasks.stop();

Dependencies

{
  "dependencies": {
    "ora": "^7.0.0",
    "chalk": "^5.0.0"
  }
}

Target Processes

  • progress-status-indicators
  • cli-output-formatting
  • cli-application-bootstrap

Source

git clone https://github.com/a5c-ai/babysitter/blob/main/plugins/babysitter/skills/babysit/process/specializations/cli-mcp-development/skills/ora-spinner-integration/SKILL.mdView on GitHub

Overview

This skill provides reusable ora based spinners for CLI progress feedback. It offers consistent styling, promise wrappers, and multi task status updates to improve user experience during async operations.

How This Skill Works

It defines a shared createSpinner with defaultOptions (color, spinner, and text), and exposes helpers like withSpinner and withSequentialSpinners to handle promises. TaskSpinner manages multiple tasks with per task states and a combined display, updating the spinner title as tasks progress.

When to Use It

  • Add loading indicators to CLI tools during async tasks
  • Show progress for long running data processing, fetches, or deployments
  • Enforce a consistent spinner style across different commands
  • Display multi step workflows with per step status updates
  • Provide per task status lines for batch jobs or parallel steps

Quick Start

  1. Step 1: Install ora and chalk, then import createSpinner, withSpinner, and TaskSpinner
  2. Step 2: Create a spinner with createSpinner('Loading...') and run a promise with withSpinner
  3. Step 3: Use TaskSpinner for multi task status or withSequentialSpinners for ordered steps

Best Practices

  • Centralize defaultOptions in createSpinner to ensure consistent styling
  • Use descriptive successText and failText for clarity
  • Prefer withSpinner for single promises and withSequentialSpinners for ordered steps
  • Leverage TaskSpinner for multi task scenarios to keep a stable UI
  • Gracefully handle errors and ensure the spinner is stopped in all paths

Example Use Cases

  • CLI data exporter showing per record processing with status icons
  • Build script running multiple bundles with sequential spinners
  • Deployment tool that marks each step as running, done, or failed
  • ETL job reporting per task progress using TaskSpinner
  • File uploader CLI with colored progress indicators

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers