Autonomous plugin testing for PageMotor CMS. Build plugins, deploy to staging, smoke test live sites, verify admin pages via Safari, and get notified if anything breaks.
Built on top of disler/mac-mini-agent, customised for the EP Suite plugin development workflow.
An AI agent (Claude Code) runs on your Mac and autonomously:
- Builds any of your PageMotor plugins from source
- Deploys to a staging site via SFTP (production is blocked in code)
- Smoke tests all your live sites (6 checks: HTTP status, body size, PHP errors, HTML structure, PageMotor markers, response time)
- Logs into the PageMotor admin via Safari and verifies settings pages render correctly
- Screenshots the frontend, dashboard, plugin list, and plugin settings for human review
- Monitors every 30 minutes and sends a macOS notification if a site goes down
- Rolls back deployments automatically if something breaks
# Install dependencies brew install tmux just uv yq # Clone and build git clone https://github.com/ElmsPark/mac-mini-agent.git cd mac-mini-agent cd apps/steer && swift build -c release && cd ../.. # Grant macOS permissions (System Settings > Privacy & Security) # - Accessibility (for clicking, typing, reading UI elements) # - Screen Recording (for screenshots) # Configure credentials cp .env.sample .env # Edit .env with your SFTP credentials and admin login # NOTE: Leave ANTHROPIC_API_KEY commented out to use your Max subscription (no extra cost) # Only uncomment it if you want to use API billing (costs extra per token) # Start the job server just listen# Terminal testing just pm-smoke # smoke test all sites just pm-build ep-email # build a plugin just pm-deploy ep-email # build + deploy to staging # Browser testing just pm-login # log into admin via Safari just pm-test ep-email # browser-test a plugin settings page just pm-test-all # test all plugin settings pages just pm-visual # screenshot key admin pages # Full cycle just pm-full ep-email # build + deploy + smoke + browser verify # Job management just jobs # list all jobs just latest # see latest result just stop <id> # kill a running job # Fast mode (tmux worker, fewer tokens, faster) just send-fast "your prompt here"Four apps, all running locally on your Mac:
| App | What it does |
|---|---|
| Steer | macOS GUI automation (Safari control, screenshots, OCR, clicking, typing) |
| Drive | Terminal automation via tmux (run commands, read output, parallel execution) |
| Listen | Job server on port 7600 (accepts jobs via HTTP, spawns AI agents) |
| Direct | CLI client for submitting jobs to Listen |
The AI agent reads a PageMotor-specific skill file (.claude/skills/pagemotor/SKILL.md) that teaches it your plugin conventions, site URLs, SFTP paths, and testing workflows.
- Production deployment blocked in code. The deploy script has a hard-coded bash guard that rejects any SFTP path outside the staging site. This is a string comparison, not an AI instruction.
- Credentials in
.envonly. Gitignored. SFTP passwords passed via environment variable (sshpass -e), never on the command line. - Job server requires API key. All endpoints check the
X-API-Keyheader. - 30-minute timeout. Stuck jobs are killed automatically.
- Browser tests via Playwright. Playwright (headless Chromium) handles admin login, form interaction, and plugin activation. Steer handles macOS-native GUI automation.
- No skill marketplace. One hand-written skill file, checked into git.
| Mode | Command | Speed | Auth | launchd? | Best for |
|---|---|---|---|---|---|
| Direct (default) | just send | ~20-30s | Max subscription | YES | Everything, no extra cost |
| Fast | just send-fast | ~30-80s | Max subscription | NO (terminal only) | Interactive use from a terminal |
| SDK | just send --mode sdk | ~90s | API key only (extra cost) | YES | Hooks, subagents, structured events |
Set the default in .env with WORKER_MODE=direct.
Important: If ANTHROPIC_API_KEY is set in .env, the claude CLI uses API billing instead of your Max subscription. Leave it commented out to avoid unexpected charges.
Install Listen as a background service that survives reboots:
just listen-install # install and start just listen-status # check if running just listen-uninstall # stop and removeInstall the smoke test cron (runs every 30 minutes):
cp scripts/pm-cron.plist ~/Library/LaunchAgents/com.elmspark.pm-smoke.plist launchctl load ~/Library/LaunchAgents/com.elmspark.pm-smoke.plistSends a macOS notification if any site fails.
Structured browser test definitions in specs/pm-tests/:
login.md-- Admin login flowdashboard.md-- Dashboard loads with module cardsplugins-list.md-- Plugin list with activation controlsplugin-upload.md-- Manage Plugins upload UIep-email.md-- EP Email settings pageep-gdpr.md-- EP GDPR settings pageep-newsletter.md-- EP Newsletter settings pageep-booking.md-- EP Booking settings pageep-support.md-- EP Support settings pagefrontend.md-- Frontend renders correctly
| Script | Purpose |
|---|---|
pm-smoke.sh | 6-check HTTP smoke test across all sites |
pm-deploy.sh | SFTP deploy to staging with automatic backup |
pm-rollback.sh | Restore from pre-deploy backup |
pm-browser-login.sh | Automated Safari login to PageMotor admin |
pm-browser-nav.sh | Navigate Safari to admin pages |
pm-browser-test.sh | Run browser test specs via the job server |
pm-visual.sh | Screenshot key pages for review |
pm-cron-smoke.sh | Scheduled smoke tests with macOS notifications |
- macOS 13 or later
- Homebrew, Swift (Xcode CLI Tools), tmux, just, uv, yq
- Node.js (for Playwright browser testing)
- Claude Code with Max subscription (recommended) or API key
- SFTP access to your PageMotor hosting
Built on mac-mini-agent by IndyDevDan. Steer (GUI automation) and Drive (terminal automation) are his work. The PageMotor skill, testing scripts, security hardening, Agent SDK integration, and launchd service are additions by ElmsPark.