> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Adding package diagnostics to about

> Learn how to use Laravel 13's AboutCommand to show your package's configuration state in CLI and JSON output, along with evaluation timing and long-term maintenance considerations.

When users contact you for support, you want a consistent way to check whether your package is enabled and which driver is selected. With `AboutCommand::add()`, you can add a section for your package to the output of `php artisan about` without implementing a dedicated command.

The official documentation includes a basic registration example. This page goes further by examining the Laravel 13 implementation, covering when information is collected, JSON types, section name collisions, and registration state in tests.

## Register the displayed content in your provider

The following example assumes that `courier.enabled` and `courier.driver` are already registered as package configuration. For how to register configuration, see [Package config merging and caching](/en/advanced/package-config-merging).

```php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Foundation\Console\AboutCommand;
use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        if (! $this->app->runningInConsole()) {
            return;
        }

        AboutCommand::add('Acme Courier', fn () => [
            'Enabled' => AboutCommand::format(
                (bool) config('courier.enabled', false),
                console: fn (bool $enabled) => $enabled ? 'ENABLED' : 'OFF',
            ),
            'Driver' => (string) config('courier.driver', 'log'),
        ]);
    }
}
```

`runningInConsole()` is a condition that avoids unnecessary registration during HTTP requests. It does not detect only when `about` is running, so the registration also happens for other Artisan commands. However, the configuration lookups inside the closure above are not executed at registration time.

<Warning>
  Choose the displayed items explicitly. Do not output API keys, access tokens, connection URLs containing credentials, or entire configuration arrays. JSON output does not automatically mask secrets either. When handling support requests, ask users to share only your package's section, and have them review its content before sharing.
</Warning>

## Think about registration and evaluation timing separately

In Laravel `v13.35.0`, `add()` does not collect data immediately. Instead, it appends a registration closure to the static `$customDataResolvers`. When `about` runs, it builds the display data and evaluates the registered data-retrieval closures.

```mermaid theme={null}
flowchart TD
    A["Provider boot()"] --> B["add() stores the registration"]
    B --> C["Run about"]
    C --> D["Collect standard info and added sections"]
    D --> E["Evaluate data-retrieval closures"]
    E --> F["Filter sections with --only"]
    F --> G["Display as CLI or JSON"]
```

Reading configuration values inside the closure reflects the state at command execution time better than reading them outside `add()` beforehand and fixing them in an array. On the other hand, the `--only` filter is applied **after** the data-retrieval closures are evaluated.

```bash theme={null}
php artisan about --only=environment
```

Even if you specify only a standard section like this, the `Acme Courier` closure above is still evaluated. Not being displayed is not the same as not being processed.

For this reason, collect the added information from configuration values or lightweight local state. If you include connectivity checks against external APIs, database queries, or file modifications, even commands that inspect unrelated sections may become slow or fail. Move connectivity checks and repairs into dedicated Artisan commands.

<Tip>
  The `runningInConsole()` condition alone does not guarantee that the `boot()` method of a deferred service provider runs. If you always want the diagnostics registered, place the registration in an eagerly loaded provider. For setups that defer only the service bindings, see [Deferred Service Providers](/en/advanced/deferred-provider).
</Tip>

## Support both CLI display and JSON types

To check only your package's information, pass the section name converted to lowercase snake case. For `Acme Courier`, this is `acme_courier`.

```bash theme={null}
php artisan about --only=acme_courier
php artisan about --only=environment,acme_courier
php artisan about --only=acme_courier --json
```

With the registration example above, when `courier.enabled` is `true` and `courier.driver` is `log`, the JSON looks like this:

```json theme={null}
{
  "acme_courier": {
    "enabled": true,
    "driver": "log"
  }
}
```

In the CLI, `Enabled` is shown as `ENABLED`. `AboutCommand::format()` is a helper that lets you specify `console` for the CLI and `json` for JSON. The example above specifies only `console`, so JSON returns the original boolean value. There is no need to reuse the CLI display string in JSON.

