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

# Laravel Chisel — a post-install script library for starter kits

> An introduction to laravel/chisel, a package that provides post-install script primitives for removing unwanted features from starter kits. Released as v0.1 in May 2026.

<Info>
  This article is based on source-code research. The package is at v0.1 and is still in early development (as of May 2026).
</Info>

## What is Laravel Chisel?

[Laravel Chisel](https://github.com/laravel/chisel) is a package that provides primitives for building **post-install scripts** to remove unwanted features from Laravel starter kits.

Starter kits ship with many features preinstalled, but for some projects certain features are unnecessary. Chisel solves this by providing an interactive way to "keep only what you need" after installation.

```mermaid theme={null}
graph TD
    A["Create a project with laravel new"] --> B["Install starter kit"]
    B --> C["Run the chisel.php script"]
    C --> D{"Ask the user<br>(multiselect)"}
    D --> E["Delete or edit unwanted<br>files based on selection"]
    E --> F["Final project structure"]
```

## Why is this needed?

Laravel starter kits bundle many features, but not every project needs all of them. For example:

* Projects that don't need email verification
* Projects that don't use passkey authentication
* Configurations that don't need certain Livewire components

Previously, you had to remove unwanted features manually. With Chisel, **customization is completed via interactive prompts at install time**.

## Defining a chisel.php script

A starter kit that uses Chisel places a `chisel.php` file at the project root. This file defines "which features are optional."

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

require getenv('LARAVEL_INSTALLER_AUTOLOADER');

use Laravel\Chisel\Chisel;
use Laravel\Chisel\Question;

return Chisel::script(dirname(__DIR__))
    ->questions([
        Question::multiselect(
            name: 'auth_features',
            label: 'Which authentication features would you like to enable?',
            options: [
                'email-verification' => 'Email verification',
            ],
            hint: 'Use space to select, enter to confirm.',
        ),
    ])
    ->selected('auth_features', 'email-verification',
        then: function (Chisel $c) {
            // When selected: strip the section markers and keep the code
            $c->files(
                'resources/js/pages/settings/profile.tsx',
                'app/Providers/FortifyServiceProvider.php',
            )->removeSectionMarkers('email-verification');
        },
        else: function (Chisel $c) {
            // When not selected: remove related files and features
            $c->php('app/Models/User.php')
                ->removeImport('Illuminate\Contracts\Auth\MustVerifyEmail')
                ->removeInterface('MustVerifyEmail');

            $c->file('config/fortify.php')->removeLinesContaining('Features::emailVerification()');

            $c->files(
                'app/Providers/FortifyServiceProvider.php',
                'resources/js/pages/settings/profile.tsx',
            )->removeSection('email-verification');

            $c->files(
                'resources/js/components/email-verification-notice.tsx',
                'resources/js/pages/auth/verify-email.tsx',
                'tests/Feature/Auth/EmailVerificationTest.php',
                'tests/Feature/Auth/VerificationNotificationTest.php',
            )->delete();
        },
    );
```

## Script definition methods

| Method                                     | Description                                      |
| ------------------------------------------ | ------------------------------------------------ |
| `Chisel::script($directory)`               | Create a script definition                       |
| `Question::multiselect(...)`               | Define a multiple-select question                |
| `questions([...])`                         | Set the script's questions                       |
| `questions()`                              | Get the registered questions                     |
| `collectAnswers()`                         | Start collecting answers to the questions        |
| `apply($callback)`                         | Register an unconditional mutation step          |
| `selected($key, $value, then:, else:)`     | Branch based on a single selected value          |
| `selectedAny($key, $values, then:, else:)` | Branch when any of the given values are selected |
| `selectedAll($key, $values, then:, else:)` | Branch when all of the given values are selected |
| `chisel($answers)`                         | Execute the registered mutations                 |

## Interactive answer collection

`collectAnswers()` returns an answer collector. All methods are fluent and can be called in any order. In non-interactive environments, default values are used automatically.

An external Artisan command displays prompts using [Laravel Prompts](https://laravel.com/docs/prompts) and passes the answers to Chisel.

```php theme={null}
use Illuminate\Console\Command;
use Laravel\Chisel\Chisel;
use Laravel\Chisel\Question;
use RuntimeException;

use function Laravel\Prompts\multiselect;

class InstallFeatures extends Command
{
    protected $signature = 'install:features
        {--answers= : JSON string of answers to skip interactive prompts}';

    public function handle(): void
    {
        $script = require base_path('chisel.php');

        $providedAnswers = $this->option('answers') === null
            ? []
            : json_decode((string) $this->option('answers'), true, 512, JSON_THROW_ON_ERROR);

        $answers = $script
            ->collectAnswers()
            ->onQuestion(fn (Question $question) => match ($question->type) {
                'multiselect' => multiselect(
                    label: $question->label,
                    options: $question->options,
                    default: $question->default ?? [],
                    required: $question->required,
                    hint: $question->hint,
                ),
                default => throw new RuntimeException("Unsupported question type [{$question->type}]."),
            })
            ->interactive($this->input->isInteractive())
            ->withAnswers($providedAnswers);

        $script->chisel($answers);

        $chisel = Chisel::in(base_path());

        $chisel->npm()->install();
        $chisel->npm()->run('build');
    }
}
```

| Method                      | Description                                   |
| --------------------------- | --------------------------------------------- |
| `onQuestion($callback)`     | Set the handler for question prompts          |
| `interactive($interactive)` | Set interactive mode                          |
| `withAnswers($answers)`     | Provide pre-collected answers to skip prompts |

## File mutations

Use `file($path)` for a single file and `files(...$paths)` to target multiple files.

| Method                            | Description                                   |
| --------------------------------- | --------------------------------------------- |
| `replace($search, $replace)`      | Replace strings                               |
| `removeLinesContaining($content)` | Remove lines that contain the given string    |
| `removeSectionMarkers($tag)`      | Remove section markers, keeping the content   |
| `removeSection($tag)`             | Remove section markers and the content inside |
| `delete()`                        | Delete the target files                       |

## PHP AST-based editing

`php($path)` provides editing using PHP AST. Changes are saved automatically when the object is destroyed.

For the basics of PHP AST (Abstract Syntax Tree) and using `nikic/php-parser`, see [this article](/en/advanced/php-ast).

| Method                        | Description                     |
| ----------------------------- | ------------------------------- |
| `removeImport($class)`        | Remove a `use` statement        |
| `removeTrait($trait)`         | Remove trait usage from a class |
| `removeInterface($interface)` | Remove an implemented interface |

## Section markers

Wrap optional code with a matching pair of comments.

```php theme={null}
/* @chisel-passkeys */
Fortify::authenticateUsingPasskeys();
/* @end-chisel-passkeys */
```

In JSX files, use block comments wrapped in curly braces (`{}`).

```tsx theme={null}
{
    /* @chisel-passkeys */
}
<PasskeyButton />;
{
    /* @end-chisel-passkeys */
}
```

* `removeSectionMarkers('passkeys')` — Removes the markers, keeps the code
* `removeSection('passkeys')` — Removes both the markers and the code

The `chisel-` prefix is added automatically.

```mermaid theme={null}
graph LR
    A["/* @chisel-feature */<br>code<br>/* @end-chisel-feature */"] --> B{"User selected<br>feature?"}
    B -->|removeSectionMarkers| C["Keep only the code<br>(markers removed)"]
    B -->|removeSection| D["Remove both markers<br>and code"]
```

## npm support

| Method                               | Description                                            |
| ------------------------------------ | ------------------------------------------------------ |
| `npm()->install()`                   | Install dependencies with the detected package manager |
| `npm()->run($script, ...$arguments)` | Run a package manager script                           |
| `npm()->remove(...$packages)`        | Remove packages with the detected package manager      |

The `npm()` method auto-detects npm, yarn, pnpm, and bun.

## Current development status

* **GitHub repository**: [laravel/chisel](https://github.com/laravel/chisel)
* **Release**: v0.1 (published May 2026)
* **Development period**: Released after three months of closed development

Chisel is not a package end users install directly into their Laravel apps—it's **a library that starter kits use internally**. In the future, we can expect Laravel's official starter kits to offer Chisel-powered post-install scripts.

<Card title="laravel/chisel repository" icon="github" href="https://github.com/laravel/chisel">
  Source code and the latest API reference.
</Card>

<Card title="Laravel starter kit official docs" icon="book-open" href="https://laravel.com/docs/starter-kits">
  See the official documentation for how to use the starter kits themselves.
</Card>


## Related topics

- [Creating a Laravel Starter Kit](/en/advanced/starter-kit-creation.md)
- [PHP AST](/en/advanced/php-ast.md)
- [Starter kits](/en/starter-kits.md)
- [Install Library](/en/packages/laravel-voicevox/engine-api/voice-library-management/install-library.md)
- [Installation](/en/installation.md)
