Skip to main content

Introduction

This tutorial walks you through building a Laravel application with custom artisan commands using revolution/laravel-console-starter. This starter kit accelerates development of applications that primarily use artisan commands, leveraging the full Laravel framework ecosystem rather than building standalone CLI tools. Benefits of using revolution/laravel-console-starter:
  • Quick Setup — Start developing console applications immediately without complex configurations
  • Laravel Ecosystem — Use Laravel’s rich features (task scheduling, database, notifications, etc.) in your console app
  • Artisan Commands — Leverage Laravel’s powerful Artisan system to easily create and manage your own commands
  • Testability — Write tests for your console commands using Laravel’s testing framework

Prerequisites

Ensure the following software is installed before you begin.

Project Setup

1

Create a new project

Run the following command in your terminal:
laravel new my-app --using=revolution/laravel-console-starter --no-interaction
This creates a my-app directory and sets up the basic console application structure.The following happen automatically during installation:
  • An .env file is generated from .env.example
  • php artisan key:generate sets the application encryption key
Main directory structure:
my-app/
├── app/Console/Commands/   # Place custom commands here
├── .github/workflows/
│   └── cron.yml            # GitHub Actions schedule example
├── config/                 # Application configuration
└── routes/console.php      # Command registration
2

Review the environment configuration

By default, mail sending is configured to output to the log (MAIL_MAILER=log).If you need to send actual emails, configure a service like Mailgun, Postmark, or SES in your .env file.

Creating a Console Command

1

Generate a command

Use the make:command Artisan command to create a new command:
php artisan make:command YourCommandName --command=your:command
  • YourCommandName — The class name of the command (e.g., SendDailyReport)
  • your:command — The command name used to call it (e.g., report:send-daily)
This generates app/Console/Commands/YourCommandName.php.
2

Implement the command

Edit the generated file to add your logic. Here is a Hello World example:
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

class HelloWorldCommand extends Command
{
    protected $signature = 'hello:world';
    protected $description = 'Displays a hello world message in the log';

    public function handle(): int
    {
        Log::info('Hello, World from Artisan Command!');
        $this->info('Hello, World message has been logged.');
        return Command::SUCCESS;
    }
}
The $signature property defines how the command is called. Write your logic in the handle() method.
3

Run the command

php artisan hello:world
After execution, you can confirm the message is output to storage/logs/laravel.log and the console.

Task Scheduling with GitHub Actions

Use GitHub Actions to run commands on a regular schedule — no server cron jobs required.
1

Review the workflow file

The starter kit includes a pre-configured .github/workflows/cron.yml:
name: cron

on:
  schedule:
    - cron: '0 0 * * *'  # Daily at midnight UTC

jobs:
  cron:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: shivammathur/setup-php@v2
        with:
          php-version: 8.5
          coverage: none
      - run: composer install --no-dev -q
      - run: cp .env.example .env
      - run: php artisan key:generate
      - run: php artisan inspire
2

Change the command

Replace php artisan inspire with your own command:
- name: Run Command
  run: php artisan your:command
To run multiple commands:
- name: Run Commands
  run: |
    php artisan first:command
    php artisan second:command
3

Adjust the schedule

Modify the cron expression to set your desired frequency:
Cron expressionWhen it runs
0 0 * * *Daily at midnight UTC
0 */6 * * *Every 6 hours
0 0 * * 1Weekly on Monday at midnight
4

Handle sensitive information with secrets

Use GitHub repository secrets for API keys, passwords, and other sensitive values.Add secrets in your repository under Settings > Secrets and variables > Actions, then reference them in the workflow:
- name: Run Command with Secrets
  run: php artisan your:command
  env:
    API_KEY: ${{ secrets.API_KEY }}
    DB_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}

Notification Feature

You can notify yourself of command results or errors via email, Slack, and other channels.
1

Create a notification class

php artisan make:notification TaskCompleted
This generates app/Notifications/TaskCompleted.php.
2

Configure notification channels

Publish the relevant config files if needed:
php artisan config:publish mail
php artisan config:publish services
3

Send a notification from your command

<?php

namespace App\Console\Commands;

use App\Notifications\TaskCompleted;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Notification;

class ProcessDataCommand extends Command
{
    protected $signature = 'data:process';
    protected $description = 'Process data and send notification when complete';

    public function handle(): int
    {
        $this->info('Processing data...');

        // Your processing logic...

        Notification::route('mail', '[email protected]')
            ->notify(new TaskCompleted('Data processing completed successfully'));

        return Command::SUCCESS;
    }
}
For full details, refer to the Laravel Notification documentation.

Practical Application Examples

Example 1: Website Uptime Monitoring with Slack Alerts

Create a command that checks if your websites are online and sends Slack alerts when issues are detected.
1

Install the Slack notification channel

composer require laravel/slack-notification-channel
2

Create the command and notification

php artisan make:command MonitorWebsites --command=monitor:websites
php artisan make:notification WebsiteDown
3

