Grav CLI Tools — bin/grav Commands, Automation and Maintenance
In this tutorial, you'll learn Grav CLI tools — the complete bin/grav command reference, Grav Package Manager (GPM), automated maintenance tasks, creating custom console commands, and CLI automation for production operations.
What You'll Learn
- All built-in
bin/gravcommands - Grav Package Manager (GPM) commands
- Automated maintenance with CLI tools
- Creating custom CLI commands in plugins
- CLI automation scripts and Cron Jobs
- Debugging and diagnostic commands
Why It Matters
In WordPress, WP-CLI provides a command-line interface for administration. In Grav, bin/grav and bin/gpm provide similar functionality out of the box. The CLI is essential for automation — tasks like cache clearing, backup, user management, and package management are faster from the command line than through the web interface.
Real-World Use
A site administrator manages 10 Grav sites. Every morning, a cron job runs bin/grav cache --clear on all sites. Before each deployment, a script runs bin/grav install and bin/grav cache:warmup. When a security vulnerability is announced, the admin runs bin/gpm update on all 10 sites from a single terminal. All of these operations are CLI-based, scriptable, and automatable.
Learning Path
flowchart LR
A["Git Workflow"] --> B["CLI Tools
← You are here"]:::current
B --> C["Production Deployment"]
classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px
bin/grav Commands
Basic Commands
| Command | Description |
|---|---|
bin/grav list |
List all available commands |
bin/grav help [command] |
Show help for a specific command |
bin/grav version |
Show Grav version |
Server
# Start development server
bin/grav server
# Start on specific port
bin/grav server --port=8080
# Start with custom host
bin/grav server --host=0.0.0.0
Cache
# Clear all caches
bin/grav cache --clear
# Clear specific cache types
bin/grav cache --clear-twig
bin/grav cache --clear-images
bin/grav cache --clear-assets
bin/grav cache --clear-plugins
# Clear without disabling site
bin/grav cache --clear --all
# Show cache status
bin/grav cache --status
Installation
# Install dependencies (Composer + plugins)
bin/grav install
# Install only Composer dependencies
bin/grav install --composer
# Install plugins only
bin/grav install --plugins
# Set up symlinks
bin/grav install --symlinks
User Management
# Create a new admin user (interactive)
bin/grav new-admin-user
# Create user with parameters
bin/grav new-admin-user --username=admin --email=admin@example.com
# List all users
bin/grav list-users
Grav Package Manager (GPM)
Package Management
# Search for packages
bin/gpm search gallery
bin/gpm search "admin panel"
# Install a plugin
bin/gpm install admin
bin/gpm install form email login
# Install a specific version
bin/gpm install admin@1.10.0
# Install a theme
bin/gpm install quark
Updates
# Check for updates
bin/gpm check-updates
# Show all available updates
bin/gpm update --check
# Update all packages
bin/gpm update
# Update specific packages
bin/gpm update admin form
# Simulate update (dry run)
bin/gpm update --simulate
Information
# Show installed packages
bin/gpm info admin
# List all installed plugins
bin/gpm list
# Show package details
bin/gpm show admin
# Check package dependencies
bin/gpm depends admin
Uninstall
# Remove a plugin
bin/gpm uninstall admin
# Remove without confirmation
bin/gpm uninstall admin --force
Maintenance Automation
Backup Script
scripts/backup.sh:
#!/bin/bash
set -e
BACKUP_DIR="/var/backups/grav"
SITE_DIR="/var/www/grav-site"
DATE=$(date +%Y-%m-%d-%H%M%S)
# Create backup directory
mkdir -p "$BACKUP_DIR/$DATE"
# Backup user data
echo "Backing up user data..."
tar -czf "$BACKUP_DIR/$DATE/user-data.tar.gz" \
-C "$SITE_DIR" user/pages user/config user/accounts user/languages
# Check if user data backup succeeded
if [ $? -eq 0 ]; then
echo "User data backup complete."
else
echo "ERROR: User data backup failed!"
exit 1
fi
# Export plugin list
echo "Exporting plugin list..."
bin/gpm list > "$BACKUP_DIR/$DATE/plugins.txt"
# Remove backups older than 30 days
find "$BACKUP_DIR" -type d -mtime +30 -exec rm -rf {} \;
echo "Backup complete: $BACKUP_DIR/$DATE"
Health Check Script
scripts/health-check.sh:
#!/bin/bash
SITE_DIR="/var/www/grav-site"
cd "$SITE_DIR"
echo "Grav Health Check"
echo "================="
# Check PHP version
echo "PHP version: $(php -v | head -n1)"
# Check Grav version
echo "Grav version: $(php bin/grav version 2>&1)"
# Check cache status
php bin/grav cache --status
# Check for updates
php bin/gpm check-updates
# Check directory permissions
echo ""
echo "Checking permissions..."
for dir in user/data user/accounts user/config; do
if [ -w "$SITE_DIR/$dir" ]; then
echo " $dir: writable"
else
echo " $dir: NOT writable!"
fi
done
# Check disk space
echo ""
echo "Disk usage:"
df -h /var/www | tail -n1
# Check PHP extensions
echo ""
echo "Required PHP extensions:"
for ext in curl mbstring xml zip gd json; do
if php -m | grep -q "^$ext$"; then
echo " $ext: installed"
else
echo " $ext: MISSING!"
fi
done
Custom CLI Commands (Review)
As covered in Lesson 28, custom CLI commands are registered in plugins:
// user/plugins/myadmin/myadmin.php
public function onCliInit()
{
$this->grav['cli']->addCommand(
new \Grav\Plugin\Console\HealthCheckCommand()
);
$this->grav['cli']->addCommand(
new \Grav\Plugin\Console\SitemapGenerateCommand()
);
}
Sitemap Generator CLI
user/plugins/myadmin/cli/SitemapGenerateCommand.php:
<?php
namespace Grav\Plugin\Console;
use Grav\Console\ConsoleCommand;
class SitemapGenerateCommand extends ConsoleCommand
{
protected function configure()
{
$this
->setName('sitemap:generate')
->setDescription('Generate XML sitemap')
->addOption(
'pretty',
'p',
\Symfony\Component\Console\Input\InputOption::VALUE_NONE,
'Pretty-print the XML'
);
}
protected function serve($input, $output)
{
$this->setupConsole($input, $output);
$io = $this->getIO();
$io->title('Sitemap Generator');
$pages = $this->grav['pages']->all();
$xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
$xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
$io->progressStart(count($pages));
foreach ($pages as $page) {
if ($page->published() && !$page->isModule()) {
$xml .= ' <url>' . "\n";
$xml .= ' <loc>' . $page->url(true) . '</loc>' . "\n";
$xml .= ' <lastmod>' . date('c', $page->modified()) . '</lastmod>' . "\n";
$xml .= ' <priority>' . ($page->route() == '/' ? '1.0' : '0.8') . '</priority>' . "\n";
$xml .= ' </url>' . "\n";
}
$io->progressAdvance();
}
$xml .= '</urlset>' . "\n";
file_put_contents(GRAV_ROOT . '/sitemap.xml', $xml);
$io->progressFinish();
$io->success('Sitemap generated: ' . GRAV_ROOT . '/sitemap.xml');
}
}
Cron Job Integration
Set up automated tasks with cron:
# Edit crontab
crontab -e
# Add tasks
# Clear cache daily at 4 AM
0 4 * * * /usr/bin/php /var/www/grav/bin/grav cache --clear >> /var/log/grav-cache.log
# Run backup nightly at 2 AM
0 2 * * * /var/www/grav/scripts/backup.sh >> /var/log/grav-backup.log
# Health check every hour
0 * * * * /var/www/grav/scripts/health-check.sh >> /var/log/grav-health.log
# Check for updates weekly
0 6 * * 1 /usr/bin/php /var/www/grav/bin/gpm check-updates >> /var/log/grav-updates.log
Learning Path
flowchart LR
A["Git Workflow"] --> B["CLI Tools
← You are here"]:::current
B --> C["Production Deployment"]
classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px
Common Mistakes
Running CLI commands with wrong PHP binary: Ensure the PHP version used by CLI matches the one used by the web server. Use
which phpto find the correct binary.Not running
bin/grav installafter adding plugins: After adding a plugin source (manually or via Git), runbin/grav installto set up dependencies and symlinks.Forgetting to clear cache after updates: After running
bin/gpm update, always runbin/grav cache --clearto ensure the new versions take effect.Running cache warmup on an idle site: Cache warming works best on a live server. Running it on a development machine caches development URLs that are invalid in production.
Not using
--simulatebefore updates: The--simulateflag shows what would happen during an update without making changes. Always use it for major version updates.
Practice Questions
What command clears only the Twig template cache? Answer:
bin/grav cache --clear-twig. This is faster than clearing all caches and is useful when you only changed Twig templates.What is the purpose of
bin/gpm check-updates? Answer: It checks for available updates to all installed plugins and themes. It does not perform the update — usebin/gpm updateto apply updates.How do you create a new admin user from the command line? Answer: Run
bin/grav new-admin-userand follow the interactive prompts for username, password, and email.What does
bin/grav installdo? Answer: It installs Composer dependencies, sets up plugin dependencies, creates symlinks, and sets up the folder structure. It must be run after cloning a Grav site or adding plugins.Challenge: Create a comprehensive CLI automation toolkit for a production Grav site. Build: a backup script that creates compressed archives of user data and config, a health check script that validates PHP extensions, permissions, and disk space, a deployment script that pulls from Git, installs dependencies, clears cache, and warms cache, a sitemap generator CLI command, a cron configuration that runs these tasks on schedule, and a status command that shows site health at a glance. All scripts should include error handling, logging, and notifications.
FAQ
Mini Project
Goal: Build a complete CLI automation toolkit for site maintenance.
- Create a backup CLI command that backs up pages, config, and plugins
- Create a health-check CLI command that validates the installation
- Create a sitemap generation CLI command
- Create a report CLI command that outputs site statistics
- Create a maintenance CLI command that runs multiple tasks
- Add progress bars and colored output to all commands
- Create shell scripts that chain multiple CLI commands
- Set up cron jobs for automated nightly tasks
- Add logging to all CLI commands
- Create a "one-command" deploy script combining all steps
What's Next
Now you can automate everything with CLI. Next, the final lesson — production deployment:
Continue to Lesson 40: Production Deployment — Nginx configuration, SSL, monitoring, and scaling.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro