PHPackages                             arthurdick/perennial-task - 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. arthurdick/perennial-task

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

arthurdick/perennial-task
=========================

A simple, command-line utility to help you cultivate recurring responsibilities.

v1.9.0(3mo ago)1812MITPHPPHP ^7.4 || ^8.0CI passing

Since Jul 11Pushed 3mo agoCompare

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

READMEChangelog (7)Dependencies (2)Versions (22)Used By (0)

Perennial Task (`prn`) v1.9.0
=============================

[](#perennial-task-prn-v190)

[![CI](https://github.com/arthurdick/perennial-task/actions/workflows/ci.yml/badge.svg)](https://github.com/arthurdick/perennial-task/actions/workflows/ci.yml/badge.svg)

Like the wood lily that graces the prairies each summer, some tasks are perennial. They return, season after season, requiring steady attention. **Perennial Task** is a simple, command-line utility built to help you cultivate these responsibilities, ensuring nothing is ever overlooked.

[![Perennial Task Logo](/docs/prn_logo.png)](/docs/prn_logo.png)

[![Perennial Task Demo](/docs/demo.svg)](/docs/demo.svg)

Features
--------

[](#features)

- **Flexible Task Scheduling**: Perennial Task uses a simple but powerful system. A task is either **Normal** (a simple, one-off to-do) or **Scheduled** (a task with a due date).
- **Powerful Rescheduling**: A scheduled task can be configured to automatically reschedule itself after completion. You have full control over the new due date, calculating it from either the previous **due date** (for fixed schedules like paying rent) or the **completion date** (for flexible timelines like watering the houseplants). Intervals can be set in days, weeks, months, or years.
- **Task Prioritization**: Assign a numerical **priority** to your tasks. The report view will sort tasks first by their status (overdue, due today, upcoming) and then by their priority, ensuring the most important items always appear first.
- **Completion History**: Every completed task retains a full history of when it was completed, allowing you to track consistency and habits over time.
- **Interactive and Non-Interactive Modes**: Create and edit tasks through a user-friendly interactive menu or automate your workflow with powerful command-line flags.
- **Intelligent Filtering**: The task selection menu is filterable, allowing you to view all tasks, only active ones, or just the reportable (due or upcoming) ones.
- **Command-Line Driven**: Designed for efficient use within a terminal environment.

---

Installation and Usage
----------------------

[](#installation-and-usage)

Perennial Task can be used in three different ways, depending on your needs.

### Method 1: PHAR Release (Recommended for most users)

[](#method-1-phar-release-recommended-for-most-users)

This method uses a single, executable `.phar` file that contains the entire application. It is the easiest way to get started.

1. **Download the `prn.phar`** file from the latest release on GitHub.
2. **Make it executable:**```
    chmod +x prn.phar

    ```
3. **(Optional) Move it into your PATH** to make it accessible from anywhere: ```
    sudo mv prn.phar /usr/local/bin/prn

    ```
4. **Run it:**```
    # If you moved it into your PATH
    prn help

    # If you did not
    ./prn.phar help

    ```

### Method 2: Composer (Recommended for PHP developers)

[](#method-2-composer-recommended-for-php-developers)

If you are a PHP developer, you can install Perennial Task globally using Composer.

1. **Install the Package:**```
    composer global require arthurdick/perennial-task

    ```
2. **Update Your PATH:** Ensure Composer's global bin directory is in your system's `PATH`. Add the following line to your `~/.bashrc` or `~/.zshrc`: ```
    export PATH="$PATH:$(composer global config bin-dir --absolute -q)"

    ```
3. **Apply the Changes:** Restart your terminal or run `source ~/.bashrc`.

### Method 3: Manual Installation from Source (Recommended for contributors)

[](#method-3-manual-installation-from-source-recommended-for-contributors)

This method is for developers who want to work on the source code.

1. **Platform &amp; Dependencies:** This utility is designed for Linux environments. Ensure you have PHP version 7.4 or higher installed, with the `SimpleXML` and `DOM` extensions enabled.
2. **Clone the repository and install dependencies:**```
    git clone https://github.com/arthurdick/perennial-task.git
    cd perennial-task
    composer install

    ```
3. **Run the application** using the `prn` executable in the project root: ```
    ./prn help

    ```

### Enabling Bash Completions

[](#enabling-bash-completions)

To make using `prn` even faster, you can enable tab completions, which will suggest commands, options, and task file paths automatically.

1. **Locate the `prn-completions.bash` file** in the root of the project directory.
2. **Create a symbolic link** to it from your system's bash completion directory. This command will vary based on how you installed the application.

    - **For Composer Installations:**```
        COMPLETIONS_PATH=$(composer global config home -q)/vendor/arthurdick/perennial-task/prn-completions.bash
        sudo ln -s "$COMPLETIONS_PATH" /etc/bash_completion.d/prn
        ```
    - **For Manual/Source Installations:**```
        # Replace /path/to/perennial-task with the actual path to the cloned repository
        sudo ln -s /path/to/perennial-task/prn-completions.bash /etc/bash_completion.d/prn
        ```
3. **Restart your terminal session** or source your `.bashrc` file (`source ~/.bashrc`) to apply the changes.

Now, you can type `prn edi` and press `Tab`, and it should autocomplete to `prn edit`.

---

Usage
-----

[](#usage)

Once installed, you can use the `prn` command from any directory.

**General Syntax:** `prn [command] [options] [argument]`

### **Commands**

[](#commands)

**`prn create`**

- Interactively prompts you to create a new **Normal** or **Scheduled** task. Can also be used non-interactively with flags.

**`prn edit `**

- Interactively or non-interactively edit an existing task.

**`prn complete `**

- Mark a task as complete. If the task is scheduled to repeat, its next due date will be calculated and set automatically.

**`prn describe `**

- Shows a detailed description, status, and completion summary of any single task.

**`prn history `**

- Shows the full, detailed completion history for a single task.

**`prn purge [task_file]`**

- Remove the history from a specified task, or all tasks.

**`prn report [date]`**

- Generates a report of all due, overdue, and upcoming tasks. Optionally run for a specific `[date]`.

**`prn help [command]`**

- Displays a list of available commands or detailed help for a specific command.

**`prn version`**

- Displays the application's version number.

### **Non-Interactive Switches**

[](#non-interactive-switches)

You can use the following flags to bypass the interactive menus and manage tasks in scripts.

#### `create`

[](#create)

- `--name `: The name of the task. **(Required for non-interactive use)**
- `--due `: The date the task is due. Accepts `YYYY-MM-DD` or flexible strings like "tomorrow" or "+2 weeks".
- `--priority `: Set the task's priority (e.g., -2, 0, 10). Defaults to 0.
- `--preview `: The number of days in advance to show the task in reports.
- `--reschedule-interval `: The interval to reschedule the task (e.g., '7 days', '1 month').
- `--reschedule-from `: The basis for rescheduling ('due\_date' or 'completion\_date').

*Example:*`prn create --name "Pay monthly internet bill" --due "next friday" --priority 10 --reschedule-interval "1 month" --reschedule-from due_date`

#### `edit`

[](#edit)

- `--set-name `: Set a new name for the task.
- `--rename-file`: Rename the task file to match the new name (can only be used with `--set-name`).
- `--set-due `: Set a new due date for the task. Accepts `YYYY-MM-DD` or flexible strings like "tomorrow".
- `--remove-due`: Remove the due date and all scheduling settings from a task.
- `--set-priority `: Set a new priority for the task.
- `--set-preview `: Set the number of preview days.
- `--remove-preview`: Remove the preview setting from the task.
- `--set-reschedule-interval `: Set the reschedule interval.
- `--set-reschedule-from `: Set the reschedule basis ('due\_date' or 'completion\_date').
- `--remove-reschedule`: Remove all reschedule settings from the task.

*Example:*`prn edit tasks/my_task.xml --set-due "+3 days" --set-priority 5`

#### `complete`

[](#complete)

- `--date `: The date the task was completed. Accepts `YYYY-MM-DD` or flexible strings like "yesterday" (defaults to today).

*Example:*`prn complete tasks/water_plants.xml --date "yesterday"`

#### `purge`

[](#purge)

- `--force`: Skip the confirmation prompt when purging all tasks.

*Example:*`prn purge --force`

### Exit Codes

[](#exit-codes)

The application uses the following exit codes to indicate success or the type of error encountered:

- 0: Success.
- **1**: A general or unknown error occurred.
- **10**: Invalid command-line argument, option, or value.
- **20**: A file system error occurred (e.g., file not found, permission denied).
- **30**: An invalid file format or configuration error was found.
- **40**: A prerequisite check failed (e.g., a required PHP extension is missing).

### Backward Compatibility &amp; Migration

[](#backward-compatibility--migration)

This version of Perennial Task uses a new, more flexible format for scheduling. However, it is **fully backward compatible** with tasks created by older versions.

When you complete or edit a task that uses a legacy format, it will be **automatically and silently migrated** to the new system. Your data is safe, and your tasks will continue to work as expected.

---

Configuration
-------------

[](#configuration)

Perennial Task stores its configuration in a file named `config.ini`, which is automatically created on first run. It allows you to customize paths for your tasks, logs, and other settings. The file is located in `$XDG_CONFIG_HOME/perennial-task/` (defaulting to `~/.config/perennial-task/`).

You can customize the following settings:

- `tasks_dir`: The directory where your task files are stored.
- `completions_log`: The file where task completions are logged.
- `xsd_path`: The path to the task schema file.
- `tasks_per_page`: The number of tasks to display per page in the interactive selector.
- `timezone`: The timezone to use for date calculations.
- `save_history`: Whether to save the completion history of tasks. Set to `false` to disable history.

---

Development and Testing
-----------------------

[](#development-and-testing)

This project includes a comprehensive test suite built with PHPUnit.

### Prerequisites

[](#prerequisites)

- **Composer**: Install from [getcomposer.org](https://getcomposer.org/).

### Installing Dependencies

[](#installing-dependencies)

1. Clone the repository.
2. Navigate to the project's root directory.
3. Run `composer install` to download development dependencies.

### Running the Test Suite

[](#running-the-test-suite)

From the project's root directory, run:

```
composer test

```

### Code Style

[](#code-style)

This project uses `php-cs-fixer`. To automatically format your code, run:

```
composer fix

```

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance78

Regular maintenance activity

Popularity13

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~9 days

Recently: every ~41 days

Total

21

Last Release

114d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/570f3ed1f70c6d5fede30235be688400c0a745a50d29bd7ec4d2b1202e37f87c?d=identicon)[arthurdick](/maintainers/arthurdick)

---

Top Contributors

[![arthurdick](https://avatars.githubusercontent.com/u/993782?v=4)](https://github.com/arthurdick "arthurdick (152 commits)")

---

Tags

clicommand-lineproductivitytask-managementtask-managercliterminalproductivitytask managementtask-manager

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/arthurdick-perennial-task/health.svg)

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

###  Alternatives

[symfony/console

Eases the creation of beautiful and testable command line interfaces

9.8k1.1B11.2k](/packages/symfony-console)[league/climate

PHP's best friend for the terminal. CLImate allows you to easily output colored text, special formats, and more.

1.9k14.0M272](/packages/league-climate)[php-school/cli-menu

A command line menu helper in PHP

2.0k1.1M27](/packages/php-school-cli-menu)[php-tui/php-tui

Comprehensive TUI library heavily influenced by Ratatui

589747.0k6](/packages/php-tui-php-tui)[aplus/cli

Aplus Framework CLI Library

2301.7M6](/packages/aplus-cli)[splitbrain/php-cli

Easy command line scripts for PHP with opt parsing and color output. No dependencies

177817.2k28](/packages/splitbrain-php-cli)

PHPackages © 2026

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