Configure Slack

php artisan config:publish services
Add your Slack webhook URL to .env:
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
Update config/services.php:
'slack' => [
    'webhook_url' => env('SLACK_WEBHOOK_URL'),
],
4

Implement the notification

Edit app/Notifications/WebsiteDown.php:
<?php

namespace App\Notifications;

use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;

class WebsiteDown extends Notification
{
    public function __construct(
        protected string $website,
        protected string $error,
    ) {}

    public function via($notifiable): array
    {
        return ['slack'];
    }

    public function toSlack($notifiable): SlackMessage
    {
        return (new SlackMessage)
            ->error()
            ->content('Website Down Alert!')
            ->attachment(function ($attachment) {
                $attachment->title($this->website)
                           ->content("Error: {$this->error}")
                           ->timestamp(now());
            });
    }
}
5

Implement the command

Edit app/Console/Commands/MonitorWebsites.php:
<?php

namespace App\Console\Commands;

use App\Notifications\WebsiteDown;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;

class MonitorWebsites extends Command
{
    protected $signature = 'monitor:websites {--timeout=10}';
    protected $description = 'Check if websites are online and send Slack alerts if they are down';

    protected array $websites = [
        'https://example.com',
        'https://yourwebsite.com',
    ];

    public function handle(): int
    {
        $timeout = (int) $this->option('timeout');
        $webhookUrl = config('services.slack.webhook_url');
        $hasErrors = false;

        foreach ($this->websites as $website) {
            try {
                $response = Http::timeout($timeout)->get($website);
                if ($response->successful()) {
                    $this->info("{$website}: Online ✓");
                } else {
                    $error = "HTTP status: " . $response->status();
                    $this->error("{$website}: Down ({$error})");
                    Notification::route('slack', $webhookUrl)
                        ->notify(new WebsiteDown($website, $error));
                    $hasErrors = true;
                }
            } catch (\Exception $e) {
                $this->error("{$website}: Error ({$e->getMessage()})");
                Log::error("Failed to check {$website}", ['error' => $e->getMessage()]);
                Notification::route('slack', $webhookUrl)
                    ->notify(new WebsiteDown($website, $e->getMessage()));
                $hasErrors = true;
            }
        }

        return $hasErrors ? Command::FAILURE : Command::SUCCESS;
    }
}
6

Schedule in GitHub Actions

Update .github/workflows/cron.yml:
name: Website Monitoring

on:
  schedule:
    - cron: '*/15 * * * *'  # Every 15 minutes

jobs:
  monitor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: shivammathur/setup-php@v2
        with:
          php-version: 8.5
      - run: composer install --no-dev -q
      - run: cp .env.example .env
      - run: php artisan key:generate
      - name: Monitor Websites
        run: php artisan monitor:websites
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

Example 2: Cryptocurrency Portfolio Update with Discord Notifications

Fetch cryptocurrency prices from the CoinGecko API and send portfolio updates to Discord via webhook.
1

Install the Discord notification channel

composer require revolution/laravel-notification-discord-webhook
2

Create the command and notification

php artisan make:command UpdateCryptoPortfolio --command=crypto:portfolio
php artisan make:notification CryptoPortfolioUpdate
3

Configure Discord

Add your Discord webhook URL to .env:
DISCORD_WEBHOOK=https://discord.com/api/webhooks/YOUR/WEBHOOK
Update config/services.php:
'discord' => [
    'webhook' => env('DISCORD_WEBHOOK'),
],
4

Implement and run the command

For the full implementation, see the GitHub repository tutorial.
php artisan crypto:portfolio

Example 3: Website Content Scraping with Email Notification

Create a command that scrapes content from a website and sends the results via email.
1

Create the command and notification

php artisan make:command WebScraper --command=scrape:website
php artisan make:notification ScrapingCompleted
2

Configure mail

php artisan config:publish mail
Update your .env with mail settings:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
[email protected]
MAIL_FROM_NAME="${APP_NAME}"
3

Implement and run the command

protected $signature = 'scrape:website {--url=https://example.com} {[email protected]}';

public function handle(): int
{
    $url = $this->option('url');
    $email = $this->option('email');

    $response = Http::timeout(30)->get($url);

    // Process content and send notification...
    Notification::route('mail', $email)
        ->notify(new ScrapingCompleted(true, $url, $title, $content));

    return Command::SUCCESS;
}
php artisan scrape:website [email protected]

Next Steps

You now know the fundamentals of building Laravel console applications with revolution/laravel-console-starter. To continue your journey:
  • Explore Laravel’s documentation — Dive deeper into features that can enhance your console applications at laravel.com/docs
  • Implement testing — Write tests for your commands using Laravel’s testing framework to ensure reliability
  • Explore package development — Package your console commands as reusable Laravel packages if you create similar functionality across projects
  • Stay updated — Follow Laravel News and the official Laravel blog to stay current with best practices
Last modified on May 1, 2026