| Target | Conversion and handling in the implementation |
| - | - |
| `--only` values and section names | Compared after lowercasing and converting to snake case |
| JSON section keys | Section name converted to snake case |
| JSON item keys | Item name lowercased, then converted to snake case |
| `format()` values | `console` is used in the CLI and `json` in JSON. The original value is used if not specified |

Using names made of ordinary English words separated by spaces, as in the example, makes filters and JSON keys easier to work with. Keys referenced by automated processes may change when display names change, so check compatibility at release time.

## Give your section a package-specific name

`add()` appends items to the same section. Specifying a section with the same name does not replace everything that was registered earlier.

Choose a name like `Acme Courier` that distinguishes your package from others, and add to Laravel's built-in `Environment`, `Cache`, `Drivers`, and `Storage` sections only when necessary.

If you register the same item name more than once in the same section, the CLI may keep it as multiple lines, but JSON merges them into the same key and keeps the later value. Also avoid names that are written differently but become the same key after conversion to snake case. Keep registration in one place and design items to be unique in both CLI and JSON output.

## Handle static registration state in tests

The display `$data` is reset when `about` starts running, but the registration list for added information, `$customDataResolvers`, is retained. This lets the command recollect information from the same registrations every time, but if a provider's `boot()` runs repeatedly within the same PHP process, registrations may accumulate.

`AboutCommand::flushState()` is a method that clears **registrations from all packages** as well as the display data. Do not call it in a production provider to avoid duplicating your own section. Doing so also discards other packages' diagnostics.

If you rebuild the application in your own test infrastructure, decide who is responsible for resetting state between tests. If you reset it, do so before booting the target providers, and then perform all necessary registrations. Also check whether your existing test infrastructure already resets the state.

### Pre-release checklist

Check the following combinations in [Testing Laravel packages with Orchestra Testbench](/en/advanced/package-testing) and in a real application that uses your package.

| Operation to check | Expected result |
| - | - |
| `about --only=acme_courier` | Shows only the package section, with no duplicate items |
| `about --only=acme_courier --json` | `enabled` is returned as a boolean and `driver` as a string |
| `about --only=environment` | Collecting package information involves no external communication or side effects, and the command exits normally |
| Change the enabled state or the driver | Displayed values and JSON values match the configuration at command execution time |
| Run twice in the same application | Items do not accumulate, and information is recollected on each run |
| Rebuild the application in the same PHP process | Registration state does not leak between tests, and other packages' information is not lost |
| With a configuration cache present | Shows the configuration values the application is actually using, not the contents of the published configuration file |

## Related pages

<Columns cols={2}>
  <Card title="Laravel Package Development" icon="box" href="/en/advanced/package-development">
    Review the basics of providers and resource registration.
  </Card>

  <Card title="Package config merging and caching" icon="sliders" href="/en/advanced/package-config-merging">
    Review how defaults, user overrides, and the configuration cache relate to each other.
  </Card>
</Columns>

## Primary sources

* [Laravel official documentation: Adding information from packages to about](https://github.com/laravel/docs/blob/13.x/packages.md#about-artisan-command)
* [Laravel official documentation: about and --only](https://github.com/laravel/docs/blob/13.x/configuration.md#the-about-command)
* [Laravel Framework v13.35.0: AboutCommand](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Foundation/Console/AboutCommand.php): registration, evaluation order, key conversion, `format()`, and `flushState()`.
* [Laravel Framework v13.35.0: format tests](https://github.com/laravel/framework/blob/v13.35.0/tests/Foundation/Console/AboutCommandTest.php)
* [Laravel Framework v13.35.0: JSON output integration tests](https://github.com/laravel/framework/blob/v13.35.0/tests/Integration/Foundation/Console/AboutCommandTest.php)


## Related topics

- [Laravel Package Development](/en/advanced/package-development.md)
- [Laravel Doctor — application diagnostics tool](/en/blog/laravel-doctor-introduction.md)
- [Package Static Analysis (PHPStan / Larastan)](/en/advanced/package-static-analysis.md)
- [Package config merging and caching](/en/advanced/package-config-merging.md)
- [Package Version Compatibility Management](/en/advanced/package-versioning.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.