Developers
Muse
Muse is the hub's command line. It is the way anything runs against a hub without a browser in front of it: migrations, cache clears, scheduled jobs, bulk data work, packaging an extension, installing the hub in the first place. Extensions add commands of their own, and that is how a component gets work done on a timer or by hand.
The point of running through muse rather than a standalone PHP script is that
muse boots the application first. Inside a command you have the configuration,
the database, models, the language files, the event dispatcher and the
container — the same objects a controller has. A script in app/bin has none
of that until it bootstraps the framework itself, and usually bootstraps it
slightly wrong.
When to write a command
Write a muse command when the work is part of an extension and someone will
run it more than once: a nightly job, a re-index, an import, a repair task
that support staff run when a user reports something. Ship it with the
extension, in the extension's own commands directory, so it travels with
the code that it operates on.
Write a plain script only for something genuinely throwaway that you will delete the same day.
Do not write a command for a schema change. Schema changes are migrations; the runner tracks which have run and an administrator applies them as part of an upgrade, which a command does not give you.
Running it
The executable is core/bin/muse, and it is not on the path. Run it from
the hub's root directory:
php core/bin/muse
With no arguments it prints the available commands. php core/bin/muse help
does the same, and php core/bin/muse <command> help describes one command.
Run it as a user that can read the hub's configuration and write its cache and logs, usually the web server user. Running as root is refused unless you confirm it.
The commands
The muse reference lists every command and task in the framework, generated from the command classes, and Common tasks walks through the ones used most.
Commands with a colon in the name are sub-commands, implemented in a
subdirectory: muse cache:css is Command/Cache/Css.php, and
muse app:package is Command/App/Package.php.
How a command is found
Muse looks up a command by name in a list of registered namespaces. Three are registered, and the first that yields a class wins:
| Namespace | Directory | Reached as |
|---|---|---|
\App\Commands |
app/commands |
muse <name> |
\Components\{Name}\Commands |
app/components/com_<name>/commands, then core/components/com_<name>/commands |
muse <name>:<command> |
Hubzero\Console\Command |
core/libraries/Hubzero/Console/Command |
muse <name> |
The framework namespace is registered last, so a hub can shadow a framework
command by putting a class of the same name in app/commands. That is
deliberate and it is also a good way to break an upgrade; prefer a new name.
Within a namespace the file name is the command name, so muse database runs
Command/Database.php, which declares:
namespace Hubzero\Console\Command;
class Database extends Base implements CommandInterface
{
}
A command must extend Base and implement
CommandInterface,
which requires two methods:
| Method | Called when |
|---|---|
execute() |
the command is run with no task: muse database |
help() |
the command is run with help, or execute() delegates to it |
Every other public method is a task, named as it is typed:
muse database dump runs dump().
Component commands
A component's commands live in <component>/commands/ and are namespaced
Components\<Name>\Commands. They are reached with a colon — the component
name, then the command:
php core/bin/muse cron:jobs run
php core/bin/muse publications:bundle
Those are core/components/com_cron/commands/jobs.php
and core/components/com_publications/commands/bundle.php.
The class is the file name in studly case, and the file itself is lower case:
namespace Components\Bookings\Commands;
use Hubzero\Console\Command\Base;
use Hubzero\Console\Command\CommandInterface;
class Reminders extends Base implements CommandInterface
{
}
in core/components/com_bookings/commands/reminders.php, run as
muse bookings:reminders.
Writing one
namespace Hubzero\Console\Command;
use Hubzero\Console\Output;
use Hubzero\Console\Arguments;
class Example extends Base implements CommandInterface
{
/**
* Default: with no task, show the help.
*
* @return void
*/
public function execute()
{
$this->help();
}
/**
* @museDescription Says hello, optionally to someone in particular
*
* @return void
*/
public function hello()
{
$name = $this->arguments->getOpt('name', 'world');
$this->output->addLine('Hello, ' . $name);
}
public function help()
{
$this->output
->getHelpOutput()
->addOverview('An example command')
->addTasks($this)
->render();
}
}
$this->output writes to the terminal and $this->arguments reads what was
typed. getOpt($key, $default = false) returns an option by name;
getOpt(4) and friends return positional words, which is how
muse scaffolding create migration for jos_things reads its arguments.
addTasks($this) builds the help by reflection over the public methods,
skipping the constructor, execute() and help(). A task with no
@museDescription is still listed, as no description available.
Run the example with:
php core/bin/muse example hello --name="Ada"
Docblock tags
| Tag | Where | Effect |
|---|---|---|
@museDescription |
task | The one-line description muse prints beside the task, and the text the generated reference uses |
@museIgnoreHelp |
class | Hides the whole command from the muse help listing |
@museArgument |
task | Describes an option the task accepts |
Configuration, hooks, and aliases
muse configuration stores settings muse itself uses, such as the name and
email the scaffolding generator puts in file headers. It also holds hooks,
which run a shell command at a named point, and aliases, which shorten a
command name. See Common tasks.
Common tasks
The commands reached for most often, with the reasoning behind them. The muse reference lists every framework command and task, generated from the source, and is the place to look for syntax and for anything not covered here.
Run everything below from the hub's root directory.
Cache
muse cache clears the hub's cache files.
muse cache:css clears only the
compiled CSS, which is what you want after changing a template's stylesheets
and finding the browser still serving the old ones.
php core/bin/muse cache clear
php core/bin/muse cache:css clear
Configuration
muse configuration holds settings
muse itself uses. The scaffolding generator asks for your name and email the
first time and stores them here, so generated files carry a sensible header.
php core/bin/muse configuration set --user_name="Ada Lovelace"
php core/bin/muse configuration set --user_email=ada@example.org
It also stores hooks — shell commands run at a named point — and aliases, which are shortcuts for a command name:
# fix permissions after updating the repository
php core/bin/muse configuration:hooks add repository.afterUpdate "chmod -R g+w /www/docroot"
# muse env -> muse environment
php core/bin/muse configuration:aliases add env environment
Aliases are resolved before the namespace search, so an alias can shadow a real command name.
Database
muse database exists for two jobs:
backups, and moving content backwards through a deployment chain.
The second is the interesting one. Copying a production database over a
development one takes the production configuration with it — hostnames, mail
settings, credentials — and breaks the development hub. dump and load
move only the parts that should travel.
# on production
php core/bin/muse database dump
# copy the file across, then on development
php core/bin/muse database load <filename>
Environment
muse environment prints the current
user and database. It is a one-line sanity check before running anything
destructive, and worth making a habit of.
Extension
muse extension adds, deletes,
installs, enables and disables rows in the extensions table. Run with no task
it prompts for what it needs, so there is no syntax to remember.
Group
The muse group tasks are wrappers on
existing commands, run in a super group's context and against its database.
See Super groups.
Log
muse log follow tails and filters a
log. Three log types are supported — post, profile and sql — and each
has to be enabled before anything appears in it.
php core/bin/muse log follow profile
It prints the field layout first, with an asterisk against each visible field:
<0:*timestamp> <1:*hubname> <2:*ip> <3:*app> <4:*uri> <5:*query> <6:*memory> <7:*querycount> <8:*timeinqueries> <9:*totaltime>
Press a field's number to hide or show it, f to reprint the layout, and h
for the rest: q quit, i input mode, p pause, b beep, r re-render the
last hundred lines. Following the profile log while clicking through a page
is the quickest way to find the request that runs four hundred queries.
Migration
See Migrations in the database chapter for
writing one, and
muse migration for the command.
Repository
muse repository wraps whatever
mechanism manages this copy of the CMS. Git is the only one currently
supported; run it with no task to find out whether it applies to your
environment.
php core/bin/muse repository # is this repository managed, and is it clean?
php core/bin/muse repository update # what would the update bring?
php core/bin/muse repository update -f # do it
As with migrations, the read-only form comes first and -f commits to it. A
failed update rolls back to the state before it started, and leaves you to
finish the update by hand.
muse repository clean prunes
rollback points and stashes, and asks before each.
Scaffolding
muse scaffolding writes the files
you would otherwise copy from an existing extension and rename. It knows how
to create commands, components, migrations and tests.
php core/bin/muse scaffolding create component com_bookings
That writes a component skeleton under core/components/com_bookings: the
manifest, the site and admin entry points, a controller on each side, an
admin display template, site display and edit templates, a model,
config/config.xml and config/access.xml, the site and admin language
files, a router, and empty CSS and JS assets. The component name is
substituted throughout. It refuses to run if the directory already exists.
What it does not write is an API controller or a migration. Add the migration yourself; see Writing one.
Test
muse test is a wrapper around PHPUnit that
knows where each extension's tests live. muse test show lists the extensions
that have tests; muse test run <extension> runs one extension's. See
Testing.
User
muse user merges and unmerges accounts.
People do create a second account by mistake and then ask for their
contributions to be moved, which means updating a user id across every table
that references one.
php core/bin/muse user merge 1042 into 1003
php core/bin/muse user unmerge 1042 from 1003
Commands not covered above
app and its package and repository sub-commands manage Composer
packages for a hub. install performs a fresh installation, step by step.
htmx and inertia scaffold and lint front-end integrations. resources
exports the resource catalogue and reports git statistics. searchmigration
rebuilds the search index. Each is listed with its tasks in the
muse reference.
Rewritten and checked against 2.4-main @ 348f0057c2 on 2026-09-10.