PHPackages                             ozmos/starboard - 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. ozmos/starboard

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

ozmos/starboard
===============

A command palette for Laravel

v0.1.0(5mo ago)00MITPHPPHP ^8.4CI failing

Since Nov 24Pushed 5mo agoCompare

[ Source](https://github.com/ozmos-dev/starboard)[ Packagist](https://packagist.org/packages/ozmos/starboard)[ Docs](https://github.com/ozmos-dev/starboard)[ RSS](/packages/ozmos-starboard/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (10)Versions (2)Used By (0)

Starboard
=========

[](#starboard)

Starboard is a command palette for Laravel applications. It provides a powerful, extensible command interface that allows you to quickly access and interact with your application's functionality. It is intended for use within the development environment only, but you can use it in production if you so desire.

[![Starboard Demo](./demo.gif)](./demo.gif)

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Built in commands](#built-in-commands)
    - [ImpersonateUser](#impersonateuser)
    - [TailLogs](#taillogs)
    - [Telescope Requests](#telescope-requests)
    - [Telescope Mail](#telescope-mail)
    - [Telescope Jobs](#telescope-jobs)
- [Custom Commands](#custom-commands)
    - [Anatomy of a command](#anatomy-of-a-command)
        - [List Views](#list-views)
        - [Detail Views](#detail-views)
    - [Model searching commands](#model-searching-commands)
    - [Building a command from scratch](#building-a-command-from-scratch)
        - [Example: Language Search Command](#example-language-search-command)
        - [Understanding Command Responses](#understanding-command-responses)
        - [Understanding Command Context](#understanding-command-context)
        - [Child Commands](#child-commands)
- [View Types Reference](#view-types-reference)
    - [ListBuilder Methods](#listbuilder-methods)
    - [ListItemBuilder Methods](#listitembuilder-methods)
    - [DetailBuilder Methods](#detailbuilder-methods)
    - [CommandResponse Methods](#commandresponse-methods)
    - [CommandContext Methods](#commandcontext-methods)
- [Advanced Usage](#advanced-usage)
    - [Custom Query Logic](#custom-query-logic)
    - [Pagination](#pagination)
    - [List Item Actions](#list-item-actions)
    - [Making Commands Hidden](#making-commands-hidden)
- [Configuring](#configuring)
- [Keyboard Shortcuts](#keyboard-shortcuts)
- [Troubleshooting](#troubleshooting)
    - [Commands not appearing](#commands-not-appearing)
    - [Command ID conflicts](#command-id-conflicts)
    - [Assets not loading](#assets-not-loading)
- [Contributing](#contributing)
- [Support](#support)
- [License](#license)

Installation
------------

[](#installation)

Require the package through composer

```
composer require ozmos/starboard

```

Publish the javascript assets to `./public/vendor/starboard`

```
php artisan vendor:publish --tag="starboard-assets"

```

Usage
-----

[](#usage)

Enable Starboard and register commands in a service provider

```
use Illuminate\Support\ServiceProvider;
use Ozmos\Starboard\Facades\Starboard;

class AppServiceProvider extends ServiceProvider
{
  public function boot(): void
  {
    Starboard::enable(app()->isLocal());
    Starboard::register([
      \Ozmos\Starboard\Commands\ImpersonateUser::make(),
      \Ozmos\Starboard\Commands\TelescopeRequests::make(),
    ]);
  }
}
```

Render starboard in your application using the `@starboard` blade directive, most likely in your root layout

```

    @starboard

```

Built in commands
-----------------

[](#built-in-commands)

### ImpersonateUser

[](#impersonateuser)

Search your User model and log in as user.

```
Starboard::register([
  \Ozmos\Starboard\Commands\ImpersonateUser::make()
]);
```

You can optionally configure this command further to suit your application

```
Starboard::register([
  \Ozmos\Starboard\Commands\ImpersonateUser::make()
    // title of the command (appears in initial palette list)
    ->commandTitle('Impersonate User')
    // what model to query
    ->model(\App\Models\User::class)
    // searchable table columns
    ->columns(['id', 'name', 'email'])
    // customise how the users appear in the list
    ->itemBuilder(function (ListItemBuilder $builder, $user) {
      return $builder
        ->title($user->name)
        ->subtitle($user->email)
        ->id($user->getKey());
    })
    // search filter placeholder
    ->placeholder('Search for a user')
    // what happens when the user is selected in the list
    ->onSelect(function (string $id) {
      $user = $this->model::find($id);
      Auth::login($user);
      return CommandResponse::make()->reload();
    })
]);
```

### TailLogs

[](#taillogs)

Returns the last `n` lines of a log file

```
Starboard::register([
  \Ozmos\Starboard\Commands\TailLogs::make()
]);
```

You can optionally configure the log file and number of lines returned

```
Starboard::register([
  \Ozmos\Starboard\Commands\TailLogs::make()
    ->logFile(storage_path('logs/laravel.log'))
    ->lines(500)
]);
```

### Telescope Requests

[](#telescope-requests)

View the most recent requests from your application. Requires telescope to be installed/enabled

```
Starboard::register([
  \Ozmos\Starboard\Commands\TelescopeRequests::make(),
]);
```

### Telescope Mail

[](#telescope-mail)

View the most recent mail sent from your application. Requires telescope to be installed/enabled

```
Starboard::register([
  \Ozmos\Starboard\Commands\TelescopeMail::make(),
]);
```

### Telescope Jobs

[](#telescope-jobs)

View the most recent jobs from your application. Requires telescope to be installed/enabled

```
Starboard::register([
  \Ozmos\Starboard\Commands\TelescopeJobs::make(),
]);
```

Custom Commands
---------------

[](#custom-commands)

All commands extend from the `Ozmos\Starboard\Commands\BaseCommand` class. You can either extend this base class directly, or use one of the several command builders offered to speed up the process.

### Anatomy of a command

[](#anatomy-of-a-command)

All commands extend `BaseCommand` and must implement:

- `id(): string` - A unique identifier for the command
- `title(): string` - The display name shown in the command palette
- `render(CommandContext $context)` - Returns a view that defines what the command displays

The render method must return a view provided by the `Ozmos\Starboard\Commands\Views\CommandView` class. There are two main view types:

#### List Views

[](#list-views)

List views display a searchable list of items. Use `CommandView::list()` to create a list view:

```
return CommandView::list()
  ->render(function (ListBuilder $builder) {
    // Return a collection of ListItemBuilder instances
    return collect($items)->map(function ($item) use ($builder) {
      return $builder
        ->item()
        ->title($item->name)
        ->subtitle($item->description)
        ->id($item->id);
    });
  })
  ->rerunsOnInputChange() // Re-run when user types
  ->placeholder('Search items...')
  ->onSelect(function (string $id) {
    // Handle item selection
    return CommandResponse::make()->push($detailCommand);
  })
  ->action('refresh', function (string $listItemId) {
    // Custom action for list items
    return CommandResponse::make()->toast('Refreshed!');
  });
```

List views support:

- **Async filtering**: Use `rerunsOnInputChange()` to filter results as the user types
- **Pagination**: Return a paginated result from your query (Laravel's paginator is supported)
- **Actions**: Add custom actions that appear as buttons for each list item
- **Placeholder text**: Customize the search input placeholder

#### Detail Views

[](#detail-views)

Detail views display detailed information about a single item. Use `CommandView::detail()` to create a detail view:

```
return CommandView::detail()
  ->render(function (DetailBuilder $builder) {
    return $builder
      ->text('Label', 'Value')                    // Plain text field
      ->preformatted('Code', $code)              // Preformatted text (monospace)
      ->markdown('Description', $markdown)       // Markdown content (rendered as HTML)
      ->html('Content', $html, iframe: false)     // Raw HTML content
      ->action('refresh', function () {
        return CommandResponse::make()
          ->replace($this)
          ->toast('Refreshed!');
      });
  });
```

Detail views support:

- **Text blocks**: Simple label-value pairs
- **Preformatted blocks**: Monospace text (great for code, JSON, etc.)
- **Markdown blocks**: Rendered markdown content
- **HTML blocks**: Raw HTML (with optional iframe rendering)
- **Actions**: Add custom action buttons

### Model searching commands

[](#model-searching-commands)

If your command operates around searching a list of models you can use the `ModelLookup` command builder

```
Starboard::register([
  \Ozmos\Starboard\Commands\ModelLookup::make()
     // title of the command (appears in initial palette list)
    ->commandTitle('Team Lookup')
    // id of the command (must be unique across all registered commands)
    ->commandId('team-lookup')
    // what model to query
    ->model(\App\Models\User::class)
    // searchable table columns
    ->columns(['id', 'name', 'email'])
    // customise how the users appear in the list
    ->itemBuilder(function (ListItemBuilder $builder, $user) {
      return $builder
        ->title($user->name)
        ->subtitle($user->email)
        ->id($user->getKey());
    })
    // search filter placeholder
    ->placeholder('Search for a user')
    // what happens when the user is selected in the list
    ->onSelect(function (string $id) {
      $user = $this->model::find($id);
      Auth::login($user);
      return CommandResponse::make()->reload();
    })
]);
```

### Building a command from scratch

[](#building-a-command-from-scratch)

Here we will build a complete example that demonstrates:

- Creating a custom command that returns a list of items
- Creating a child command that shows detail views
- Using CommandResponse to navigate between commands
- Using actions for additional functionality

#### Example: Language Search Command

[](#example-language-search-command)

First, let's create a command that searches through a list of programming languages:

```
use Ozmos\Starboard\Commands\BaseCommand;
use Ozmos\Starboard\Commands\CommandContext;
use Ozmos\Starboard\Commands\CommandResponse;
use Ozmos\Starboard\Commands\Views\CommandView;
use Ozmos\Starboard\Commands\Views\ListBuilder;

class SearchLanguages extends BaseCommand
{
  public function id(): string
  {
    return 'search-languages';
  }

  public function title(): string
  {
    return 'Search Languages';
  }

  public function render(CommandContext $context)
  {
    $languages = ['PHP', 'JavaScript', 'Python', 'Ruby', 'Go', 'Rust'];

    return CommandView::list()
      ->render(function (ListBuilder $builder) use ($context, $languages) {
        return collect($languages)
          ->when($context->input(), fn($query) => $query->filter(
            fn($language) => str_contains(strtolower($language), strtolower($context->input()))
          ))
          ->map(function ($language) use ($builder) {
            return $builder
              ->item()
              ->title($language)
              ->id($language);
          });
      })
      ->rerunsOnInputChange()
      ->placeholder('Search for a programming language...')
      ->onSelect($this->onSelect(...));
  }

  private function onSelect(string $language)
  {
    return CommandResponse::make()->push(LanguageDetail::make()->forLanguage($language));
  }

  public function children(): array
  {
    return [
      LanguageDetail::make()->hidden(),
    ];
  }
}
```

Now, let's create the detail command that shows information about a selected language:

```
use Ozmos\Starboard\Commands\BaseCommand;
use Ozmos\Starboard\Commands\CommandContext;
use Ozmos\Starboard\Commands\CommandResponse;
use Ozmos\Starboard\Commands\Views\CommandView;
use Ozmos\Starboard\Commands\Views\DetailBuilder;

class LanguageDetail extends BaseCommand
{
  public string $language;

  public function forLanguage(string $language): self
  {
    $this->language = $language;
    return $this;
  }

  public function id(): string
  {
    return 'language-detail';
  }

  public function title(): string
  {
    return 'Language Detail';
  }

  public function render(CommandContext $context)
  {
    return CommandView::detail()
      ->render(function (DetailBuilder $builder) {
        $info = $this->getLanguageInfo($this->language);

        return $builder
          ->text('Name', $this->language)
          ->text('Type', $info['type'])
          ->text('Year Created', $info['year'])
          ->preformatted('Description', $info['description'])
          ->markdown('Features', $info['features'])
          ->action('view-docs', fn() => CommandResponse::make()
            ->openUrl($info['docs_url'])
            ->toast('Opening documentation...'));
      });
  }

  private function getLanguageInfo(string $language): array
  {
    // Your logic to fetch language information
    return [
      'type' => 'Interpreted',
      'year' => '1995',
      'description' => 'A popular programming language...',
      'features' => '- Feature 1\n- Feature 2',
      'docs_url' => "https://example.com/docs/{$language}",
    ];
  }
}
```

Register your custom commands:

```
Starboard::register([
  SearchLanguages::make(),
]);
```

#### Understanding Command Responses

[](#understanding-command-responses)

When a user interacts with your command (selects an item, clicks an action), you return a `CommandResponse` that tells Starboard what to do next:

- `push($command)` - Navigate to a new command (adds to navigation stack)
- `replace($command)` - Replace the current command
- `openUrl($url)` - Open a URL in a new tab
- `reload()` - Reload the current page
- `dismiss()` - Close the command palette
- `toast($message)` - Show a toast notification (can be chained with other responses)

#### Understanding Command Context

[](#understanding-command-context)

The `CommandContext` provides information about the current state:

- `$context->input()` - The current search input from the user
- `$context->page()` - The current page number (for pagination)
- `$context->cursor()` - The pagination cursor (for cursor-based pagination)

#### Child Commands

[](#child-commands)

Child commands are commands that are automatically registered when their parent is registered, but are marked as hidden (not discoverable in the root command list). They're typically used for detail views or sub-commands that are only accessible through their parent.

To create a child command, return it from the `children()` method and mark it as hidden:

```
public function children(): array
{
  return [
    LanguageDetail::make()->hidden(),
  ];
}
```

View Types Reference
--------------------

[](#view-types-reference)

### ListBuilder Methods

[](#listbuilder-methods)

- `render(Closure $callback)` - Define how list items are generated. The callback receives a `ListBuilder` and should return a collection of `ListItemBuilder` instances or a paginator.
- `item()` - Create a new list item builder
- `placeholder(string $text)` - Set the search input placeholder
- `rerunsOnInputChange(bool $async = true)` - Enable automatic re-rendering when the user types
- `onSelect(Closure $callback)` - Handle item selection. Callback receives the item ID and should return a `CommandResponse`
- `action(string $name, Closure $callback)` - Add a custom action button. Callback receives the list item ID

### ListItemBuilder Methods

[](#listitembuilder-methods)

- `id(string $id)` - Set the unique identifier for this item
- `title(string $title)` - Set the main title text
- `subtitle(?string $subtitle)` - Set optional subtitle text

### DetailBuilder Methods

[](#detailbuilder-methods)

- `render(Closure $callback)` - Define the detail content. The callback receives a `DetailBuilder`
- `text(string $label, string $value)` - Add a plain text field
- `preformatted(string $label, string $value)` - Add preformatted (monospace) text
- `markdown(string $label, string $value)` - Add markdown content (rendered as HTML)
- `html(string $label, string $value, bool $iframe = false)` - Add raw HTML content
- `action(string $name, Closure $callback)` - Add a custom action button

### CommandResponse Methods

[](#commandresponse-methods)

- `push(BaseCommand $command)` - Navigate to a new command (adds to navigation history)
- `replace(BaseCommand $command)` - Replace the current command (no history)
- `openUrl(string $url)` - Open a URL in a new browser tab
- `reload()` - Reload the current page
- `dismiss()` - Close the command palette
- `toast(string $message)` - Show a toast notification (can be chained)

### CommandContext Methods

[](#commandcontext-methods)

- `input()` - Get the current search input value
- `page()` - Get the current page number (for pagination)
- `cursor()` - Get the pagination cursor (for cursor-based pagination)

Advanced Usage
--------------

[](#advanced-usage)

### Custom Query Logic

[](#custom-query-logic)

When using `ModelLookup`, you can override the default query logic:

```
\Ozmos\Starboard\Commands\ModelLookup::make()
  ->model(\App\Models\User::class)
  ->columns(['name', 'email'])
  ->query(function (CommandContext $context) {
    // Custom query logic
    return \App\Models\User::query()
      ->where('active', true)
      ->when($context->input(), function ($query) use ($context) {
        $query->where('name', 'like', '%' . $context->input() . '%');
      })
      ->orderBy('created_at', 'desc')
      ->limit(20);
  })
```

### Pagination

[](#pagination)

List views support Laravel's pagination. Simply return a paginated result:

```
return CommandView::list()
  ->render(function (ListBuilder $builder) use ($context) {
    return \App\Models\User::query()
      ->when($context->input(), fn($q) => $q->where('name', 'like', '%' . $context->input() . '%'))
      ->paginate(perPage: 10, page: $context->page())
      ->through(function ($user) use ($builder) {
        return $builder
          ->item()
          ->title($user->name)
          ->id($user->id);
      });
  });
```

### List Item Actions

[](#list-item-actions)

Add custom actions to list items that appear as buttons:

```
return CommandView::list()
  ->render(function (ListBuilder $builder) {
    // ... build items
  })
  ->action('edit', function (string $itemId) {
    return CommandResponse::make()
      ->openUrl("/users/{$itemId}/edit")
      ->toast('Opening editor...');
  })
  ->action('delete', function (string $itemId) {
    \App\Models\User::find($itemId)->delete();
    return CommandResponse::make()
      ->replace($this)
      ->toast('User deleted');
  });
```

### Making Commands Hidden

[](#making-commands-hidden)

Commands that shouldn't appear in the root command list can be marked as hidden:

```
$command->hidden();
```

Hidden commands are typically child commands that are only accessible through their parent command.

Configuring
-----------

[](#configuring)

Publish the config to `config/starboard.php`

```
php artisan vendor:publish --tag="starboard-config"

```

The configuration file allows you to customize the routing for Starboard endpoints:

```
return [
  'routes' => [
    'prefix' => '_starboard',      // URL prefix for Starboard routes
    'middleware' => ['web'],        // Middleware to apply to routes
    'name' => 'starboard.',         // Route name prefix
  ],
];
```

Keyboard Shortcuts
------------------

[](#keyboard-shortcuts)

Starboard supports the following keyboard shortcuts:

- `Cmd+K` / `Ctrl+K` - Open/close the command palette
- `Esc` - Close the command palette or go back
- `↑` / `↓` - Navigate through list items
- `Enter` - Select the highlighted item
- `Cmd+Enter` / `Ctrl+Enter` - Execute the first action (if available)

Troubleshooting
---------------

[](#troubleshooting)

### Commands not appearing

[](#commands-not-appearing)

- Ensure Starboard is enabled: `Starboard::enable(true)`
- Check that commands are registered in a service provider's `boot()` method
- Verify commands are marked as discoverable (not hidden)

### Command ID conflicts

[](#command-id-conflicts)

If you see "Command already registered" errors, ensure all command IDs are unique. You can override the `id()` method to provide a custom identifier.

### Assets not loading

[](#assets-not-loading)

Make sure you've published the assets:

```
php artisan vendor:publish --tag="starboard-assets"

```

And that the `@starboard` directive is included in your layout file.

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

Support
-------

[](#support)

For issues, questions, or feature requests, please visit the [GitHub repository](https://github.com/ozmos-dev/starboard).

License
-------

[](#license)

Starboard is open-sourced software licensed under the [MIT license](LICENSE.md).

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance70

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

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

Unknown

Total

1

Last Release

175d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/be670fed3185aa9290a43acbcc227b06817f626bb98e72ef0efb6c4c0ce65b40?d=identicon)[ozzie](/maintainers/ozzie)

---

Top Contributors

[![ozziexsh](https://avatars.githubusercontent.com/u/2093630?v=4)](https://github.com/ozziexsh "ozziexsh (2 commits)")

---

Tags

laravelcommandpalettestarboard

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/ozmos-starboard/health.svg)

```
[![Health](https://phpackages.com/badges/ozmos-starboard/health.svg)](https://phpackages.com/packages/ozmos-starboard)
```

###  Alternatives

[worksome/envy

Automatically keep your .env files in sync.

6871.8M](/packages/worksome-envy)[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

24149.7k](/packages/vormkracht10-laravel-mails)

PHPackages © 2026

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