cove trustCommand: A one-shot installer that drops Cove's local root certificate into the OS trust store and every NSS database it can find, so Firefox and Chromium stop showing "Not Secure" warnings on*.localhostwithout hand-rollingcertutilcommands.- Wraps
frankenphp trustfor the baseline (macOS login keychain, Linux/usr/local/share/ca-certificates+~/.pki/nssdb+~/.mozilla/firefox/*). - On Linux, auto-installs
libnss3-tools/nss-toolsifcertutilis missing, then walks~/snap/*/common/.mozilla/firefox/*/cert9.dband~/snap/chromium/*to inject the root into snap-packaged browsers — a path Caddy's built-in scanner doesn't touch. - Idempotent on re-run: existing "Cove Local Authority" entries are removed before the current root is re-added, so rotating the Caddy CA doesn't stack stale copies.
cove installcallscove_trustat the end of first setup, so a fresh install is trusted everywhere with no extra step.
- Wraps
cove memoryCommand: A cross-cutting view + editor for PHPmemory_limiteverywhere it can bite you.cove memoryprints a side-by-side report: Cove's own~/Cove/php.ini, thememory_limitbaked into the Caddyfile'sfrankenphpblock, everyphpbinary onPATH(version + loaded ini + live value), andwp-cli's effective PHP.cove memory set <value>writesmemory_limit,upload_max_filesize, andpost_max_sizeinto Cove's ini (values accept512M,2G, or-1for unlimited), regenerates the Caddyfile so FrankenPHP picks up the new limits, then walks external inis onPATHand offers to update each one individually.- New
cove_ini_gethelper inmainmakes Cove's ini the single source of truth:regenerate_caddyfilereads the current values at render time instead of hardcoding512M. cove memory set --yesaccepts every writable ini non-interactively for scripted fleet updates.
- Cove-Branded Landing Page for Plain Sites:
cove add --plainnow writes a designedindex.phpthat matches the dashboard and landing page palette — Fraunces italic headline, Geist/Geist Mono body, teal accent, and the cove brand mark — instead of leaving an empty directory that serves a 404. The page reads$_SERVER['HTTP_HOST']and__FILE__at request time, so it self-identifies no matter which hostname or mapping serves it, and includes a~-shortened absolute path so users can jump straight to the file they need to edit. - Linux
cove.serviceSystemd Unit:cove enablenow generates/etc/systemd/system/cove.servicealongside the existingmailpit.service, so the whole stack survives a reboot without a manualcove enableon each boot.- Runs FrankenPHP as the invoking user (not root),
Restart=on-failurewith a 2s backoff, and passesPHPRC+HOMEsophp-clisees the same ini Cove writes. cove enablestops any ad-hoc FrankenPHP left over from a pre-1.10 install beforesystemctltakes the listening sockets, andcove disablenow stopscove.servicefirst (with a fallback tofrankenphp stopfor users who never re-rancove enable).cove installmasks the distro-packagedfrankenphp.servicethat ships with the apt package — previously that unit would fight Cove for ports 80/443.
- Runs FrankenPHP as the invoking user (not root),
- Adminer 5.4.2 with a Native Cove Skin: The old Catppuccin-derived theme has been replaced with a full redesign matching the dashboard and landing page — warm cream + teal palette in light mode, dark olive + teal in dark mode, Fraunces/Geist/Geist Mono typography.
- Explicit light/dark toggle in the Adminer header, persisted in
localStorageand applied synchronously via a head-injected inline script so there's no theme flash on load. - Drag-to-resize sidebar (persisted, clamped 180–480px) so wide table names don't truncate.
- Cove's
AdminerCoveLoginclass now overrideshead()to inject the pre-paint theme script andadminer.jsvia\Adminer\nonce(), so the CSP nonce the Adminer core emits lines up with Cove's asset. - Stale Catppuccin preview screenshots (
adminer-theme/assets/*.webp) removed from the repo.
- Explicit light/dark toggle in the Adminer header, persisted in
- Dashboard — Post-Create Alerts, Spinner, and Smart Errors: After creating a site the dashboard now shows a persistent dismissible alert row with either "Log in to admin" (WP) or "Open site" (plain), so the one-time login URL is one click away instead of buried in the toast that fades in 3.5s.
- Inline spinner on the create button plus an animated teal progress stripe across the top of the add-row while
cove addis running (site creation takes 5–10s; the extra cue makes the wait feel intentional). - New-site row now carries the correct
size_bytesfrom the server's inlinedu -skmeasurement, so the size column shows "4.0 KB" immediately instead of—until the next refresh. - Backend translates known
cove addfailure signatures into user-facing messages ("Site name is taken", "That name is reserved", "Invalid site name", "WordPress installation failed — check the logs") instead of a flat "An error occurred." - Dashboard header pills for
dbandmailnow carry inline SVG icons (barrel database, envelope) that inheritcurrentColorso they tint correctly in both themes. - Inline
data-themebootstrap runs in<head>before any CSS paints, eliminating the first-frame FOUC on cold loads.
- Inline spinner on the create button plus an animated teal progress stripe across the top of the add-row while
cove upgradeNow Refreshes the Full Cove Surface: Pre-1.10cove upgradeonly replacedcove.sh+frankenphp+adminer-core.php, which left upgraders stuck with the old Catppuccin CSS, the old Adminerindex.php, and whatevermemory_limitthey'd set in the past.- Extracted a shared
deploy_adminer_themehelper used by bothcove installandcove upgrade. Upgraders now pick up the new Cove skin, the theme toggle, and the resizable sidebar in a singlecove upgrade— no reinstall required. - Floors Cove's
memory_limit/upload_max_filesize/post_max_sizeat1G(the fresh-install default) but leaves any user-set value>= 1Guntouched, so a user who bumped to2Gstays at2G. - Runs
cove reloadat the end of the upgrade (via the on-disk binary so the newly-replaced script's functions are in use), so dashboard and Caddyfile changes apply without a second manual step.
- Extracted a shared
- Scripted Flags on Confirmation-Only Prompts: Following the
cove ports --yesfix, the rest of the confirmation-only prompts now accept--force/--yesand auto-promote when stdin isn't a TTY, so dashboard-backed and CI-driven use never deadlocks ongum confirm.cove directive delete <name> [--force]cove proxy add <name> <domain> <target> [--force](skips the overwrite confirm)cove proxy delete <name> [--force]cove memory set <value> [--yes](accepts every writable ini in one shot)cove upgrade [--yes](skips the prompt shown when the local Adminer version can't be parsed)
- Linux — Pre-1.10 Sites and Reload Lock Were Root-Owned: Before v1.10, Cove sudo-started FrankenPHP on Linux so it could bind 80/443. Every site created from the dashboard, every
/etc/hostsedit, the reload lock dir, and thecaddy.pidfile ended up owned by root — which meant a later user-runcove deletesilently failed (with a success message) and a user-runcove reloadcouldn't reclaim its own lock. v1.10 flips this entirely:cove installrunssetcap 'cap_net_bind_service=+ep'on the FrankenPHP binary so it can bind low ports as the invoking user, without sudo.cove enablewritescove.servicewithUser=$current_user, so the systemd-managed process is user-owned going forward.- A new
heal_cove_state_ownershiphelper runs at the top ofcove_reloadand repairs ownership of the reload lock,caddy.pid, and site directories left behind by a pre-1.10 install. cove deletenow falls back tosudo -n rm -rfwhen the site dir is root-owned, and surfaces a real error (with the exact recovery command) instead of silently skipping the delete.
- Concurrent Reloads Deadlocking Caddy's Admin Server: The dashboard fires
reload_serverin the background after every site add/delete (shell_exec '…&'), so bulk actions would spawn many concurrentcove reloadprocesses. Two parallelfrankenphp reloadcalls reliably deadlock Caddy's admin endpoint with its 10s shutdown timeout, wedging further reloads and HTTP requests. v1.10 serializes reloads with an atomic lock: first caller does the work, subsequent callers touch apendingmarker and exit, and the holder re-runs once if the marker is set — so the final state always converges on the latest Sites listing. - Reload Lock TOCTOU Allowing 3+ Concurrent Reloads: The initial
mkdir + echo > pidimplementation of the reload lock left a window where a competing reload couldcatan emptypidfile, decide the holder was dead, and stomp the lock — letting two or more reloads run in parallel and racecreate_gui_file's.tmpwrites. Switched to a single lock file opened withset -C(noclobber) so the pid is written atomically with the lock's creation. The cleanup trap is also paired with an explicitrm -fat function end, since the trap was observed not firing reliably undershell_exec('cove reload &'). - Dashboard Deletes Queued During Reload Were Lost:
processDeleteQueuewouldshift()every item once,await apiPost('reload_server'), and then return — but deletes queued during that await would sit forever, because the nextdeleteSite()call short-circuited onisProcessingQueue. Wrapped the drain in an outer loop so post-reload enqueues are picked up in the same batch. - Adminer Session Warnings on Every Request: The apt
php-ztspackage defaultssession.save_pathto/var/lib/php-zts/session, owned by thefrankenphpuser. Since Cove now runs FrankenPHP as the invoking user, that path is unwritable and Adminer emits asession_start(): Failed to read session datawarning on every request. The Caddyfile now pinssession.save_pathto~/Cove/cache/sessions/(auto-created byregenerate_caddyfile), so sessions land somewhere the process can actually write to.
- Redesigned Dashboard: The built-in web dashboard at
https://cove.localhosthas been fully rewritten to match the Cove landing page.- Warm-dark-first palette with a teal accent (
oklch(72% 0.12 190)in dark mode), Fraunces/Geist/JetBrains Mono typography, and a new SVG cove/bay brand mark with disc/land/horizon/water/waves/ring layers and theme-aware colour overrides. - Single rounded card with a soft elevation shadow, three-tier backgrounds (
--bg/--panel/--bg-sunk), and subgrid columns so every WP/STATIC pill, modified stamp, size, and action row lines up across rows instead of sizing independently. - Per-site size cache at
~/Cove/cache/site-sizes.json, populated by a newrefresh_sizesAPI action. The dashboard shows cached bytes, auto-refreshes on an empty cache, and exposes a manual ↻ button in the footer. - "Last modified" column backed by a
modified_atfield inlist_sites(mtime ofpublic/falling back to the site dir), rendered as relative time with the full timestamp on hover. - Filter input with
/focus shortcut (GitHub-style), Esc to clear, and clickable WP/STATIC pills that set a dedicatedtype:chip for exact-type matching rather than substring. - Sort pill cycles name / size / modified.
- Matched substrings in domain names are wrapped in
<mark>so the letters you typed are highlighted as you filter. The site-name portion of each domain is accented in teal while the.localhostsuffix stays dim. - Optimistic single-flight delete queue: rows pop out instantly, the backend runs deletes sequentially so concurrent deletes can't race on Caddyfile regeneration or
/etc/hostswrites, and a single reload fires at the end. - Click anywhere on a row to open the site — skipped when text is selected so drag-to-copy still works.
- Login button uses an inline-grid label/spinner stack so the loading state can't shift neighbouring actions.
- Snackbar fades in/out (no sliding) and is centered without transform so Alpine's transition styles don't fight CSS centering.
- Theme defaults to
prefers-color-schemeon first visit; the moon/sun toggle cross-fades between two stroked SVGs in a 32×32 bordered button. - Inline SVG favicon ships with the dashboard — no extra asset to deploy.
- Warm-dark-first palette with a teal accent (
- Installer
--mainMode:install-cove.shnow accepts--mainto pullcove.shfrom themainbranch instead of the latest GitHub release, giving testers a one-liner for verifying unreleased changes.
cove.shPATH Hardening:cove.shnow prepends/opt/homebrew/bin,/usr/local/bin, and~/.local/bintoPATHat the top of the script. Callers with a minimalPATH— launchd plists, systemd units, and the dashboard'sshell_exec— can now findgum,wp,frankenphp, andmariadbwithout per-platform shims.- Shared Caddy Start Helpers: New
is_caddy_runningandstart_caddy_servicehelpers inmain.regenerate_caddyfileprobeslocalhost:2019before reloading and starts Caddy if it's down (the start reads the fresh Caddyfile, so no separate reload is needed).cove enabledelegates to the shared helper instead of duplicating the macOS/Linux start block.
cove addNo Longer Lies About Success on a Stopped Stack: On a stopped stack,cove addused to print "Caddy configuration reload initiated" while the reload silently failed, leaving the new site unreachable until the user noticed and rancove enable.regenerate_caddyfilenow detects a down Caddy and starts it, and the reload itself is no longer backgrounded — we wait for the admin API to return and surface a real error if it fails. The deadlock that originally motivated backgrounding is now handled at the PHP layer (the dashboard'sreload_serveralready backgroundscove reloadviashell_exec '…&').- First TLS Request After
cove addHittingtlsv1 alert internal error: On a busy running stack, the old backgrounded reload plussleep 0.25returned before Caddy had issued the new hostname's internal-CA cert.cove addnow polls the site's HTTPS URL for up to ~2s after reload so the cert is warmed up before the command returns. Happy-path cost is one ~5ms probe. cove db backupOverwriting Previous Snapshots: Backups were always written to../private/database-backup.sql, so a second run silently clobbered the earlier snapshot. Each backup now includes aYYYYMMDD-HHMMSSsuffix so repeat runs accumulate instead of overwriting.- Orphan
/etc/hostsEntries Aftercove delete:cove reloadappends127.0.0.1entries for every site hostname and custom mapping, butcove deletepreviously only removed the site directory and the custom Caddy directive file — the/etc/hostslines lingered forever. Delete now reads the mappings file beforerm -rf, then usessudo sed -i.bak -Eto strip the matching127.0.0.1lines in one pass, only prompting for sudo when entries actually need removing. - Dashboard Delete Hanging on Sudo Prompt: The
/etc/hostscleanup insidecove deleteused plainsudo sed, which hangs the caller when there's no TTY — notably the dashboard's PHPshell_exec, which was locking up the UI waiting for a password prompt nothing could answer.cove deletenow checks[ -t 0 ]and drops tosudo -notherwise, so it fails fast with a warning instead of blocking the whole delete flow. cove renameTemp File Collisions and Symlink Risk: The old database dump was written to a predictable/tmp/${old_db_name}.sqlpath, which collides if two renames run in parallel and is a symlink-attack vector on shared systems. Switched tomktempwith atrap EXITcleanup so the temp file is removed on any exit path, not just the happy path.- Shell Injection in
cove pullandcove push: Interpolating$remote_pathintossh "cd $remote_path && …"passed shell metacharacters — spaces, semicolons,$(…)— straight through to the remote shell. A path with a space would break thecd; a path with a;or$(…)would execute arbitrary commands on the remote server. A newshell_quotehelper wraps values in single quotes and rewrites interior'as'\'', andpull/pushnow route$remote_pathand$backup_filenamethrough it at everysshcall site. - Installer Prompts Silently Falling Through Under
curl | bash: When the installer is run the documented way —bash <(curl -sL https://cove.run/install-cove.sh)— bash's stdin is the piped script, so everygum confirm/choose/inputduringcove installreceived a closed stdin and silently fell through.install-cove.shnow wires the childcove installcall to/dev/ttywhen it's readable so the interactive port-conflict and option prompts actually work during the fresh install.
- Alternative HTTP/HTTPS Ports: Cove can now run alongside other local WordPress tools (Local, WordPress Studio, DevKinsta, MAMP) that already bind 80/443. The installer detects conflicts and offers a menu of alternatives.
- IPv4 and IPv6 port probing via bash
/dev/tcp, so the check works even against root-owned listeners (whichlsofcan't see from a regular user on macOS). - Recommended fallback ports
8090/8453— picked specifically to avoid the well-trodden 8080/8443/8888/8881 range used by Docker, Lando, wp-env, MAMP, and WordPress Studio. - Chosen ports persist to
~/Cove/configand are emitted into the Caddy global block ashttp_port/https_port. Site blocks continue to use their plainsite.localhost {}form — Caddy handles the rewrite automatically. - Re-running
cove installon a machine with non-default ports saved presents a "Keep current / Switch to default / Pick custom" menu so you can migrate in either direction.
- IPv4 and IPv6 port probing via bash
cove portsCommand: A new top-level command to reconfigure ports at any time, not just during install.- Interactive menu by default; accepts
--http PORT --https PORTfor scripted use. - After a port change, walks every WordPress site under
~/Cove/Sites/and runswp search-replace --all-tables --skip-plugins --skip-themesto rewrite stored URLs (siteurl, home, serialized content, custom mappings) so existing sites keep working on the new port. - Iterates each hostname a site answers on — base domain plus any entries in
site/mappings— so extra domains don't get left stale. --dry-runpreviews the port change and per-site replacement counts without committing anything.--skip-urlschanges ports without touching databases, for power users who want to migrate manually.- Shows a confirmation list before running (ask-once, not per-site).
cove installnow also runs this DB migration step when a re-install changes ports with pre-existing WordPress sites on disk.
- Interactive menu by default; accepts
- FrankenPHP-Backed
wp-cli: Cove now uses FrankenPHP's bundled PHP for both the web server andwp-cliinvocations, removing the standalonebrew install phpdependency entirely.get_wp_cmdroutes all wp-cli calls throughfrankenphp php-cli— one PHP runtime for everything Cove touches.- A dedicated
~/Cove/php.iniis written at install time and exported viaPHPRC, giving Cove full control ofmemory_limit,display_errors, anderror_reportingwithout fighting any system-wide/opt/homebrew/etc/php/*/php.ini. cove list,cove db, andcove upgradealso usefrankenphp php-cli -rfor their inline PHP helpers, so Cove works on a fresh Apple Silicon Mac with zero standalone PHP installed.
- Tailscale Access Serves Sites Directly:
cove tailscale enablenow serves site files directly from the Tailscale-scoped server block instead of reverse-proxying through the localsite.localhostblock. This fixes CSS/JS/image loading when a site is accessed from a remote device. - Dynamic siteurl/home Override: The bundled
captaincore-helper.phpMU-plugin now filtersoption_homeandoption_siteurlat request time when a site is accessed via a non-.localhosthost (Tailscale, LAN, orcove share). Assets resolve against the current host so the page renders correctly, andwp-cliis unaffected. - Smarter FrankenPHP Upgrade:
cove upgradenow detects how FrankenPHP was installed and uses the right upgrade path —aptordnffor distro-packaged installs, direct download for static binaries. - macOS Services via
launchd: Caddy, Mailpit, and the Cove-managed services now run via customlaunchdplists on macOS instead ofbrew services, giving Cove precise control over process arguments and log routing, plus proper auto-restart on crashes. - Shared Port Helpers:
port_is_free,port_is_own,port_has_conflict,prompt_custom_ports,port_url_for, andupdate_wp_site_urls_for_port_changeare now top-level helpers inmain, shared betweencove installandcove ports. - Cleaner
cove addOutput:cove addnow writesWP_DEBUG_DISPLAY = falseintowp-config.phpso WordPress doesn't forcedisplay_errorsback on mid-install, keeping the command output clean. An additional stderr filter strips any remainingDeprecated:lines that leak out of wp-cli's colorizer on PHP 8.5. - Readme Overhaul: Major readme refresh, including a new Quick Start section, a "Running Alongside Local, Studio, or DevKinsta" walkthrough, a Troubleshooting section (cert warnings, WSL systemd, port conflicts, DB recovery), and a rewritten Features list that now covers LAN/mobile, Tailscale, Cloudflare share, WordPress migration, and
/etc/hostsautomation.
- "Installation Cancelled" No Longer Reads as "Successful": The outer
install-cove.shinstaller used to printSUCCESS: Cove has been installed successfully!even when the user explicitly cancelled from Cove's interactive prompts. The installer now letsset -ehandle the non-zero exit fromcove installcleanly, so a real cancel no longer ends with a contradictory success message. - Mailpit Install on Fresh Apple Silicon Macs: The upstream Mailpit installer hardcodes
/usr/local/binas its install directory, which doesn't exist on a fresh Apple Silicon Mac (Homebrew lives at/opt/homebrew). Cove now usesbrew install mailpiton macOS instead, sidestepping the issue entirely. The upstream installer is still used on Linux, where/usr/local/binis always present. - FrankenPHP Install on Fresh Apple Silicon Macs: The official FrankenPHP installer had the same
/usr/local/binproblem — it would silently drop the binary in the current working directory instead of onPATH. Cove now runs the installer from a tempdir and, if the binary ends up there, moves it into$BIN_DIR(e.g.,/opt/homebrew/bin) before continuing. - PHP 8.5 Deprecation Noise: wp-cli 2.12.0's bundled vendor code (
react/promise,php-cli-tools/Colors.php) emitsDeprecated:warnings on PHP 8.5 that previously flooded everycove addrun — ~50 lines per install, polluting captured output like the one-time login URL. A combination of PHPRCdisplay_errors=0,WP_DEBUG_DISPLAY=false, and a precision stderr filter on the install subshell now keeps output clean while preserving real errors. - IPv6-Only Port Listeners Not Detected: The initial version of
port_is_freeonly probed127.0.0.1, which missed IPv6-only listeners like Python'shttp.server(which binds::by default). The helper now probes both IPv4 and IPv6 loopback so a service on either stack is seen. wp --versionValidation Loop:install_dependencyused to runwp --versionas a sanity check after install, which failed when no standalonephpwas on PATH (wp's shebang is#!/usr/bin/env php). The check now skips that validation step forwp, matching the existing special case formariadb.- Adminer Version Detection on macOS:
cove upgradeused Perl-regexgrep -oP ... \Kto read the installed Adminer version, which only works on GNU grep. macOS ships BSD grep, so detection silently fell back to "unknown" and the upgrade prompt always asked to re-download even when the current version was up to date. Switched to a portableLC_ALL=C sed -nEextraction that pulls the version cleanly from bothVERSION="x.y.z"and the@versiondocblock.
- Linux & WSL Support: Cove now runs natively on Linux distributions including Ubuntu, Debian, Fedora, CentOS, and RHEL. It also includes full support for Windows Subsystem for Linux (WSL).
- Automatic OS and package manager detection (
apt/dnf/brew). - Smart MariaDB service name detection across different distros.
- WP-CLI
--allow-rootsupport for Docker and WSL environments where running as root is common.
- Automatic OS and package manager detection (
- LAN Access for Mobile Sync: A new
cove lancommand enables LAN access to your sites for mobile app testing and sync.- Assigns a unique port and broadcasts via Bonjour/mDNS for easy device discovery.
- Includes
cove lan trustinstructions for installing Caddy's CA certificate on mobile devices.
- Log Viewer: A new
cove logcommand provides quick access to site logs or the global error log.- Supports
--follow(-f) flag for real-time log tailing.
- Supports
- Public Site Sharing: A new
cove sharecommand creates temporary public tunnels using Cloudflare Quick Tunnels.- Uses
cloudflared(installed on-demand via Homebrew if missing). - Generates a random public URL that works until you press Ctrl+C.
- Uses
- Tailscale Integration: A new
cove tailscalecommand exposes all Cove sites to your Tailscale network.- Auto-detects your Tailscale hostname or accepts a manual override.
- Assigns unique ports to each site, plus fixed ports for Mailpit (9901), Adminer (9902), and the dashboard (9900).
- Reverse Proxy Management: A new
cove proxycommand manages standalone reverse proxy entries.- Useful for exposing local services (like AI coding tools) via Tailscale or custom domains.
- Domain Mappings: A new
cove mappingscommand allows a single site to be served from multiple domains.- Mappings are automatically added to
/etc/hostsand the Caddyfile on reload.
- Mappings are automatically added to
- WSL Hosts Helper: A new
cove wsl-hostscommand (WSL only) displays PowerShell commands for updating the Windows hosts file so you can access Cove sites from your Windows browser.
- Catppuccin Adminer Theme: A new custom Adminer theme has been bundled with Cove, featuring the beautiful Catppuccin color palette.
- Automatic light/dark mode switching based on system preferences (Latte for light, Mocha for dark).
- Full SQL syntax highlighting with Catppuccin colors.
- Modern UI with improved typography, spacing, and styled action buttons.
- Adminer Auto-Upgrade: The
cove upgradecommand now also checks for and installs the latest version of Adminer. - Improved Site Listing: The
cove listcommand output has been refined for better readability. - Smarter Tailscale Detection: Tailscale hostname auto-detection has been improved for more reliable setup.
- Cleaner Error Display: PHP's
display_errorsis now disabled by default. The Whoops error handler has been refined to silence noisyE_DEPRECATEDandE_NOTICEwarnings (common in older plugins) while still displaying fatal errors with full stack traces. - Enhanced Share Command: The
cove sharecommand now displays a real-time access log showing timestamp, HTTP status (color-coded), client IP address, method, and path for each request. Connection loss is now detected and reported, and shutdown no longer displays terminal noise.
- Remote Site Pushing: A new
cove pushcommand has been introduced to migrate a local Cove site to a remote server via SSH.- It features an interactive TUI to guide you through selecting a local site and providing remote credentials.
- The command creates a local backup, securely uploads it, and then executes a migration script on the remote server to overwrite the destination site's content.
- Remote Site Pulling: A new
cove pullcommand has been introduced to migrate a remote WordPress site into Cove via SSH.- It features an interactive TUI to guide you through providing remote credentials.
- It can create a new local site or overwrite an existing one.
- Includes a powerful
--proxy-uploadsflag that skips downloading thewp-content/uploadsdirectory and instead configures Caddy toreverse_proxymedia requests to the live site, saving significant time and disk space.
- Piped Directives: The
cove directive add <site>command now accepts input fromstdin, allowing you to pipe complex, multi-line Caddy rules directly into a site's configuration. This is ideal for scripting and is used by the newpullcommand to set up the upload proxy.
- FrankenPHP Auto-Upgrade: The
cove upgradecommand is now more powerful. In addition to upgrading the Cove script itself, it now also checks for the latest version of the FrankenPHP binary on GitHub and will automatically download and install it if a newer version is available. - Correct Directive Order: The Caddyfile generation logic has been updated to place custom directives before the
php_serverdirective. This ensures that custom rules likereverse_proxyare evaluated first, which is critical for the new upload proxy feature to function correctly. - Automatic Directive Cleanup: When a site is deleted using
cove delete, any associated custom Caddy directive file is now also automatically removed, ensuring no orphaned configuration files are left behind.
- Self-Healing Login Command: The
cove logincommand is now "self-healing." If the command fails, it will automatically check for and inject a required Must-Use (MU) plugin into the WordPress site, then retry the login process. This ensures the command works reliably even on sites created with older versions of Cove or if the plugin was manually deleted. - Integrated MU-Plugin: Cove now uses a dedicated MU-plugin (
captaincore-helper.php) which is automatically added to new WordPress sites. This plugin provides the core functionality for one-time logins via a custom WP-CLI command (wp user login <user>) and also disables WordPress's plugin and theme auto-update email notifications for a cleaner local experience.
- Global PHP Memory Limit: The global PHP
memory_limithas been increased to 512M in the main Caddyfile configuration. This helps prevent errors when working with memory-intensive plugins or operations across all sites. - Refactored Plugin Injection: The logic for creating the MU-plugin has been moved into its own dedicated function (
inject_mu_plugin), cleaning up thecove addcommand and allowing the new self-healingcove logincommand to utilize it. - More Robust Dashboard Logins: The web dashboard's "Login" button is now significantly more reliable. It delegates directly to the
cove logincommand, inheriting its new self-healing capabilities and simplifying the dashboard's backend logic. - Non-Blocking Server Reloads: Server reloads triggered from the web UI (or the
cove reloadcommand) now run as a background process. This fixes a potential deadlock issue, preventing the dashboard from freezing and providing a much smoother user experience when adding, deleting, or modifying sites.
- Admin Login Command: A new
cove login <site> [<user>]command has been added to generate a one-time login link for a WordPress site. This works by finding the first available administrator or by specifying a user ID, email, or login. - Dashboard Login Button: The web dashboard now includes a "Login" button for WordPress sites, allowing for one-click access to the admin area. This is powered by a new
get_login_linkAPI endpoint.
- Automatic
/etc/hostsManagement: Thereloadcommand now automatically checks for and adds required entries for all Cove sites to the/etc/hostsfile, ensuring local domains resolve without manual setup. This requires sudo privileges upon first run. - Smarter Installation Script: The main installer (
install-cove.sh) is now architecture-aware, correctly using/opt/homebrew/binon Apple Silicon and/usr/local/binon Intel Macs. It will also offer to install Homebrew if it's not detected and attempt to create the installation directory if it doesn't exist. - Robust MariaDB Setup: The
cove installcommand now first attempts an automatic, non-interactivesudo mysqlcommand to create the database user. If this fails, it falls back to the interactive prompt for root credentials, improving the initial setup experience. - Resilient Site Creation: The
cove addcommand for WordPress sites is now more robust. It will automatically clean up the site directory and database if the installation process fails, preventing partial sites. It also now deletes the default "Hello Dolly" and "Akismet" plugins for a cleaner start.
- Site Renaming: A new
cove rename <old-name> <new-name>command has been added to fully rename a site. This includes updating the directory name, database name, and running a search-and-replace on the site's URL within the database. - Path & URL Commands:
- Added
cove path <name>to quickly get the full system path to a site's public directory. - Added
cove url <name>to print the fullhttps://<name>.localhostURL for a site.
- Added
- Increased Upload Limits: The default PHP
upload_max_filesizeandpost_max_sizehave been increased to 512M to allow for larger file and database imports. - Enhanced
listCommand: Thecove listcommand now includes a "Path" column, displaying the path to each site's public directory.
-
Interactive Web UI: A new web-based dashboard has been introduced at
cove.localhostfor managing sites. This interface allows users to:- Add and delete sites directly from the browser.
- View a list of all managed sites with links to each.
- See the current database user and password configuration.
- Toggle between light and dark themes.
-
FrankenPHP Support: The script now detects and prefers a
frankenphpinstallation, falling back tocaddyif it's not found. This allows Cove to leverage the performance benefits of FrankenPHP. -
One-Time Login URLs: When creating a new WordPress site, a one-time login URL is now generated and displayed, allowing for quick and easy access to the new site's admin area without needing to manually enter the generated password.
-
Database Listing: A new command,
cove db list, has been added. It provides a formatted table of all WordPress sites and their associated database credentials and size. -
Sizing Information in Site List: The
cove listcommand now includes a--totalsflag to display the disk usage of each site'spublicdirectory. -
Upgrade Command: A new
cove upgradecommand allows users to automatically fetch and install the latest version of Cove from GitHub.
-
Enhanced
listCommand: Thecove listcommand now outputs a neatly formatted and styled table for better readability, replacing the previous plain text list. -
Persistent Mailpit Storage: Mailpit is now launched with a persistent database file (
mailpit.db), ensuring that emails are not lost when the service is restarted. -
Adminer Auto-Login: The Adminer setup now includes an auto-login feature, pre-filling the database credentials from the Cove configuration file for a more seamless experience. A custom theme has also been applied.
-
Improved Output and Styling: The use of
gumhas been expanded across various commands to provide more consistent and visually appealing feedback, including styled tables, prompts, and messages. -
Refined Site Creation and Deletion:
- The site creation process now validates against a list of protected names (
cove,mailpit,adminer). - Site names are now restricted to lowercase letters, numbers, and hyphens.
- The
cove addcommand now accepts a--no-reloadflag to prevent the server from reloading, which is used by the new web UI to manage the process.
- The site creation process now validates against a list of protected names (
-
Better Service Management:
- The
cove enablecommand now ensures that any running instances of Mailpit are stopped before starting a new one to prevent conflicts. - The
cove statuscommand now provides more readable, color-coded output.
- The
-
Robust Dependency Checks: The installation script now checks for conflicting services running on ports 80 and 443 and warns the user.
-
Help Command Enhancements: The help text for all commands has been updated to be more descriptive and now includes subcommand details for
dbanddirective.
- MariaDB Connection Wait: The installation script now correctly waits for the MariaDB service to be fully available before attempting to create the database user, preventing a common installation failure.
- Initial Release of Cove, a command-line tool for local development.
- Core Service Management: Commands to
enable,disable, and check thestatusof background services (Caddy, MariaDB, Mailpit). - Site Management:
cove add <name>: Create new WordPress sites.cove add <name> --plain: Create new plain/static HTML sites.cove delete <name>: Delete sites and their associated databases.cove list: List all currently managed local sites.
- Web Dashboard: A GUI at
https://cove.localhostto view, add, and delete sites. It also provides quick links to Adminer and Mailpit. - Database Features:
cove db backup: Command to create a.sqlbackup for every WordPress site.- Integrated Adminer for web-based database management.
- Caddy Integration:
cove reload: Regenerates the master Caddyfile and gracefully reloads the Caddy server.cove directive: Sub-commands (add,update,delete,list) to manage site-specific Caddyfile rules.- Automatic HTTPS for all local sites using internal certificates.
- Development Environment:
cove install: Installs and configures all required dependencies like Caddy, MariaDB, and Mailpit using Homebrew.- Built-in Mailpit service to catch all outgoing application emails.
- Integrated Whoops for informative PHP error pages.
- Build System:
compile.sh: Script to combine all source files into a single, distributable shell script.watch.sh: A helper script usingfswatchto automatically re-compile the project on file changes.
- Versioning:
cove versioncommand to display the current version of the tool.
- License: The project is licensed under the MIT License.