Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › Acorn

How to Write Custom WP-CLI Commands With Acorn

By Freedom251 Team · · 12 min read

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Acorn lets a WordPress theme or plugin expose Laravel-style Artisan commands through WP-CLI. The practical workflow is: install and boot Acorn, generate a command class with wp acorn make:command, declare its interface in $signature, put the work in handle(), and run it through the wp acorn namespace.

This guide shows where command classes live, how to define arguments and options, how to combine Acorn console features with WordPress APIs, and how to diagnose the common “acorn is not a registered wp command” failure.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What Acorn adds to WP-CLI

Acorn is a way to use Laravel components inside WordPress. Its console layer brings Laravel’s Artisan programming model to WP-CLI, so a command is represented by a PHP class with a signature, description, and lifecycle method rather than by a large procedural callback.

The command is still executed by WP-CLI, but Acorn supplies the Laravel-style command object. That gives you structured arguments and options, formatted console output, prompts, and an integer exit status while retaining access to WordPress functions such as get_posts(). This combination is useful for content audits, cleanup, imports, migrations, and repeatable maintenance jobs.

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.

Prerequisites and project layout

Install Acorn with Composer

Acorn must be installed in the WordPress project before its generator or command namespace can work. Use the Composer installation procedure for the Acorn release used by your project. A project that manages the package directly will commonly add the Acorn dependency from its Composer configuration; an existing Acorn-based theme or plugin may already provide it.

After installation, run Composer’s autoloader generation as part of the project’s normal deployment process. Do not copy a command class into production without deploying the dependency and updated autoloader that load it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a supported runtime

The current Acorn installation requirements list PHP 8.3 or newer, WordPress 5.4 or newer, and WP-CLI. These are minimums for the current installation documentation, not a guarantee that every older Acorn release has the same requirements. Check the release installed in your project before upgrading PHP or WordPress.

Ensure Acorn is booted by an active extension

A theme or plugin that boots Acorn must be active when WP-CLI starts WordPress. If the bootstrapping extension is inactive, Roots documents the resulting error as:

Error: 'acorn' is not a registered wp command.

This is a loading problem, not a syntax problem in your command class. Activate the Acorn-booting theme or plugin, run WP-CLI against the correct WordPress installation, and then retry.

Know the conventional directory

In the conventional Acorn application structure, generated command classes live in:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
app/Console/Commands/

Keep application commands there unless your project has deliberately changed its autoloading and command registration. A class in an arbitrary directory may be perfectly valid PHP yet never be discovered by Acorn.

Generate a command class

From the WordPress project root, run the Acorn generator:

Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.
wp acorn make:command SeoAuditCommand

Roots’ documentation says this creates the command file in app/Console/Commands/. The generated class gives you the namespace, imports, and method shape expected by the installed Acorn version. Start from that file instead of creating a class with a guessed namespace.

The class name is a PHP identifier; the command users type is defined separately in $signature. For example, SeoAuditCommand can expose the command name seo:audit.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Define the command interface in $signature

The signature is the command’s contract. It determines the name shown to users, positional arguments, option names, defaults, and whether a value is required.

protected $signature = 'seo:audit {--post-type=post}';
protected $description = 'Audit posts for SEO issues';

This declares an option named post-type with a default value of post. A user can accept that default or override it with --post-type=page. Put the default and the purpose of an option in the signature whenever possible; the help screen then documents the interface close to the code that enforces it.

Positional arguments

Use an argument when the value is the subject of the operation and is normally required in a particular position. A migration that acts on one source could declare:

protected $signature = 'content:migrate {source}';

The command would then be called with a value after the command name. Arguments make concise, verb-like commands, but a required argument also makes ad-hoc invocation fail when it is omitted.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Options

Use an option for a modifier, filter, limit, mode, or optional setting. For example:

protected $signature = 'seo:audit
    {--post-type=post}
    {--limit=50}
    {--dry-run}';

Here, --post-type and --limit take values, while --dry-run is a boolean switch. The same command can be run as:

Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by
wp acorn seo:audit
wp acorn seo:audit --post-type=page --limit=50
wp acorn seo:audit --dry-run

Choose the interface deliberately

Design choice Best fit Trade-off
Required argument The command cannot identify its target without the value, such as a source name or record identifier. Short invocation, but omission is an error and scripts must supply the value.
Value option A filter, limit, date, post type, or alternate mode. Self-documenting and order-independent; you must validate the supplied value.
Boolean option A switch such as --dry-run or --force. Convenient for scripts, but the default behavior must be safe without the switch.
Interactive prompt A human-run operation where a missing value should be requested rather than rejected. Helpful at a terminal, unsuitable for cron, CI, or unattended deployment.

Put the work in handle()

handle() is where the command reads its inputs, calls WordPress or application services, reports progress, and returns an integer status. Acorn examples use methods such as $this->info(), $this->error(), $this->line(), $this->newLine(), and $this->components->ask().

The following implementation audits a selected post type. It is intentionally conservative: it reads posts, reports missing titles or excerpts, and does not modify content.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<?php

namespace AppConsoleCommands;

use IlluminateConsoleCommand;

class SeoAuditCommand extends Command
{
    protected $signature = 'seo:audit
        {--post-type=post : Post type to inspect}
        {--limit=50 : Maximum number of posts to inspect}
        {--dry-run : Explicitly keep the command read-only}';

    protected $description = 'Audit posts for SEO issues';

    public function handle(): int
    {
        $postType = (string) $this->option('post-type');
        $limit = (int) $this->option('limit');

        if ($limit < 1) {
            $this->error('The --limit option must be at least 1.');

            return 1;
        }

        $posts = get_posts([
            'post_type' => $postType,
            'post_status' => 'publish',
            'posts_per_page' => $limit,
            'orderby' => 'ID',
            'order' => 'ASC',
        ]);

        $issues = 0;

        foreach ($posts as $post) {
            $hasTitle = trim((string) get_the_title($post)) !== '';
            $hasExcerpt = trim((string) get_the_excerpt($post)) !== '';

            if ($hasTitle && $hasExcerpt) {
                $this->line('OK: ' . $post->ID);
                continue;
            }

            $issues++;
            $missing = [];

            if (! $hasTitle) {
                $missing[] = 'title';
            }

            if (! $hasExcerpt) {
                $missing[] = 'excerpt';
            }

            $this->error(
                'Post ' . $post->ID . ' is missing ' . implode(' and ', $missing) . '.'
            );
        }

        $this->newLine();
        $this->info(sprintf(
            'Inspected %d %s item(s); found %d issue(s).',
            count($posts),
            $postType,
            $issues
        ));

        return $issues === 0 ? 0 : 1;
    }
}

The example uses a non-zero return value when issues are found. That distinction matters in automation: a shell script, CI job, or deployment hook can stop on a failure even when the command printed useful output. Decide whether “issues found” should be a failure for your workflow and document that choice in the description or project runbook.

Use output methods for different purposes

  • info(): successful milestones and final counts.
  • error(): invalid input or a detected failure that should be visible in automation.
  • line(): neutral per-item or diagnostic output.
  • newLine(): visual separation before a summary.
  • components->ask(): a prompt for an interactive operator.

Do not prompt for a value that a scheduled invocation cannot provide. Offer an option with a safe default for unattended runs and reserve prompts for an explicitly interactive mode.

Read arguments and options safely

The signature is only the declaration; handle() still needs to validate values before using them. Convert numeric limits to integers, reject values below one, restrict post types to those your operation supports, and fail before making changes when input is invalid.

For a required argument, treat an empty or unknown value as an error. For a value option, distinguish the omitted default from an explicit override when that difference changes behavior. Keep error messages actionable: identify the option, state the accepted range or format, and show a corrected invocation when useful.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Never silently reinterpret a destructive option. If an operation deletes, overwrites, or migrates data, require an explicit switch such as --force or make the default a dry run. A command that can be safely run twice is easier to recover and schedule than one that depends on a fragile sequence of manual steps.

