The Castor Task Runner is Now Stable!
When we unveiled Castor to the world, we shared the reasons that prompted us to develop our own task runner.
Since that article from 2023, many things have evolved in the project. And we now consider Castor and its public API to be stable enough to finally deserve the v1.0.0 milestone.
Let’s take a look at what Castor looks like now… but before that, a quick recap of the project.
Section intitulée did-you-say-castorDid You Say Castor?
Castor is the PHP task runner we’ve been developing for several years. Its goal? To replace our Makefiles (or Fabric, Invoke, or shell scripts) by allowing us to create our tasks using simple PHP functions, which are easy to read, understand, and write.
No classes, no OOP, no YAML configuration, or overly complex layers to implement.
Castor’s main feature is the Developer eXperience (DX) it offers. A castor.php
file, an AsTask
attribute—that’s all you need to get started:
// castor.php
use Castor\Attribute\AsTask;
use function Castor\run;
#[AsTask()]
function start(''): void
{
run('composer install');
run('bin/console assets:install');
run('yarn install');
// …
}
You can then execute your task:
castor start
Despite this apparent simplicity, Castor has much more to offer: a notion of context to adapt your tasks based on the environment, imports and namespaces to structure your Castor project however you like, events to hook into Castor’s internals, and much more.
Many native utilities are, of course, available to serve as building blocks in your tasks: environment variable management, input/output, logs, HTTP calls, SSH, etc. Check out the exhaustive list of available utilities.
Missing a tool? Add it naturally, just as you would in your usual PHP project. And if you think it could benefit everyone, come discuss it with us, open an issue, or even better, a PR!
Section intitulée key-highlightsKey Highlights
Section intitulée the-public-apiThe Public API
All the natively provided functions and their signatures form the public part of Castor’s API. They are guaranteed not to change within minor Castor versions.
If we need to modify or remove a function, a deprecation will always be added before its definitive removal in a major version, similar to what Symfony does to respect Semver and avoid Backward compatibility (BC) breaks.
Info
This compatibility promise has been in place since the very first 0.x versions!
This public API also includes all classes and behaviors mentioned in the documentation. For instance, this includes the classes for the Context or events. Generally speaking, all classes not marked with the @internal
annotation are part of this public API.
Thanks to this promise, we have been able to progressively improve Castor’s internal workings throughout the 0.x versions:
- added new features;
- improved the code;
- simplified maintenance.
All of this without breaking projects already using Castor since the early v0.x versions.
Section intitulée user-experienceUser Experience
As we’ve said, DX is at the heart of the project. We do everything to make Castor:
- easy to install;
- simple to pick up;
- understandable at a glance;
- and easy to debug (thanks to logs, in particular).
When you use Castor, it automatically generates a .castor.stub.php
file containing all the definitions of the public API’s functions and classes. This allows your IDE to better understand your Castor project and offer autocompletion and suggestions, as if Castor were installed in your project’s dependencies.
Castor also provides autocompletion in your favorite shell, with completion for available tasks, their arguments, and options.
The tool must serve developers, and everything is done to make the experience smoother, more natural, and more pleasant than with alternatives.
Section intitulée documentation-and-examplesDocumentation and Examples
Having lots of features is great. But if they’re not documented anywhere, they’ll never be used. Therefore, a significant effort has been made to document all the functionalities offered by Castor:
- everything you need to quickly get started with Castor;
- all native functions and helpers;
- supported advanced usages.
Astuce
If you only remember one thing: take a look at the project documentation!
The documentation is divided into 2 main sections:
- “Getting started” to quickly understand the basics of Castor;
- “Going further” for more advanced needs.
And because nothing beats code, you’ll find numerous examples directly in the jolicode/castor repository to show the different features in action.
Psst, easter egg: these examples also serve as a complete test suite to ensure we don’t break anything when modifications are made to Castor.
Section intitulée numerous-featuresNumerous Features
Castor has been considerably enriched over the versions. Let’s look at the main things our favorite rodent can do now.
Section intitulée native-helpersNative Helpers
We have added several functions that are commonly used in the tasks we execute daily.
Since the idea was not to reinvent the wheel, we fully leverage PHP and its very complete ecosystem. Several functions exposed by Castor are therefore totally based on Symfony components. For example:
cache()
, which utilizessymfony/cache
and PSR-6;io()
, which offers the interactivity capabilities ofsymfony/console
;http_request()
, which allows HTTP requests thanks tosymfony/http-client
;run()
to execute commands usingsymfony/process
;fs()
for filesystem manipulation withsymfony/filesystem
andfinder()
for searching files/folders thanks tosymfony/finder
;yaml_parse()
andyaml_dump()
for manipulating YAML files withsymfony/yaml
.
In addition, Castor includes:
- a log system based on Monolog;
- desktop notifications with JoliNotif;
- parallel process execution thanks to PHP 8.1 Fibers;
- SSH or SCP commands via the
spatie/ssh
library.
To conclude this far-from-exhaustive list, note that it’s also possible to monitor the file system to restart commands upon disk changes or even to encrypt/decrypt files.
Once again, we can only encourage you to take a look at the exhaustive list of functions to discover everything that can be done natively with Castor.
Section intitulée installation-methodsInstallation Methods
Castor now offers several installation modes. The simplest way:
curl "https://castor.jolicode.com/install" | bash
If you have PHP >= 8.2 installed, you can benefit from the PHAR, as with most PHP projects that offer an executable (Composer, Rector, PHPStan, etc.).
Don’t have PHP or is your PHP too old? No problem, the installation script allows you to install Castor as a standalone binary that includes the correct PHP version:
curl "https://castor.jolicode.com/install" | bash -s -- --static
And because we also use GitHub Actions in most of our projects, we created a castor-php/setup-castor
Action that allows you to install Castor directly in your workflow:
jobs:
my-job:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup castor
uses: castor-php/setup-castor@v0.1.0
- name: Run castor "hello" task
run: castor hello
As with the rest, everything is explained in the installation documentation.
Section intitulée castor-as-a-cli-frameworkCastor as a CLI Framework
Castor makes it easy for you to code your everyday tasks. Imagine you have a set of Castor tasks that you would like to share with other users or within other projects?
Castor now allows you to “repack” your project, which means building a PHAR containing Castor and all your tasks, as if it were your own executable.
It is even possible to hide the default Castor logo, or more recently, to configure your own logo 🎨.
And in the same way that Castor is available for installation as a PHAR, but also as a binary, it is possible to build a binary containing your own repacked project.
Section intitulée remote-importsRemote Imports
In cases where you need a feature that is not natively included in Castor, it is now possible to import tasks, functions, or even classes from external packages.
Again, the idea was not to re-develop an entire plugin management and download system. Instead, we chose to reuse the best package manager we know: Composer. Castor directly embeds Composer and allows you to configure the different packages to import (from packagist.org or from your own internal repository) in the same way you would in your project’s composer.json
.
<?php
import('composer://vendor/package/', file: 'functions.php');
This feature required several iterations before reaching a reliable and satisfactory implementation. However, we prefer to consider this feature experimental for some time to fine-tune the final details.
Section intitulée adoptionAdoption
We designed Castor to simplify our daily lives: driving our Docker/Ansible stacks, automating tasks, etc. All our developers are delighted to no longer have a Python environment to install, to be able to easily contribute tasks, and to no longer have dependency issues, etc.
We also use Castor to develop Castor. The project’s CI runs in GitHub Actions with Castor, the release system is a Castor task that handles creating the tag and the release with the gh
CLI, then attaching the different artifacts (PHARs, binaries) to the release, and the documentation is generated by MkDocs via Castor tasks. In short, we are Castor’s first users 🦫
When we open-sourced Castor, we received a lot of very positive feedback from people who were also thrilled to be able to write their tasks simply in PHP. We have more and more contributions from people outside the project, which confirms the enthusiasm and interest around Castor.
Thank you for your ⭐, which motivates us even more!
Section intitulée a-final-wordA Final Word
Castor v1 is available, and we hope it will meet all your needs.
Let us know if you’d be interested in learning how Castor works internally, how we automated the build of the different Linux/macOS/Windows versions, how we built the test suite, etc.
Commentaires et discussions
Nos formations sur ce sujet
Notre expertise est aussi disponible sous forme de formations professionnelles !

Castor
Découvrez Castor, l’outil PHP dédié à l’automatisation de tâches.
Ces clients ont profité de notre expertise
Au fil de notre collaboration avec Deezer, nous avons été impliqués dans plusieurs initiatives visant à optimiser les performances de leur plateforme. Notre engagement initial s’est concentré sur le soutien et le conseil à l’équipe “Product Features” lors de leur projet de migration en cours. Nous avons apporté notre expertise pour résoudre…
Groupama Épargne Salariale digitalise son expérience client en leur permettant d’effectuer leurs versements d’épargne salariale en ligne. L’application offre aux entreprises une interface web claire et dynamique, composé d’un tunnel de versement complet : import des salariés via fichier Excel, rappel des contrats souscrits et des plans disponibles, …
L’équipe de Finarta a fait appel à JoliCode pour le développement de leur plateforme Web. Basée sur le framework Symfony 2, l’application est un réseau privé de galerie et se veut être une place de communication et de vente d’oeuvres d’art entre ses membres. Pour cela, de nombreuses règles de droits ont été mises en places et une administration poussée…