> ## 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 tag，屬於開發初期階段（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 啟動套件內建了許多功能，但並非每個專案都需要所有功能。例如：

* 不需要 Email 驗證的專案
* 不使用 Passkey 認證的專案
* 不需要某些 Livewire 元件的結構

過去必須手動刪除不需要的功能，使用 Chisel 後就能**在安裝時以互動式 prompt 完成客製化**。

## 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) 顯示 prompt，並將回答交給 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)`     | 設定問題 prompt 的處理器     |
| `interactive($interactive)` | 設定是否為互動式模式           |
| `withAnswers($answers)`     | 提供事先收集好的回答，跳過 prompt |

## 檔案變更

以 `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-TW/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-TW/installation.md)
- [PHP AST](/zh-TW/advanced/php-ast.md)
- [用 Inertia.js 建構 SPA](/zh-TW/blog/inertia-introduction.md)
- [Laravel 啟動套件的建立方式](/zh-TW/advanced/starter-kit-creation.md)
- [Laravel Fortify 與啟動套件](/zh-TW/advanced/fortify.md)
