> ## 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 — 启动套件的安装后脚本库

> 介绍 laravel/chisel。这是一个为启动套件提供"安装后脚本"原语,用于删除启动套件中不需要功能的包。v0.1 于 2026 年 5 月发布。

<Info>
  本文基于源代码调查整理。这是刚打上 v0.1 标签的早期开发阶段的包(截至 2026 年 5 月)。
</Info>

## 什么是 Laravel Chisel

[Laravel Chisel](https://github.com/laravel/chisel) 是一个为构建**安装后脚本**提供原语的包,用来在 Laravel 启动套件中删除不需要的功能。

启动套件预装了很多功能,但根据项目情况,有些功能可能是多余的。Chisel 通过提供在安装后交互式地“只保留需要的功能”的机制来解决这个问题。

```mermaid theme={null}
graph TD
    A["laravel new 创建项目"] --> B["安装启动套件"]
    B --> C["执行 chisel.php 脚本"]
    C --> D{"向用户提问<br>(multiselect)"}
    D --> E["根据选择<br>删除或编辑不需要文件"]
    E --> F["最终项目构成"]
```

## 为什么需要它

Laravel 启动套件捆绑了大量功能,但并不是每个项目都需要所有这些功能。举例来说:

* 不需要邮件验证的项目
* 不使用 Passkey 认证的项目
* 不需要某些 Livewire 组件的构成

以前需要手动删除不需要的功能,而使用 Chisel,**在安装时通过交互式提示就能完成定制**。

## chisel.php 脚本定义

使用 Chisel 的启动套件会在项目根目录放置一个 `chisel.php` 文件。这个文件定义了“哪些功能作为可选项”。

```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) {
            // 被选中时:去掉分段标记,保留代码
            $c->files(
                'resources/js/pages/settings/profile.tsx',
                'app/Providers/FortifyServiceProvider.php',
            )->removeSectionMarkers('email-verification');
        },
        else: function (Chisel $c) {
            // 未被选中时:删除相关文件和功能
            $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();
        },
    );
```

## 脚本定义方法

| 方法                                         | 说明         |
| ------------------------------------------ | ---------- |
| `Chisel::script($directory)`               | 创建脚本定义     |
| `Question::multiselect(...)`               | 定义多选问题     |
| `questions([...])`                         | 设置脚本的问题    |
| `questions()`                              | 获取已注册的问题   |
| `collectAnswers()`                         | 开始收集问题的回答  |
| `apply($callback)`                         | 注册无条件的变更步骤 |
| `selected($key, $value, then:, else:)`     | 按单个选中值分支   |
| `selectedAny($key, $values, then:, else:)` | 任一值被选中时分支  |
| `selectedAll($key, $values, then:, else:)` | 所有值都被选中时分支 |
| `chisel($answers)`                         | 执行已注册的变更   |

## 交互式回答收集

`collectAnswers()` 会返回一个回答收集器。所有方法都是流式的,可以任意顺序调用。在非交互式环境下会自动使用默认值。

外部的 Artisan 命令使用 [Laravel Prompts](https://laravel.com/docs/prompts) 来显示提示,并把回答传递给 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');
    }
}
```

| 方法                          | 说明             |
| --------------------------- | -------------- |
| `onQuestion($callback)`     | 设置问题提示的处理器     |
| `interactive($interactive)` | 设置交互模式         |
| `withAnswers($answers)`     | 提供预先收集的回答以跳过提示 |

## 文件变更

用 `file($path)` 处理单个文件,用 `files(...$paths)` 处理多个文件。

| 方法                                | 说明           |
| --------------------------------- | ------------ |
| `replace($search, $replace)`      | 字符串替换        |
| `removeLinesContaining($content)` | 删除包含指定字符串的行  |
| `removeSectionMarkers($tag)`      | 去掉分段标记但保留内容  |
| `removeSection($tag)`             | 删除分段标记及其中的内容 |
| `delete()`                        | 删除目标文件       |

## 基于 PHP AST 的编辑

`php($path)` 提供基于 PHP AST 的编辑。当对象被销毁时,更改会自动保存。

关于 PHP AST(抽象语法树)基础与 `nikic/php-parser` 的使用方法,可以参考[这里](/zh/advanced/php-ast)。

| 方法                            | 说明               |
| ----------------------------- | ---------------- |
| `removeImport($class)`        | 删除 `use` 语句      |
| `removeTrait($trait)`         | 从类中删除 trait 的使用  |
| `removeInterface($interface)` | 删除已实现的 interface |

## Section Markers

用一对注释包裹可选的代码。

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

在 JSX 文件中使用花括号(`{}`)包裹的块注释。

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

* `removeSectionMarkers('passkeys')` — 删除标记但保留代码
* `removeSection('passkeys')` — 标记和代码一起删除

`chisel-` 前缀会自动添加。

```mermaid theme={null}
graph LR
    A["/* @chisel-feature */<br>代码<br>/* @end-chisel-feature */"] --> B{"用户是否<br>选择 feature?"}
    B -->|removeSectionMarkers| C["只保留代码<br>(删除标记)"]
    B -->|removeSection| D["标记和代码<br>全部删除"]
```

## npm 支持

| 方法                                   | 说明            |
| ------------------------------------ | ------------- |
| `npm()->install()`                   | 用检测到的包管理器安装依赖 |
| `npm()->run($script, ...$arguments)` | 执行包管理器的脚本     |
| `npm()->remove(...$packages)`        | 用检测到的包管理器删除包  |

`npm()` 方法会自动检测 npm、yarn、pnpm、bun。

## 当前开发状态

* **GitHub 仓库**:[laravel/chisel](https://github.com/laravel/chisel)
* **版本**:v0.1(2026 年 5 月公开)
* **开发时间**:经历约 3 个月的非公开开发后公开

Chisel 不是终端用户直接安装到 Laravel 应用中的包,而是**启动套件内部使用的库**。未来 Laravel 官方启动套件预计会基于 Chisel 提供安装后脚本。

<Card title="laravel/chisel 仓库" icon="github" href="https://github.com/laravel/chisel">
  源代码和最新的 API 参考请查看这里。
</Card>

<Card title="Laravel 启动套件官方文档" icon="book-open" href="https://laravel.com/docs/starter-kits">
  启动套件本身的使用方法请参考官方文档。
</Card>


## Related topics

- [启动套件](/zh/starter-kits.md)
- [安装](/zh/installation.md)
- [使用 Inertia.js 构建 SPA](/zh/blog/inertia-introduction.md)
- [Laravel PAO — 面向 AI 智能体的输出优化工具](/zh/blog/pao-introduction.md)
- [Laravel Maestro — 启动套件开发的编排器](/zh/blog/maestro-introduction.md)
