Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Chisel Laravel Package

laravel/chisel

Laravel Chisel provides primitives for starter-kit post-install scripts, letting users opt into features and automatically remove unwanted code. Define a chisel.php with questions and file/PHP mutations to prune sections, imports, interfaces, and config.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by installing Chisel via Composer:

composer require laravel/chisel

For your first use case, create a chisel.php script in your project root. Define optional features using Question::multiselect() and specify file mutations for each selection. Example:

return Chisel::script(dirname(__DIR__))
    ->questions([
        Question::multiselect(
            name: 'features',
            label: 'Select features to enable:',
            options: [
                'auth' => 'Authentication',
                'api' => 'API Support',
            ],
        ),
    ])
    ->selected('features', 'auth', then: fn($c) => $c->apply(fn($c) => $c->php('User.php')->removeInterface('MustVerifyEmail')))
    ->selected('features', 'api', then: fn($c) => $c->apply(fn($c) => $c->file('routes/web.php')->removeLinesContaining('Route::get'))));

Run the script via an Artisan command (see Implementation Patterns for details).

Where to look first:


Implementation Patterns

Core Workflow

  1. Define Questions: Use Question::multiselect() in chisel.php to present feature choices.
  2. Branch Logic: Use selected(), selectedAny(), or selectedAll() to handle conditional mutations.
  3. File Operations: Chain methods like removeSection(), removeImport(), or delete().
  4. Execute: Run via an Artisan command with Laravel\Prompts for interactive prompts.

Common Patterns

Conditional Feature Removal

->selected('features', 'auth', then: fn($c) => $c->apply(
    fn($c) => $c->php('User.php')
        ->removeInterface('MustVerifyEmail')
        ->removeTrait('Notifiable')
))

Section-Based Cleanup

Wrap optional code in markers (PHP/JSX):

/* @chisel-passkeys */
Fortify::authenticateUsingPasskeys();
/* @end-chisel-passkeys */

Remove with:

->selected('features', 'passkeys', else: fn($c) => $c->files('FortifyServiceProvider.php')->removeSection('passkeys'))

npm Dependency Pruning

->selected('features', 'api', then: fn($c) => $c->apply(
    fn($c) => $c->npm()->remove('laravel-sanctum')
))

Artisan Command Integration

use Laravel\Prompts\multiselect;

public function handle(): void {
    $script = require base_path('chisel.php');
    $answers = $script->collectAnswers()
        ->onQuestion(fn(Question $q) => multiselect(
            label: $q->label,
            options: $q->options,
            default: $q->default ?? [],
        ))
        ->interactive($this->input->isInteractive())
        ->withAnswers(json_decode($this->option('answers'), true) ?? []);

    $script->chisel($answers);
    $this->info('Chisel cleanup complete!');
}

Integration Tips

  • Composer Scripts: Add a post-install-cmd to composer.json:
    "scripts": {
        "post-install-cmd": "php artisan install:features"
    }
    
  • CI/CD: Use --answers flag to skip prompts:
    php artisan install:features --answers='{"features":["auth"]}'
    
  • Testing: Mock collectAnswers() to test mutations:
    $script->chisel(['features' => ['auth']]);
    

Gotchas and Tips

Pitfalls

  1. Section Marker Mismatches:

    • Ensure @chisel-* markers are balanced (e.g., /* @chisel-x */ ... /* @end-chisel-x */).
    • Gotcha: JSX requires { /* @chisel-x */ } syntax, not HTML-style comments.
    • Fix: Use removeSectionMarkers() to debug—it keeps content but removes markers.
  2. PHP AST Limitations:

    • removeImport() only works for fully qualified class names (e.g., Illuminate\Support\Facades\Log).
    • Gotcha: Relative imports (e.g., use App\Models\User) may fail.
    • Fix: Use absolute paths or extend the AST parser.
  3. npm Detection:

    • Chisel auto-detects npm, yarn, pnpm, or bun via which.
    • Gotcha: If none are found, npm()->install() throws.
    • Fix: Explicitly set the package manager:
      $c->npm()->setManager('yarn')->install();
      
  4. Interactive Mode Quirks:

    • Gotcha: withAnswers() overrides interactive prompts completely. Missing keys fall back to defaults, not prompts.
    • Fix: Validate answers before passing:
      $answers = $script->collectAnswers()->withAnswers($providedAnswers)->toArray();
      
  5. File Paths:

    • Gotcha: Paths are resolved relative to the script directory (dirname(__DIR__)).
    • Fix: Use absolute paths or base_path() for clarity.

Debugging Tips

  • Dry Run: Log mutations before applying:
    $script->apply(fn($c) => $c->php('User.php')->removeInterface('MustVerifyEmail'))
        ->then(fn($mutations) => $this->info('Would run: ' . print_r($mutations, true)));
    
  • Section Debugging: Use removeSectionMarkers() to inspect content:
    $c->file('FortifyServiceProvider.php')->removeSectionMarkers('passkeys');
    
  • AST Errors: Wrap PHP mutations in try-catch:
    try {
        $c->php('User.php')->removeInterface('MustVerifyEmail');
    } catch (\Exception $e) {
        $this->error("Failed to remove interface: " . $e->getMessage());
    }
    

Extension Points

  1. Custom Question Types: Extend Laravel\Chisel\Question for checkboxes, radio buttons, etc. Example:

    Question::checkbox('features', 'Enable API?', ['api' => 'API Support']);
    

    Register a handler in collectAnswers()->onQuestion().

  2. Custom Mutations: Implement Laravel\Chisel\Mutation for domain-specific edits (e.g., database migrations):

    $c->custom('migrations', fn($m) => $m->dropTableIfExists('failed_jobs'));
    
  3. Pre/Post Hooks: Use apply() for global mutations (e.g., .env cleanup):

    $script->apply(fn($c) => $c->file('.env')->replace('APP_DEBUG=true', 'APP_DEBUG=false'));
    
  4. Package Manager Extensions: Override npm() detection logic in a service provider:

    Chisel::extend('npm', fn() => new CustomNpmManager());
    

Configuration Quirks

  • Default Answers: Set in Question constructor:
    Question::multiselect(..., default: ['auth'])
    
  • Required Fields: Enforce with required: true in Question:
    Question::multiselect(..., required: true)
    
  • Hint Text: Use hint for multi-line instructions:
    Question::multiselect(..., hint: 'Select all features you need.\nUse arrow keys to navigate.')
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky