PHP code example of mwguerra / web-terminal

1. Go to this page and download the library: Download mwguerra/web-terminal library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

mwguerra / web-terminal example snippets


// If you generated only the Terminal page
WebTerminalPlugin::make()
    ->withoutTerminalPage()

// If you generated only the TerminalLogs resource
WebTerminalPlugin::make()
    ->withoutTerminalLogs()

// If you generated both, disable both plugin defaults
WebTerminalPlugin::make()
    ->withoutTerminalPage()
    ->withoutTerminalLogs()

// Or use only() to keep plugin services without any default pages
WebTerminalPlugin::make()
    ->only([])

// In your Filament PanelProvider
use MWGuerra\WebTerminal\WebTerminalPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            WebTerminalPlugin::make(),
        ]);
}

use MWGuerra\WebTerminal\Schemas\Components\WebTerminal;

WebTerminal::make()
    ->local()
    ->allowedCommands(['ls', 'pwd', 'cd', 'cat', 'git *'])
    ->workingDirectory(base_path())
    ->height('400px')



namespace App\Providers\Filament;

use Filament\Panel;
use Filament\PanelProvider;
use MWGuerra\WebTerminal\WebTerminalPlugin;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->plugins([
                WebTerminalPlugin::make(),
            ]);
    }
}

WebTerminalPlugin::make()
    // Configure Terminal page navigation
    ->terminalNavigation(
        icon: 'heroicon-o-command-line',
        label: 'Terminal',
        sort: 100,
        group: 'Tools',
    )
    // Configure Terminal Logs resource navigation
    ->terminalLogsNavigation(
        icon: 'heroicon-o-clipboard-document-list',
        label: 'Terminal Logs',
        sort: 101,
        group: 'Tools',
    )

// Disable Terminal page (only show logs)
WebTerminalPlugin::make()
    ->withoutTerminalPage()

// Disable Terminal Logs resource (only show terminal)
WebTerminalPlugin::make()
    ->withoutTerminalLogs()

// Register only specific components
WebTerminalPlugin::make()
    ->only([
        \MWGuerra\WebTerminal\Filament\Pages\Terminal::class,
    ])

use MWGuerra\WebTerminal\WebTerminalPlugin;

// Get current plugin instance
$plugin = WebTerminalPlugin::get();

// Check if components are enabled
$plugin->isTerminalPageEnabled();
$plugin->isTerminalLogsEnabled();

// Get navigation configuration
$plugin->getTerminalNavigationIcon();
$plugin->getTerminalNavigationLabel();
$plugin->getTerminalNavigationSort();
$plugin->getTerminalNavigationGroup();



namespace App\Filament\Pages;

use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use MWGuerra\WebTerminal\Filament\Pages\Terminal as BaseTerminal;
use MWGuerra\WebTerminal\Schemas\Components\WebTerminal;

class Terminal extends BaseTerminal
{
    public function schema(Schema $schema): Schema
    {
        return $schema
            ->components([
                Section::make('Server Terminal')
                    ->description('Execute commands on the server.')
                    ->icon('heroicon-o-command-line')
                    ->schema([
                        WebTerminal::make()
                            ->key('custom-terminal')
                            ->local()
                            // Customize allowed commands
                            ->allowedCommands([
                                'ls', 'pwd', 'cd', 'cat', 'head', 'tail',
                                'git *',
                                'php artisan *',
                                'composer *',
                                'npm *', 'yarn *',
                            ])
                            // Set working directory
                            ->workingDirectory(base_path())
                            // Enable login shell for full environment
                            ->loginShell()
                            // UI customization
                            ->timeout(60)
                            ->height('500px')
                            ->title('Development Terminal')
                            ->windowControls(true)
                            ->startConnected(false)
                            // Logging
                            ->log(
                                enabled: true,
                                commands: true,
                                identifier: 'dev-terminal',
                            ),
                    ]),
            ]);
    }
}

// In your PanelProvider
WebTerminalPlugin::make()
    ->withoutTerminalPage()  // Disable default Terminal page

// Register your custom page
public function panel(Panel $panel): Panel
{
    return $panel
        ->pages([
            \App\Filament\Pages\Terminal::class,
        ])
        ->plugins([
            WebTerminalPlugin::make()
                ->withoutTerminalPage(),
        ]);
}



namespace App\Filament\Pages;

use Filament\Pages\Page;
use Filament\Schemas\Schema;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Concerns\InteractsWithSchemas;
use Filament\Schemas\Contracts\HasSchemas;
use MWGuerra\WebTerminal\Schemas\Components\WebTerminal;

class Terminal extends Page implements HasSchemas
{
    use InteractsWithSchemas;

    protected string $view = 'filament.pages.terminal';

    public function schema(Schema $schema): Schema
    {
        return $schema
            ->components([
                Section::make('Terminal')
                    ->description('Execute allowed commands.')
                    ->icon('heroicon-o-command-line')
                    ->collapsible()
                    ->schema([
                        WebTerminal::make()
                            ->local()
                            ->allowedCommands(['ls', 'pwd', 'cd'])
                            ->timeout(10)
                            ->prompt('$ ')
                            ->historyLimit(50)
                            ->height('350px'),
                    ]),
            ]);
    }
}

'allowed_commands' => [
    'ls', 'ls *',
    'pwd',
    'cd', 'cd *',
    'uname', 'uname *',
    'whoami',
    'date',
    'uptime',
    'df -h',
    'free -m',
    'cat *',
    'head *',
    'tail *',
    'wc *',
    'grep *',
],

WebTerminal::make()
    ->allowedCommands([
        'ls', 'pwd', 'cd',           // Basic navigation
        'git *',                      // All git commands
        'npm *', 'yarn *',           // Package managers
        'php artisan migrate',        // Specific artisan command only
    ])

WebTerminal::make()
    ->allowAllCommands()

WebTerminal::make()
    ->key(fn () => 'terminal-' . auth()->id())
    ->allowedCommands(fn () => auth()->user()->isAdmin()
        ? ['*']
        : ['ls', 'pwd', 'cat'])
    ->ssh(fn () => [
        'host' => auth()->user()->server->host,
        'username' => auth()->user()->server->username,
        'key' => auth()->user()->server->private_key,
    ])
    ->log(fn () => [
        'enabled' => true,
        'commands' => true,
        'identifier' => 'user-' . auth()->id(),
        'metadata' => [
            'user_id' => auth()->id(),
            'user_email' => auth()->user()?->email,
            'tenant_id' => filament()->getTenant()?->id,
        ],
    ])

WebTerminal::make()
    ->local()
    ->allowedCommands(['ls', 'pwd', 'cd'])

WebTerminal::make()
    ->ssh(
        host: 'server.example.com',
        username: 'deploy',
        password: 'your-password',
        port: 22
    )

WebTerminal::make()
    ->ssh([
        'host' => 'server.example.com',
        'username' => 'deploy',
        'password' => 'your-password',
        'port' => 22,
    ])

// With key authentication
WebTerminal::make()
    ->ssh([
        'host' => 'server.example.com',
        'username' => 'deploy',
        'key' => file_get_contents('/path/to/private_key'),
        'passphrase' => 'optional-passphrase',
    ])

// With Closure for dynamic resolution
WebTerminal::make()
    ->ssh(fn () => [
        'host' => auth()->user()->server->host,
        'username' => auth()->user()->server->username,
        'key' => auth()->user()->server->private_key,
    ])

// Key from file
WebTerminal::make()
    ->ssh(
        host: 'localhost',
        username: 'root',
        key: file_get_contents('/path/to/private_key'),
        port: 2222
    )

// Key from environment variable
WebTerminal::make()
    ->ssh(
        host: 'localhost',
        username: 'root',
        key: env('SSH_PRIVATE_KEY'),
        port: 22
    )

// Key from Laravel Storage
use Illuminate\Support\Facades\Storage;

WebTerminal::make()
    ->ssh(
        host: 'localhost',
        username: 'root',
        key: Storage::disk('local')->get('ssh/private_key'),
        port: 2222
    )

// Key with passphrase
WebTerminal::make()
    ->ssh(
        host: 'localhost',
        username: 'root',
        key: file_get_contents('/path/to/encrypted_key'),
        passphrase: 'key-passphrase',
        port: 22
    )

use MWGuerra\WebTerminal\Data\ConnectionConfig;
use MWGuerra\WebTerminal\Enums\ConnectionType;

// Using array
WebTerminal::make()
    ->connection([
        'type' => 'ssh',
        'host' => 'server.example.com',
        'username' => 'deploy',
        'password' => 'secret',
        'port' => 22,
    ])

// Using ConnectionConfig object (constructor)
$config = new ConnectionConfig(
    type: ConnectionType::SSH,
    host: 'server.example.com',
    username: 'deploy',
    password: 'secret',
    port: 22,
);

WebTerminal::make()->connection($config)

// Using static factory methods (cleaner API)
use MWGuerra\WebTerminal\Data\ConnectionConfig;

// Local connection
$config = ConnectionConfig::local(
    timeout: 30,
    workingDirectory: base_path(),
);

// SSH with password
$config = ConnectionConfig::sshWithPassword(
    host: 'server.example.com',
    username: 'deploy',
    password: 'secret',
    port: 22,
);

// SSH with key
$config = ConnectionConfig::sshWithKey(
    host: 'server.example.com',
    username: 'deploy',
    privateKey: file_get_contents('/path/to/key'),
    passphrase: 'optional-passphrase',
);

WebTerminal::make()->connection($config)

// Stream-only terminal (no Classic mode)
WebTerminal::make()
    ->local()
    ->streamTerminal()
    ->classicTerminal(false)
    ->streamTheme([
        'background' => '#1a1b26',
        'foreground' => '#a9b1d6',
        'fontSize' => 14,
        'fontFamily' => 'JetBrains Mono, monospace',
    ])
    ->height('500px')
    ->title('Stream Terminal')

// Dual-mode terminal (toggle between Classic and Stream)
WebTerminal::make()
    ->local()
    ->allowAllCommands()
    ->streamTerminal()
    ->streamTheme([
        'background' => '#1a1b26',
        'foreground' => '#a9b1d6',
    ])
    ->height('500px')

'stream' => [
    'enabled' => env('WEB_TERMINAL_STREAM_ENABLED', false),
    'ratchet_host' => env('WEB_TERMINAL_RATCHET_HOST', '127.0.0.1'),
    'ratchet_port' => env('WEB_TERMINAL_RATCHET_PORT', 8090),
    'websocket_url' => env('WEB_TERMINAL_WEBSOCKET_URL'),
    'ssl_cert' => env('WEB_TERMINAL_SSL_CERT'),
    'ssl_key' => env('WEB_TERMINAL_SSL_KEY'),
    'working_directory' => env('WEB_TERMINAL_STREAM_CWD'),
    // ...
],

// Auto-disconnect after 30 minutes of inactivity
WebTerminal::make()
    ->local()
    ->inactivityTimeout(1800)

// Keep connection when navigating (useful for SPAs)
WebTerminal::make()
    ->local()
    ->keepConnectedOnNavigate()

// Disable inactivity timeout (never auto-disconnect)
WebTerminal::make()
    ->local()
    ->noInactivityTimeout()

'session' => [
    // Automatically disconnect when user navigates away or refreshes
    'disconnect_on_navigate' => env('WEB_TERMINAL_DISCONNECT_ON_NAVIGATE', true),

    // Inactivity timeout in seconds (0 = disabled)
    // Default: 3600 seconds (60 minutes)
    'inactivity_timeout' => env('WEB_TERMINAL_INACTIVITY_TIMEOUT', 3600),
],

// Example: Make NVM-installed node available
WebTerminal::make()
    ->local()
    ->path('/home/user/.nvm/versions/node/v18.0.0/bin:/usr/local/bin:/usr/bin:/bin')
    ->allowedCommands(['node', 'npm', 'npx'])

// Or inherit the server's PATH
WebTerminal::make()
    ->local()
    ->inheritPath()
    ->loginShell()  // Also loads shell profile for full environment

// Read-only file browser
WebTerminal::make()->readOnly()

// File browser with navigation
WebTerminal::make()->fileBrowser()

// Git operations
WebTerminal::make()->gitTerminal()

// Docker management
WebTerminal::make()->dockerTerminal()

// Node.js development
WebTerminal::make()->nodeTerminal()

// Laravel Artisan commands
WebTerminal::make()->artisanTerminal()

WebTerminal::make()
    ->gitTerminal()                    // Use git preset
    ->workingDirectory(base_path())    // Set working directory
    ->loginShell()                     // Enable full shell environment
    ->title('Git Terminal')            // Custom title
    ->height('400px')

use MWGuerra\WebTerminal\Data\Script;
use MWGuerra\WebTerminal\Schemas\Components\WebTerminal;

WebTerminal::make()
    ->local()
    ->scripts([
        Script::make('deploy')
            ->label('Deploy Application')
            ->description('Pull latest code and restart services')
            ->icon('heroicon-o-rocket-launch')
            ->commands([
                'git pull origin main',
                'composer install --no-dev',
                'php artisan migrate --force',
                'php artisan cache:clear',
            ])
            ->stopOnError(),

        Script::make('logs')
            ->label('View Recent Logs')
            ->description('Display the last 100 lines of Laravel logs')
            ->commands(['tail -100 storage/logs/laravel.log'])
            ->continueOnError(),
    ])

Script::make('maintenance')
    ->label('Enable Maintenance Mode')
    ->elevated()  // Bypasses command whitelist
    ->commands([
        'php artisan down --secret=bypass-token',
        'php artisan cache:clear',
        'php artisan config:cache',
    ])

Script::make('reboot')
    ->label('Reboot Server')
    ->elevated()
    ->willDisconnect()
    ->beforeMessage('Server will reboot in 30 seconds.')
    ->disconnectMessage('Server is rebooting. Please wait and reconnect.')
    ->confirmBeforeRun()
    ->commands(['sudo shutdown -r +1'])

// This script will only appear if 'git *' and 'composer *' are allowed
Script::make('update')
    ->commands(['git pull', 'composer install'])

// This script always appears (elevated bypasses whitelist)
Script::make('admin-task')
    ->elevated()
    ->commands(['any-command-here'])

Script::make('deploy')
    ->label('Deploy to Production')
    ->description('Full deployment with migrations')
    ->icon('heroicon-o-rocket-launch')
    ->commands([
        'git pull origin main',
        'composer install --no-dev --optimize-autoloader',
        'php artisan migrate --force',
        'php artisan config:cache',
        'php artisan route:cache',
        'php artisan view:cache',
    ])
    ->stopOnError()
    ->confirmBeforeRun()

Script::make('all-logs')
    ->label('View All Logs')
    ->description('Display recent logs from multiple sources')
    ->icon('heroicon-o-document-text')
    ->commands([
        'echo "=== Laravel Logs ==="',
        'tail -50 storage/logs/laravel.log',
        'echo ""',
        'echo "=== Nginx Access Logs ==="',
        'tail -20 /var/log/nginx/access.log',
    ])
    ->continueOnError()  // Continue even if some logs don't exist

Script::make('backup-db')
    ->label('Backup Database')
    ->description('Create a timestamped database backup')
    ->icon('heroicon-o-circle-stack')
    ->elevated()
    ->commands([
        'php artisan backup:run --only-db',
    ])
    ->confirmBeforeRun()

Script::make('server-status')
    ->label('Server Status')
    ->description('Check server health metrics')
    ->icon('heroicon-o-server')
    ->commands([
        'echo "=== Disk Usage ==="',
        'df -h',
        'echo ""',
        'echo "=== Memory Usage ==="',
        'free -m',
        'echo ""',
        'echo "=== System Uptime ==="',
        'uptime',
    ])
    ->continueOnError()

'logging' => [
    // Global toggle - can be overridden per-terminal
    'enabled' => env('WEB_TERMINAL_LOGGING', true),

    // What to log
    'log_connections' => env('WEB_TERMINAL_LOG_CONNECTIONS', true),
    'log_disconnections' => env('WEB_TERMINAL_LOG_DISCONNECTIONS', true),
    'log_commands' => env('WEB_TERMINAL_LOG_COMMANDS', true),
    'log_output' => env('WEB_TERMINAL_LOG_OUTPUT', false), // Can be verbose
    'log_errors' => env('WEB_TERMINAL_LOG_ERRORS', true),

    // Output handling
    'max_output_length' => env('WEB_TERMINAL_MAX_OUTPUT_LOG', 10000),
    'truncate_output' => true,

    // User configuration
    'user_table' => 'users',
    'user_foreign_key' => 'user_id',

    // Retention (cleanup via manual `terminal:cleanup` command)
    'retention_days' => env('WEB_TERMINAL_LOG_RETENTION', 90),

    // Terminals to log (empty = all)
    'terminals' => [], // ['local-terminal', 'ssh-terminal']

    // Multi-tenant support
    'tenant_column' => null, // 'tenant_id' if using tenancy
    'tenant_resolver' => null, // fn () => auth()->user()?->tenant_id
],

// Enable logging with all defaults from config
WebTerminal::make()
    ->local()
    ->log()

// Enable logging with custom settings (named parameters)
WebTerminal::make()
    ->key('server-terminal')
    ->ssh(host: 'server.com', username: 'admin', password: 'secret')
    ->log(
        enabled: true,                    // Enable logging
        connections: true,                // Log connect/disconnect
        commands: true,                   // Log all commands
        output: false,                    // Don't log output (verbose)
        identifier: 'production-ssh',     // Custom identifier for filtering
    )

// Disable logging for a specific terminal
WebTerminal::make()
    ->key('debug-terminal')
    ->local()
    ->log(enabled: false)

// Full audit logging (including output)
WebTerminal::make()
    ->key('audit-terminal')
    ->local()
    ->log(
        enabled: true,
        output: true,
        identifier: 'full-audit-terminal',
    )

// Array configuration with metadata
WebTerminal::make()
    ->local()
    ->log([
        'enabled' => true,
        'connections' => true,
        'commands' => true,
        'identifier' => 'admin-terminal',
        'metadata' => [
            'context' => 'admin_panel',
            'feature' => 'server_maintenance',
        ],
    ])

// Closure for dynamic resolution (recommended for user-specific data)
WebTerminal::make()
    ->local()
    ->log(fn () => [
        'enabled' => true,
        'commands' => true,
        'identifier' => 'user-terminal',
        'metadata' => [
            'user_id' => auth()->id(),
            'user_email' => auth()->user()?->email,
            'tenant_id' => filament()->getTenant()?->id,
            'session_started_at' => now()->toIso8601String(),
        ],
    ])

// Set metadata independently from log configuration
WebTerminal::make()
    ->local()
    ->log(enabled: true, commands: true)
    ->logMetadata([
        'user_id' => auth()->id(),
        'tenant_id' => filament()->getTenant()?->id,
        'context' => 'admin_panel',
    ])

// With Closure for dynamic resolution
WebTerminal::make()
    ->local()
    ->log()
    ->logMetadata(fn () => [
        'user_id' => auth()->id(),
        'user_email' => auth()->user()?->email,
        'session_started_at' => now()->toIso8601String(),
    ])

use MWGuerra\WebTerminal\Models\TerminalLog;

// Get all commands for a user today
TerminalLog::forUser(auth()->id())
    ->commands()
    ->whereDate('created_at', today())
    ->get();

// Get session summary
$logger = app(TerminalLogger::class);
$summary = $logger->getSessionSummary($sessionId);

// Get logs for a specific terminal
TerminalLog::forTerminal('production-ssh')
    ->recent(24) // Last 24 hours
    ->get();

// Get recent errors
TerminalLog::errors()
    ->recent(72)
    ->get();

// Get connection history
TerminalLog::connections()
    ->forUser($userId)
    ->orderBy('created_at', 'desc')
    ->limit(20)
    ->get();

// In config/web-terminal.php
'logging' => [
    'tenant_column' => 'tenant_id',
    'tenant_resolver' => fn () => auth()->user()?->tenant_id,
],

'tenant_resolver' => App\Services\TenantResolver::class,

class TenantResolver
{
    public function __invoke(): ?int
    {
        return session('current_tenant_id');
    }
}

// Get terminal output as plain text (ANSI codes stripped)
$text = $this->getPlainTextOutput();

// Clear all terminal output
$this->clearOutput();

// Allow only piping (low risk)
WebTerminal::make()
    ->allowedCommands(['ls', 'grep', 'sort', 'wc'])
    ->allowPipes()

// Allow piping and redirection
WebTerminal::make()
    ->allowedCommands(['ls', 'grep', 'cat', 'echo'])
    ->allowPipes()
    ->allowRedirection()

// Full shell access (high risk - trusted environments only)
WebTerminal::make()
    ->allowAllCommands()
    ->allowAllShellOperators()

// Whitelist + interactive mode (secure and functional)
WebTerminal::make()
    ->allowedCommands(['php artisan *', 'composer *', 'npm *'])
    ->allowInteractiveMode()
    ->allowAllShellOperators()

// Or use the TerminalPermission enum
use MWGuerra\WebTerminal\Enums\TerminalPermission;

WebTerminal::make()
    ->allowedCommands(['php artisan *', 'composer *'])
    ->allow([TerminalPermission::InteractiveMode, TerminalPermission::ShellOperators])

use MWGuerra\WebTerminal\Enums\TerminalPermission;

// Individual permissions
WebTerminal::make()
    ->allow([TerminalPermission::InteractiveMode, TerminalPermission::Pipes])

// All shell operators
WebTerminal::make()
    ->allow([TerminalPermission::ShellOperators])

// Everything (commands + operators + interactive)
WebTerminal::make()
    ->allow([TerminalPermission::All])

'rate_limit' => [
    'enabled' => env('WEB_TERMINAL_RATE_LIMIT', true),
    'max_attempts' => env('WEB_TERMINAL_RATE_LIMIT_MAX', 1),   // Commands per decay period
    'decay_seconds' => env('WEB_TERMINAL_RATE_LIMIT_DECAY', 1), // Decay window in seconds
],

// More permissive: 10 commands per 10 seconds
'rate_limit' => [
    'enabled' => true,
    'max_attempts' => 10,
    'decay_seconds' => 10,
],

use MWGuerra\WebTerminal\Events\CommandExecutedEvent;

class LogDangerousCommands
{
    public function handle(CommandExecutedEvent $event): void
    {
        if (str_contains($event->command, 'rm ')) {
            Log::warning('Dangerous command executed', $event->toArray());
        }
    }
}

WebTerminal::make()
    ->key('server-monitor')
    ->ssh(
        host: config('servers.production.host'),
        username: config('servers.production.user'),
        key: Storage::get('ssh/production.key'),
    )
    ->allowedCommands([
        'htop', 'top', 'df', 'free', 'uptime',
        'ps', 'netstat', 'iostat', 'vmstat',
    ])
    ->timeout(30)
    ->log(identifier: 'production-monitor')
    ->title('Production Server')
    ->height('500px')

WebTerminal::make()
    ->key('dev-sandbox')
    ->local()
    ->workingDirectory(base_path())
    ->loginShell()
    ->allowedCommands([
        'php', 'composer', 'npm', 'node', 'yarn',
        'git', 'artisan', 'pest', 'phpunit',
    ])
    ->environment([
        'PATH' => '/usr/local/bin:/usr/bin:/bin:' . base_path('vendor/bin'),
    ])
    ->log(
        commands: true,
        output: true, // Full audit trail
        identifier: 'developer-sandbox',
    )
    ->title('Development Terminal')

WebTerminal::make()
    ->key('docker-terminal')
    ->local()
    ->dockerTerminal() // Preset with docker commands
    ->log(identifier: 'docker-ops')
    ->title('Docker Management')

WebTerminal::make()
    ->key('db-readonly')
    ->local()
    ->allowedCommands(['mysql', 'psql', 'redis-cli'])
    ->timeout(60)
    ->log(
        commands: true,
        identifier: 'database-readonly',
    )
    ->title('Database Console')

WebTerminal::make()
    ->key('tenant-terminal-' . auth()->user()->tenant_id)
    ->local()
    ->workingDirectory('/var/www/tenants/' . auth()->user()->tenant_id)
    ->allowedCommands(['ls', 'cat', 'tail', 'grep'])
    ->log(identifier: 'tenant-' . auth()->user()->tenant_id)
    ->title('Tenant Files')

// In PHP
__('web-terminal::terminal.navigation.terminal')
__('web-terminal::terminal.resource.label')

// In Blade
{{ __('web-terminal::terminal.terminal.connect') }}
bash
php artisan terminal:install
bash
# Standard installation (interactive)
php artisan terminal:install

# Multi-tenant installation (adds tenant_id column)
php artisan terminal:install --with-tenant

# Standard installation (explicitly no tenant)
php artisan terminal:install --no-tenant

# Force overwrite existing files
php artisan terminal:install --force
bash
# Generate a custom Terminal page
php artisan terminal:install --page

# Generate a custom TerminalLogs resource
php artisan terminal:install --resource

# Generate both page and resource
php artisan terminal:install --page --resource

# Generate for a specific panel (multi-panel apps)
php artisan terminal:install --page --panel=admin
bash
# Publish configuration
php artisan vendor:publish --tag=web-terminal-config

# Publish views (optional)
php artisan vendor:publish --tag=web-terminal-views
bash
php artisan terminal:serve
bash
php artisan vendor:publish --tag=web-terminal-lang
bash
mkdir -p lang/es
cp lang/en/terminal.php lang/es/terminal.php
# Edit lang/es/terminal.php with Spanish translations