Design for safe re-runs and large datasets

Make the operation idempotent where possible

An idempotent command produces the same final state when run again. A cleanup command can select only records that still meet its criteria; an importer can record an external identifier and skip items already imported; a migration can check the target state before writing. If re-running is not safe, say so in the description and require an explicit confirmation or force option.

Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.

Add a dry-run mode for writes

A --dry-run option should execute selection and validation, print what would change, and skip the write or delete. Keep the dry-run path close to the real path so that it exercises the same queries and permissions. Report a count of proposed changes and make it clear that no records were modified.

Bound memory and batch size

WordPress queries that load an entire dataset can exhaust memory. Expose a limit option, process records in bounded batches, and avoid retaining every processed object in an array. For a large migration, use a stable cursor such as an increasing ID or another deterministic ordering, and persist enough state to resume after an interruption.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Batch size is a design parameter rather than a universal constant. Start with a conservative value for the target hosting environment, measure execution time and memory in a staging copy, and make the size configurable. A command that works for 50 posts may fail when pointed at 500,000.

Separate selection, mutation, and reporting

First resolve and validate the input, then select the records, then perform the mutation, and finally print a summary. This separation makes dry runs possible and lets you return a failure code when a subset of items could not be processed. Include the item identifier in per-item errors so an operator can retry or repair one record.

Choose a command, scheduled job, or queue worker

Not every long-running task belongs in an interactive WP-CLI command. Use the execution model that matches the workload.

Execution model Use it when Important design considerations
Interactive WP-CLI command An operator starts an audit, one-off cleanup, import, or migration from a terminal. Provide readable progress, predictable exit codes, and optional prompts only when a human is present.
Scheduled job The same maintenance task should run on a timetable without a person at the keyboard. Do not require prompts; use defaults and options, keep runs bounded, and make retries safe.
Queue worker The work is too large for one request or should be distributed and retried per item. Move item-level work into jobs, record failures, and let the command enqueue or monitor work rather than doing everything synchronously.

Acorn’s console layer is especially useful when the command needs both Laravel-style console services and WordPress APIs. The command remains a convenient operator interface even when the underlying work is delegated to a scheduler or queue.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Run and inspect the command

After saving the class and deploying the autoloader, invoke the command through Acorn:

wp acorn seo:audit

Override the defaults with options:

wp acorn seo:audit --post-type=page --limit=50

Ask Acorn for the command’s help text:

wp acorn help seo:audit

Help output is the fastest way to confirm that the signature being loaded is the one you intended. It should show the command name, description, options, and defaults. If it does not, verify that WP-CLI is operating on the expected WordPress installation and that the deployed class is in the project’s autoloaded application directory.

Run read-only audits against a staging database first. For a write command, make a database backup and begin with --dry-run if available. Capture standard output and the process exit code in automation; a visually successful message is not a substitute for a reliable status.

Fix “acorn is not a registered wp command”

When wp acorn is unknown, work through the boot chain in order:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Confirm the command is being run inside the correct project. Check the current directory, WordPress installation, environment variables, and WP-CLI path. A globally installed WP-CLI pointed at another site will not load your project’s Acorn dependency.
  2. Confirm Composer dependencies are installed. Deploy the project’s Composer files and generated autoloader. A command class cannot load if the Acorn package or its dependencies are missing.
  3. Activate the Acorn-booting theme or plugin. Acorn is discovered only when the extension that boots it is active. This is the documented cause of the exact unregistered-command error.
  4. Check the runtime requirements. Verify the PHP version, WordPress version, and WP-CLI installation against the requirements of the Acorn release you installed.
  5. Test the namespace before the custom command. Run an Acorn help command. If the namespace itself is unavailable, editing SeoAuditCommand will not solve the problem.
  6. Check the generated file and namespace. Keep the class under app/Console/Commands/ and compare its namespace and base class with another generated command from the same project.
  7. Clear deployment inconsistencies. Ensure the server is using the newly deployed release, not an older symlink or stale container, and that the Composer autoloader was regenerated for that release.

If wp acorn works but your command is missing, the problem has moved from Acorn bootstrapping to command discovery or the class itself. Re-run the generator to create a known-good file, then reapply your signature and implementation in small increments.

Example: a cleanup command with a controlled write path

Roots shows a cleanup pattern using a command such as wp acorn wp:cleanup-drafts --days=7 and reporting how many drafts were deleted. A production-grade version should make the selection criteria explicit, support a dry run, and return a failure code if an item cannot be processed.

<?php

namespace AppConsoleCommands;

use IlluminateConsoleCommand;

class CleanupDraftsCommand extends Command
{
    protected $signature = 'wp:cleanup-drafts
        {--days=7 : Delete drafts older than this many days}
        {--dry-run : Report matching drafts without deleting them}';

    protected $description = 'Remove old WordPress drafts';

    public function handle(): int
    {
        $days = (int) $this->option('days');
        $dryRun = (bool) $this->option('dry-run');

        if ($days < 1) {
            $this->error('The --days option must be at least 1.');

            return 1;
        }

        $before = gmdate('Y-m-d H:i:s', time() - ($days * DAY_IN_SECONDS));
        $drafts = get_posts([
            'post_status' => 'draft',
            'post_type' => 'any',
            'posts_per_page' => 100,
            'date_query' => [
                [
                    'before' => $before,
                    'inclusive' => false,
                ],
            ],
            'fields' => 'ids',
        ]);

        if ($dryRun) {
            $this->info(sprintf(
                'Dry run: %d draft(s) match the cleanup criteria; nothing was deleted.',
                count($drafts)
            ));

            return 0;
        }

        $deleted = 0;
        foreach ($drafts as $postId) {
            if (wp_delete_post((int) $postId, true)) {
                $deleted++;
                $this->line('Deleted draft ' . $postId);
                continue;
            }

            $this->error('Could not delete draft ' . $postId);
        }

        $this->info(sprintf('Deleted %d draft(s).', $deleted));

        return $deleted === count($drafts) ? 0 : 1;
    }
}

The example limits one run to 100 IDs. A site with more matches needs pagination or repeated bounded runs rather than an unbounded query. Before enabling deletion, verify the date interpretation, post statuses, post types, and retention policy in staging; “older than seven days” is a business rule, not a universally safe default.

Deployment checklist

  • Acorn is installed through the project’s Composer workflow.
  • The active theme or plugin boots Acorn during WP-CLI execution.
  • The deployed PHP, WordPress, and WP-CLI versions satisfy the installed Acorn release.
  • The command class is autoloaded from app/Console/Commands/ or an intentionally configured equivalent.
  • $signature documents names, defaults, and switches accurately.
  • Arguments and options are validated before reads or writes occur.
  • Destructive operations have a dry-run or explicit confirmation path.
  • Large datasets are processed in bounded batches.
  • Output identifies progress and failures without requiring an interactive terminal.
  • The command returns a meaningful integer status for automation.
  • wp acorn help your:command and a real invocation have been tested in the target environment.

Acorn release details to verify

A Roots product page displays Acorn v6.3.0, but that displayed version is volatile and should not be treated as the version installed in your project. Pin and verify the release through your Composer lock file and the release’s installation requirements. Generated code and supported PHP versions can change between major releases, so regenerate a command with the same Acorn version used in deployment when upgrading.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Conclusion

Writing a custom WP-CLI command with Acorn is a short, repeatable process: boot Acorn from an active theme or plugin, generate the class with wp acorn make:command, keep it in app/Console/Commands/, define the public interface in $signature, implement validated work in handle(), and run it through wp acorn. Treat exit codes, dry runs, idempotence, and bounded batches as part of the command’s design—not as afterthoughts—and the result can safely serve both a developer at a terminal and an unattended maintenance system.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

AcornCommand LineLaravelPHPWordPressWordPress developmentWP-CLI

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.