Skip to main content
This article is based on source-code research. The package is at v0.1 and is still in early development (as of May 2026).

What is Laravel Chisel?

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.

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

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

MethodDescription
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 and passes the answers to Chisel.
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');
    }
}
MethodDescription
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.
MethodDescription
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.
MethodDescription
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.
/* @chisel-passkeys */
Fortify::authenticateUsingPasskeys();
/* @end-chisel-passkeys */
In JSX files, use block comments wrapped in curly braces ({}).
{
    /* @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.

npm support

MethodDescription
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
  • 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.

laravel/chisel repository

Source code and the latest API reference.

Laravel starter kit official docs

See the official documentation for how to use the starter kits themselves.
Last modified on July 13, 2026