clonio-dev/clonio-cli
Clonio CLI is a command-line interface for Clonio that helps Laravel/PHP developers clone and manage application environments from the terminal. It simplifies setup and makes common cloning workflows faster, repeatable, and easier to automate.
Clonio is a database cloning/scrubbing CLI (built on Laravel Zero), so there is no service provider to register and no migrations to run — you install a binary and drive it from the terminal. Pick the channel that matches how your team ships tooling:
# Preferred inside a Laravel app: pinned, reproducible, no global state
composer require --dev clonio-dev/clonio-cli
vendor/bin/clonio --version
# Or a standalone binary (no PHP required)
mv clonio-linux-x86_64 clonio && chmod +x clonio && sudo mv clonio /usr/local/bin/clonio
Where to look first: run clonio --help, then clonio list to see the available commands before touching config. Publish/inspect the config file (typically config/clonio.php) and read it top to bottom — the clone definitions, matchers, and per-column strategies are all declarative, and that file is where 90% of your day-to-day work happens. The repo's docs/ folder is the second stop; in v1.3.0 the audit, matchers, and column-edit documentation was explicitly aligned with the actual CLI behaviour, so it is finally trustworthy as a reference.
First use case: get a production-shaped dataset into local dev without leaking PII. Define one clone pointing at your source, add matchers for the columns that must be faked (emails, names, phone numbers), and run a dry run before the real thing:
clonio clone --config=production-to-local --dry-run
clonio clone --config=production-to-local
Because it is a dev dependency, the natural second step is wiring it into a Composer script ("db:refresh": "clonio clone --config=production-to-local") so composer db:refresh is the only command a new hire needs to learn.
Config-as-code, one clone per source→target pair. Keep a clone definition per environment pair (production-to-local, production-to-staging) rather than mutating one. This keeps the destructive options (recreate_tables) scoped to the environments where dropping target tables is acceptable, and lets CI reference a specific definition by name.
Layer your scrubbing with matchers, then override per column. The matcher layer handles the common shape (all *_email columns get faked); column-level strategies handle the exceptions. As of v1.3.0 you have three strategies worth designing around:
Use recreate_tables as the drift escape hatch, not the default. When production has had migrations your local/staging DB missed, the clone fails on schema mismatch. recreate_tables rebuilds the drifted target tables from the source. Treat it as a repair mode: enable it while you are catching up on a long-lived staging box, disable it once schemas are in sync, and never enable it against a target that holds data you care about.
Run it in CI with the Docker image, pinned to a tag. ghcr.io/clonio-dev/clonio:v1.3.0 is multi-arch, so the same job works on both GitHub's amd64 and ARM runners. Mount the workspace, pass the config and credentials via env vars, and pin the tag — latest will eventually drag a DB-destroying option change into your pipeline unannounced.
Audit channels are your post-run safety net. Configure a channel (Slack/webhook/email-style) so every clone run reports what it touched. v1.3.0 fixed a bug where updating a channel silently dropped its delivery flags — if you have existing channel definitions created under v1.2.x, re-save them and verify the flags survived.
Version-pin the tool next to your app. composer require --dev clonio-dev/clonio-cli:^1.3 gives you a lockfile entry; the binary on a developer's $PATH is invisible to code review. Prefer the Composer route for anyone who touches a Laravel repo.
PHP 8.5 for the PHAR. The .phar channel requires PHP 8.5 specifically — not 8.3, not 8.4. On older runtimes use the standalone binary or Docker instead. Check php -v before filing a bug about the phar not starting.
Laravel Zero 13 upgrade changes the floor. v1.3.0 bumps the CLI's own framework and all dependencies. This matters for you in two ways: the Composer-installed package will pull a newer dependency graph into your require-dev, so run composer update --dev on a branch and check for conflicts with your app's pinned Symfony/Laravel versions; and if you had scripted around the CLI's output formatting, re-test those parsers — a major Laravel Zero bump often changes console output styling.
The macOS binary is unsigned. Gatekeeper will refuse to run it on first launch. The xattr -d com.apple.quarantine clonio step in the install docs is mandatory, not optional, and it must be re-applied after every download. Worth wrapping in an internal install script so nobody rediscovers this individually. Also note only macos-aarch64 is published — Intel Macs must use the phar or Docker.
Excluded columns are a one-way door per run. Excluding a column means the target keeps whatever was there before (or the column default). Re-running a clone does not restore data to a column you previously excluded — if you later un-exclude it, do a clean target or expect a mix of old and new values.
Structure-only tables silently drop referential expectations. Copying schema without rows is fine for lookup tables only if your app seeds them independently. If foreign keys point at a schema-row table, inserts into child tables will fail in ways that look like a Clonio bug but are actually an empty-parent problem. Seed those tables after the clone.
Generated columns cannot be targeted by matchers. Since v1.3.0 they are skipped, but a matcher pattern that previously matched a generated column will now be a no-op rather than an error. If you had a matcher entry there purely to satisfy a constraint, remove it — it is dead config that will confuse the next reader.
Keep credentials out of the config file. Source DB credentials belong in env vars referenced from the config; the config file is committed, the env file is not. Same for the audit channel webhook URLs.
Debug with a dry run and verbosity flags, not with a production target. --dry-run plus -v/-vv will surface matcher resolution and schema comparison without writing anything. When a clone fails halfway, the useful signal is almost always the first table it complained about — that is your schema-drift table, and it is usually the one you should put in recreate_tables scope or migrate by hand.
Extension point: the column-edit command. For one-off corrections, editing config and re-cloning is heavy. The column-edit command lets you adjust a column's strategy in place — but treat its changes as ephemeral unless you copy them back into the committed config; the next config-driven run will otherwise undo your intent.
How can I help you explore Laravel packages today?