Skip to content

stromseng/effective-progress

Repository files navigation

effective-progress

npm version

Warning

Pre-1.0.0, breaking changes may happen in any release. SemVer guarantees will begin at 1.0.0.
I recommend using only the Progress.all and Progress.forEach APIs for now, as they will likely change the least. The lower-level APIs for manual progress bar control are more likely to see breaking changes as I iterate on the design.

Please open an issue or reach out if you have any questions or want to contribute! Feedback and contributions are very welcome!

Showcase output

effective-progress is an Effect-native CLI progress bar library with:

  • multiple nested tree-like progress bars
  • spinner support for “we have no idea how long this takes” work
  • keep using Console.log / Effect.logInfo while progress rendering is active
  • familiar .all and .forEach APIs — swap Effect for Progress, get progress bars basically for free
  • flicker-free rendering (in theory) by drawing everything in a single terminal frame

Install

bun add effective-progress

Usage

This shows the simplest usage: iterate items with a single progress bar.

import { Console, Effect } from "effect";
import * as Progress from "effective-progress";

const program = Progress.all(
  Array.from({ length: 5 }).map((_, i) =>
    Effect.gen(function* () {
      yield* Effect.sleep("1 second");
      yield* Console.log(`Completed task ${i + 1}`);
    }),
  ),
  { description: "Running tasks in parallel", concurrency: 2 },
);

Effect.runPromise(program);

Basic example output

Nested example

Run:

bun examples/nesting.ts

This demonstrates nested multibar behavior where parent tasks each run their own child progress bars.

import { Effect } from "effect";
import * as Progress from "effective-progress";

const program = Progress.all(
  Array.from({ length: 5 }).map((_, i) =>
    Effect.asVoid(
      Progress.all(
        Array.from({ length: 15 }).map((_) => Effect.sleep("100 millis")),
        { description: `Running subtasks for task ${i + 1}` },
      ),
    ),
  ),
  { description: "Running tasks in parallel", concurrency: 2 },
);

Effect.runPromise(program);

Nested example output

Other examples

  • examples/simpleExample.ts - low-boilerplate real-world flow
  • examples/advancedExample.ts - full API usage and manual task control
  • examples/showcase.ts - nested concurrent tasks, spinner workloads, and mixed Effect/Console logging
  • examples/performance.ts - stress-style run with high log volume and deeply nested progress updates

Configuration

Console behavior

  • The Ink renderer runs with patchConsole: true, so console output is patched by Ink while the app is mounted.
  • Progress.task, Progress.all, and Progress.forEach write through the currently provided Effect Console implementation.
  • Formatting is controlled by the API consumer's logger/console implementation.

Ink renderer behavior

  • Rendering is powered by Ink.
  • Built-in columns are: description, bar, amount/spinner, elapsed, and ETA.
  • Column widths are shared per frame (widest visible cell wins), so rows stay aligned.
  • Elapsed and ETA reserve stable widths to reduce jitter while tasks transition states.
  • Layout uses a 100-column baseline and grows when content requires more space.
  • On narrow terminals, layout compacts to fit available width and tree prefixes are suppressed when description space is too tight.

Manual task control

For manual usage, task still provides the current Task context, while logs continue through your outer Console:

const program = Progress.task(
  Effect.gen(function* () {
    const currentTask = yield* Progress.Task;
    yield* Console.log("This log is handled by the outer Console", { taskId: currentTask });
    yield* Effect.sleep("1 second");
  }),
  { description: "Manual task" },
);

Column customization

Custom column APIs are not part of the first Ink release. The renderer ships with built-in columns only, and old renderer config APIs (RendererConfig, ProgressBarConfig, custom column definitions) are intentionally removed in this iteration.

Notes

  • As Effect 4.0 is around the corner with some changes to logging, there may be some adjustments needed to align with the new Effect APIs.

About

An Effect-native CLI progressbar

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors