| dxkit | ||
| dx | ||
| README.md | ||
🛠️ DX
dx is a framework-agnostic bash CLI that orchestrates the full development lifecycle for PHP projects — Docker, Apache, Traefik, environment config, migrations, and tests — across multiple frameworks (Yii2, Laravel).
The dx script at the project root is the entrypoint. It loads dxkit/bootstrap.sh and dispatches to the command and module system inside dxkit/.
Prerequisites
- Bash (Linux/macOS native; Windows via Git Bash or WSL)
- Docker + Docker Compose
dxmust be executable:chmod +x dx
Quick start
./dx setup # first time: build image + init environment
./dx up # start the stack
./dx shell # enter the app container
./dx console migrate # run database migrations
Command reference
Setup & initialization
| Command | Description |
|---|---|
dx build |
Build the Docker image and generate the compose stack |
dx init [env] |
Bring the project to a runnable state for an environment (default: dev) |
dx setup |
build + init in one step |
dx build flags
| Flag | Description |
|---|---|
--dev / --qly / --prd |
Target environment (default: --dev) |
--project=NAME |
Override the project name |
--port=PORT |
Override the app HTTP port |
--db=mysql|mssql |
Database engine (default: mysql) |
--db-port=PORT |
Override the database port |
--sync-hosts |
Write the project domain to /etc/hosts after build |
--no-vhosts |
Skip Apache virtual host generation |
--no-interact |
Non-interactive mode (no prompts) |
--debug |
Enable shell trace output |
dx init flags
| Flag | Description |
|---|---|
--skip-vendors |
Skip composer install |
--skip-framework-init |
Skip framework init script |
--skip-framework-config |
Skip framework config generation |
--skip-proxy |
Skip starting the reverse proxy |
--debug |
Enable shell trace output |
Runtime
| Command | Description |
|---|---|
dx up |
Start the Docker stack |
dx down |
Stop the Docker stack |
dx logs |
Tail container logs |
dx shell / dx bash |
Open an interactive shell inside the app container |
dx exec <cmd> [args] |
Run a command inside the app container |
dx list / dx ls |
List stack containers |
dx test [args] |
Run PHPUnit tests inside the container |
dx up flags
| Flag | Description |
|---|---|
--sync-hosts |
Sync domain entries to /etc/hosts before starting |
--skip-proxy |
Do not ensure the reverse proxy is running |
--recreate |
Force container recreation |
--build |
Rebuild the image before starting |
--foreground |
Run in foreground (don't detach) |
--debug |
Enable shell trace output |
dx down flags
| Flag | Description |
|---|---|
--volumes |
Also remove Docker volumes |
--orphans |
Remove orphan containers |
--debug |
Enable shell trace output |
Framework console
| Command | Description |
|---|---|
dx console <cmd> [args] |
Run a framework console command |
dx yii <cmd> |
Alias for Yii2 (php yii <cmd>) |
dx artisan <cmd> |
Alias for Laravel (php artisan <cmd>) |
Migration shortcuts
These are resolved by the active framework driver.
Yii2
| Command | Description |
|---|---|
dx migrate |
Run all pending migrations |
dx migrate-create <name> |
Generate a new timestamped migration file in console/migrations/ |
dx migrate-down [n] |
Revert n migrations (default: 1) |
dx migrate-new |
Show pending migrations |
dx migrate-history |
Show migration history |
Laravel
| Command | Description |
|---|---|
dx migrate |
Run all pending migrations |
dx migrate-create <name> |
Create a migration via artisan make:migration |
dx migrate-rollback [--step=N] |
Revert migrations |
dx migrate-status |
Show migration status |
dx migrate-fresh |
Drop all tables and re-run all migrations |
Apache
| Command | Description |
|---|---|
dx apache validate |
Validate vhost configuration |
dx apache reload |
Graceful reload (picks up config changes without downtime) |
dx apache restart |
Full restart |
dx apache vhosts |
List all loaded virtual hosts |
dx apache modules |
List all loaded Apache modules |
dx apache version |
Show Apache version |
dx apache logs [error|access] |
Tail error or access logs |
Proxy (Traefik)
| Command | Description |
|---|---|
dx proxy start |
Start the Traefik reverse proxy |
dx proxy stop |
Stop the proxy |
dx proxy restart |
Restart the proxy |
dx proxy status |
Show proxy status |
dx proxy logs |
Tail proxy logs |
Network & hosts
| Command | Description |
|---|---|
dx network status |
Show resolved port assignments |
dx network resolve |
Re-run port resolution and show changes |
dx network hosts |
Alias for the hosts command |
dx hosts sync |
Write project domain entries to /etc/hosts (requires root/sudo) |
dx hosts remove |
Remove project entries from /etc/hosts |
dx hosts list |
Show current /etc/hosts entries for this project |
dx hosts preview |
Preview entries that would be written |
Workspace
| Command | Description |
|---|---|
dx workspace / dx ws |
Drop into a subshell where all dx commands and framework driver commands are available without the dx prefix |
Global flags
These flags are accepted by all commands:
| Flag | Description |
|---|---|
--framework=NAME |
Override auto-detected framework |
--debug |
Enable shell trace output (set -x) |
Environments
Three built-in environments:
| Name | Use |
|---|---|
dev |
Development (default) |
qly |
Quality |
prd |
Production |
Environment variables are layered in order:
dxkit/env/globals.env— shared defaults, source-controlled.project/artifacts/env/${ENVIRONMENT}.env— local overrides, gitignored.project/artifacts/env/${ENVIRONMENT}.resolved.env— generated resolved values, gitignored
Resolved port assignments are written to .project/artifacts/ports and loaded back on subsequent runs.
Port values in env files may use the auto:PORT syntax — dxkit will find the next available port starting from that number.
Framework support
Framework detection reads composer.json at project root.
| Framework | Detected by | Console binary | dx console alias |
|---|---|---|---|
| Yii2 Advanced | yiisoft/yii2 + advanced template structure |
yii |
dx yii |
| Yii2 Basic | yiisoft/yii2 + basic template structure |
yii |
dx yii |
| Laravel | laravel/framework |
artisan |
dx artisan |
Use --framework=NAME to override detection (e.g. --framework=yii2-advanced).
Architecture
For contributors and maintainers.
dx # project-level entrypoint; defines aliases, calls dx::dispatch()
dxkit/
├── bootstrap.sh # loads core.sh, exports PROJECT_ROOT, defines dx::load_modules()
├── core.sh # sources all core subsystems in order
├── core/ # low-level infrastructure
│ ├── platform.sh # OS detection, privilege elevation
│ ├── context.sh # execution context management
│ ├── utils.sh # general utilities
│ ├── string.sh # string helpers
│ ├── hook.sh # pre/post hook system
│ ├── module.sh # module loader
│ ├── command.sh # command registration framework
│ ├── loader.sh # dynamic file loader
│ ├── flag.sh # flag/argument parsing
│ └── runtime/runtime.sh # runtime abstraction entry
├── commands/ # one file per command, loaded dynamically by the dispatcher
│ ├── build.command.sh
│ ├── init.command.sh
│ ├── setup.command.sh
│ ├── console.command.sh
│ ├── apache.command.sh
│ ├── hosts.command.sh
│ ├── network.command.sh
│ ├── proxy.command.sh
│ ├── workspace.command.sh
│ ├── docker/ # low-level docker subcommands
│ └── runtime/ # runtime-abstracted subcommands (used by default)
├── modules/ # reusable function libraries sourced at startup
│ ├── app.module.sh # framework abstraction layer (scaffold, init, config, console)
│ ├── docker.module.sh # Docker and Docker Compose wrappers
│ ├── env.module.sh # environment variable loading and derivation
│ ├── log.module.sh # structured logging with icons and context prefixes
│ ├── fs.module.sh # cross-platform file write and sed utilities
│ ├── network.module.sh # port resolution and persistence
│ ├── apache.module.sh # Apache management functions
│ ├── proxy.module.sh # proxy abstraction (delegates to docker/proxy.module.sh)
│ ├── artifact.module.sh # runtime artifact directory management
│ ├── composer.module.sh # composer operations (install, update, require, auth)
│ ├── template.module.sh # envsubst-based template rendering
│ ├── yii.module.sh # Yii2 shared utilities (exec, env name mapping)
│ ├── phpstorm.module.sh # PhpStorm datasource config generation
│ ├── docker/
│ │ ├── db.module.sh # database port/path/env helpers (MySQL + MSSQL)
│ │ └── proxy.module.sh # Traefik container lifecycle and label generation
│ └── framework/
│ ├── yii2-advanced.module.sh
│ ├── yii2-basic.module.sh
│ └── laravel.module.sh
├── drivers/ # framework-specific command registration
│ ├── dispatcher.sh # resolves framework → driver, populates DRIVER_COMMANDS
│ ├── yii2/
│ │ ├── driver.sh # registers yii, migrate-* commands
│ │ └── migrate.sh # migration file generation helpers
│ └── laravel/
│ ├── driver.sh # registers artisan, migrate-* commands
│ └── migrate.sh # artisan make:migration wrappers
├── runtime/ # runtime abstraction (Docker vs. native execution)
│ ├── runtime.sh # selects active runtime
│ ├── docker.runtime.sh # implements runtime::exec via docker compose exec
│ └── native.runtime.sh # implements runtime::exec directly on host
├── templates/ # envsubst-rendered config templates
│ ├── docker/
│ │ ├── Dockerfile.template
│ │ └── docker-compose.yml.template
│ ├── apache/
│ │ ├── yii2-advanced/vhosts.conf.template
│ │ └── yii2-basic/vhosts.conf.template
│ ├── yii2-advanced/
│ │ ├── main-local.php.template
│ │ └── components/ # db.mysql, db.mssql, log php templates
│ └── yii2-basic/
│ ├── db.mysql.php.template
│ └── db.mssql.php.template
├── env/ # layered environment variable files
│ ├── globals.env
│ ├── dev.env
│ ├── qly.env
│ └── prd.env
└── docker/
└── entrypoint.sh # container entrypoint script
How command dispatch works
dx <command> [args]callsdx::dispatch()- Aliases in
dxare resolved first (e.g.sh→runtime/shell,ls→runtime/list) - Built-ins (
help,elevate) are handled inline - Driver commands registered in
DRIVER_COMMANDS(viadxkit/drivers/dispatcher.sh) are checked next - Remaining commands are matched to files in
dxkit/commands/and loaded dynamically
Adding a new command
- Create
dxkit/commands/<name>.command.shwith a functioncommand::<name>() - Optionally register an alias in
dxunder the alias map - For framework-specific commands, register the command name in the driver file (
dxkit/drivers/<framework>/driver.sh)