PHPackages                             eliashaeussler/task-runner - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [CLI &amp; Console](/categories/cli)
4. /
5. eliashaeussler/task-runner

ActiveLibrary[CLI &amp; Console](/categories/cli)

eliashaeussler/task-runner
==========================

Progress helper for long-running CLI tasks, based on Symfony Console

1.2.2(4mo ago)143.6k↓29.9%[1 issues](https://github.com/eliashaeussler/task-runner/issues)1GPL-3.0-or-laterPHPPHP ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0CI passing

Since Dec 26Pushed 1mo agoCompare

[ Source](https://github.com/eliashaeussler/task-runner)[ Packagist](https://packagist.org/packages/eliashaeussler/task-runner)[ RSS](/packages/eliashaeussler-task-runner/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (11)Versions (8)Used By (1)

Task Runner
===========

[](#task-runner)

[![Coverage](https://camo.githubusercontent.com/9682db3b4894f276393ca8df7b3cb41a425f32efebc8434d384eb3cd28f2d763/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c73436f7665726167652f6769746875622f656c6961736861657573736c65722f7461736b2d72756e6e65723f6c6f676f3d636f766572616c6c73)](https://coveralls.io/github/eliashaeussler/task-runner)[![CGL](https://camo.githubusercontent.com/9ac0705f03be1cc1ff5ef0a95aef889fc7bf644e30024895ce5be4a5ab6c83a0/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f656c6961736861657573736c65722f7461736b2d72756e6e65722f63676c2e79616d6c3f6c6162656c3d63676c266c6f676f3d676974687562)](https://github.com/eliashaeussler/task-runner/actions/workflows/cgl.yaml)[![Tests](https://camo.githubusercontent.com/e6fe99c2a427787d6c627c25e0379d425abba0f44e96013dff1360aedc235a78/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f656c6961736861657573736c65722f7461736b2d72756e6e65722f74657374732e79616d6c3f6c6162656c3d7465737473266c6f676f3d676974687562)](https://github.com/eliashaeussler/task-runner/actions/workflows/tests.yaml)[![Supported PHP Versions](https://camo.githubusercontent.com/03b9e01773705d53228d2b365990506b56f1bbdab48f16de750f72602b7305c5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f656c6961736861657573736c65722f7461736b2d72756e6e65722f7068703f6c6f676f3d706870)](https://packagist.org/packages/eliashaeussler/task-runner)

*Task Runner* is a simple PHP library targeted for CLI-oriented applications and projects. It provides a progress helper for long-running CLI tasks, based on *Symfony Console* or *Composer IO* (for use in Composer plugins).

🔥 Installation
--------------

[](#-installation)

[![Packagist](https://camo.githubusercontent.com/9708c27684c6180c5475721ed4c45ad4c52863d18f8d8efa502436e010b8d2c1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f656c6961736861657573736c65722f7461736b2d72756e6e65723f6c6162656c3d76657273696f6e266c6f676f3d7061636b6167697374)](https://packagist.org/packages/eliashaeussler/task-runner)[![Packagist Downloads](https://camo.githubusercontent.com/99ed9726f70a374f020c693ac541cd55b38b8cdea98d00dee6b4bbb3f34c9e86/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f656c6961736861657573736c65722f7461736b2d72756e6e65723f636f6c6f723d627269676874677265656e)](https://packagist.org/packages/eliashaeussler/task-runner)

```
composer require eliashaeussler/task-runner
```

⚡️ Usage
--------

[](#️-usage)

### Basic usage

[](#basic-usage)

A common use case is to wrap a long-running process in a [`TaskRunner`](src/TaskRunner.php) instance, which handles progress messages and the overall task execution:

```
use EliasHaeussler\TaskRunner;
use Symfony\Component\Console;

// 1. Create a new TaskRunner instance
$output = new Console\Output\ConsoleOutput();
$taskRunner = new TaskRunner\TaskRunner($output);

// 2. Run the task
$taskRunner->run(
    'Downloading some large files from the internet',
    static function () {
        // Do some long-running work here...
    },
);
```

This will output the following progress message:

```
Downloading some large files from the internet... Done

```

### Progress message decorators

[](#progress-message-decorators)

User-oriented progress messages are decorated by a [`ProgressDecorator`](src/Decorator/ProgressDecorator.php) instance. By default, a simple progress decorator is used. It displays the various steps like follows:

- Progress start: `Downloading some large files from the internet...`
- Task successful: `Downloading some large files from the internet... Done`
- Task failed: `Downloading some large files from the internet... Failed`

It is possible to pass a customized progress decorator to the `TaskRunner`instance:

```
use EliasHaeussler\TaskRunner;
use Symfony\Component\Console;

// 1. Create a custom progress decorator
$decorator = new class implements TaskRunner\Decorator\ProgressDecorator
{
    public function progress(string $message, bool &$newLine = false): string
    {
        return '⏳ '.$message.'... ';
    }

    public function done(mixed $result = null): string
    {
        return '🥳'
    }

    public function failed(?Throwable $exception = null): string
    {
        return '💥';
    }
}

// 2. Create a new TaskRunner instance
$output = new Console\Output\ConsoleOutput();
$taskRunner = new TaskRunner\TaskRunner($output, $decorator);

// 3. Run the task
$taskRunner->run(
    'Downloading some large files from the internet',
    static function () {
        // Do some long-running work here...
    },
);
```

The above example will output the following progress messages:

- Progress start: `⏳ Downloading some large files from the internet...`
- Task successful: `⏳ Downloading some large files from the internet... 🥳`
- Task failed: `⏳ Downloading some large files from the internet... 💥`

### Custom output

[](#custom-output)

Some long-running tasks may also produce output that should be displayed to the user. For this usecase, the executing task receives a `RunnerContext`instance, which holds a buffered output stream. This can be used to write output to the console:

```
use EliasHaeussler\TaskRunner;

$taskRunner->run(
    'Downloading some large files from the internet',
    static function (TaskRunner\RunnerContext $context) {
        // Do some long-running work here...

        $context->output->writeln('This content is displayed to the user.');
    },
);
```

The additional output will be displayed after the progress message:

```
Downloading some large files from the internet... Done
This content is displayed to the user.

```

### Error Handling

[](#error-handling)

If an error occurs during the execution of the task, the `TaskRunner` will automatically catch it, mark the test execution as failed, and by default throw the catched exception afterwards:

```
Downloading some large files from the internet... Failed
PHP Fatal error:  Uncaught RuntimeException: Downloading failed.

```

This behavior can be customized in various ways.

#### Avoid throwing an exception

[](#avoid-throwing-an-exception)

In some cases, a thrown exception may not be relevant for the user and hence should not avoid further execution of the application. This behavior can be controlled with the passed `RunnerContext` instance:

```
use EliasHaeussler\TaskRunner;

$taskRunner->run(
    'Downloading some large files from the internet',
    static function (TaskRunner\RunnerContext $context) {
        $context->throwExceptions = false;

        // Do some long-running work here...

        if ($downloadFailed) {
            throw new RuntimeException('Downloading failed.');
        }
    },
);
```

In the above example, the task execution is still marked as failed, but the exception is not thrown afterwards:

```
Downloading some large files from the internet... Failed

```

#### Control task result

[](#control-task-result)

In addition, it is also possible to control the task result manually, even if no exception was thrown:

```
use EliasHaeussler\TaskRunner;

$taskRunner->run(
    'Downloading some large files from the internet',
    static function (TaskRunner\RunnerContext $context) {
        // Do some long-running work here...

        if ($downloadFailed) {
            $context->markAsFailed();
        }
    },
);
```

In the above example, the task execution is now manually marked as failed:

```
Downloading some large files from the internet... Failed

```

#### Receive task result

[](#receive-task-result)

If the provided task is successful, the `TaskRunner` returns the result of the executed task:

```
use EliasHaeussler\TaskRunner;

$files = $taskRunner->run(
    'Downloading some large files from the internet',
    static function (TaskRunner\RunnerContext $context) {
        // Do some long-running work here...

        return $files;
    },
);

// $files is now the result of the task
```

If a task does not provide a result, `null` will be returned instead:

```
use EliasHaeussler\TaskRunner;

$files = $taskRunner->run(
    'Downloading some large files from the internet',
    static function (TaskRunner\RunnerContext $context) {
        // Do some long-running work here...
    },
);

// $files is always NULL
```

This, however, can be slightly adapted, if the task is declared as returning `void`. In this case, the `TaskRunner` will return a dedicated [`TaskResult`](src/TaskResult.php) object instead:

```
use EliasHaeussler\TaskRunner;

$result = $taskRunner->run(
    'Downloading some large files from the internet',
    static function (TaskRunner\RunnerContext $context): void {
        // Do some long-running work here...
    },
);

// $result is now a TaskResult instance, e.g. TaskResult::Success
```

In case a task throws an exception and the passed `RunnerContext` was modified to avoid throwing exceptions, the `TaskResult` will return `TaskResult::Failed`instead:

```
use EliasHaeussler\TaskRunner;

$result = $taskRunner->run(
    'Downloading some large files from the internet',
    static function (TaskRunner\RunnerContext $context) {
        $context->throwExceptions = false;

        // Do some long-running work here...

        if ($downloadFailed) {
            $context->markAsFailed();
        }
    },
);

// $result is now a TaskResult::Failed instance
```

🧑‍💻 Contributing
----------------

[](#‍-contributing)

Please have a look at [`CONTRIBUTING.md`](CONTRIBUTING.md).

⭐ License
---------

[](#-license)

This project is licensed under [GNU General Public License 3.0 (or later)](LICENSE).

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance63

Regular maintenance activity

Popularity32

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 56.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

6

Last Release

132d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/144cefe55242b883c87cb537463f3ba75a0f8198fc5b602b50c838aae31fe7ee?d=identicon)[eliashaeussler](/maintainers/eliashaeussler)

---

Top Contributors

[![renovate[bot]](https://avatars.githubusercontent.com/in/2740?v=4)](https://github.com/renovate[bot] "renovate[bot] (30 commits)")[![eliashaeussler](https://avatars.githubusercontent.com/u/16313625?v=4)](https://github.com/eliashaeussler "eliashaeussler (23 commits)")

---

Tags

outputprogressrunnertask

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/eliashaeussler-task-runner/health.svg)

```
[![Health](https://phpackages.com/badges/eliashaeussler-task-runner/health.svg)](https://phpackages.com/packages/eliashaeussler-task-runner)
```

###  Alternatives

[illuminate/console

The Illuminate Console package.

12944.1M5.1k](/packages/illuminate-console)[crazywhalecc/static-php-cli

Build single static PHP binary, with PHP project together, with popular extensions included.

1.8k13.9k](/packages/crazywhalecc-static-php-cli)[matthiasnoback/symfony-console-form

Use Symfony forms for Console command input

368264.8k8](/packages/matthiasnoback-symfony-console-form)[phpcr/phpcr-shell

Shell for PHPCR

721.3M8](/packages/phpcr-phpcr-shell)[madewithlove/license-checker

CLI tool to verify allowed licenses for composer dependencies

54449.8k21](/packages/madewithlove-license-checker)[shel/neos-terminal

Neos CMS Ui terminal for running Eel expressions and other commands

1441.3k](/packages/shel-neos-terminal)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
