The cfg command
cfg sets up and maintains a project’s configuration: the .env file, the
WINTER_KEY secret, the Docker scaffolding and shell completion. It is the first
thing that runs when a project is created, and the thing you come back to when
setting an environment up.
What cfg is and why
cfg is the project-configuration command.
The problem. A new project has to be brought into working shape: create the
.env, generate a secret key and, if you want them, the Docker files and shell
completion. Doing that by hand makes a forgotten step easy.
The solution. cfg gathers those operations into subcommands, and cfg init
performs the basic setup in one go. That is what this page is about.
Subcommands
| Subcommand | Purpose |
|---|---|
init |
Patches composer.json, creates .env, generates the key, drops in the stub meta |
key |
Manages WINTER_KEY |
env |
Manages the .env file |
docker |
Generates the Docker files |
completion |
Installs or prints the shell completion |
cfg init
Brings the project into working shape (called automatically on
composer create-project):
php call cfg initThe sequence: patch composer.json (rewrite name and description, clear
authors/keywords) → create .env → generate WINTER_KEY.
cfg key — the secret key
| Flag | Action |
|---|---|
key -g |
Generate or regenerate the key (64 hex = 32 bytes) and write it into .env |
key -s |
Show the current key |
php call cfg key -g # a new WINTER_KEYIt needs a .env
key -g warns and stops when .env is missing — create it first (cfg env -i).
cfg env — the environment file
| Flag | Action |
|---|---|
env -i |
Create .env from the template (skipped when it exists) |
env -s |
Print the loaded $_ENV |
env -s --file |
Print the raw contents of .env |
cfg docker — the Docker scaffolding
php call cfg dockerCreates a Dockerfile, a docker-compose.yml, a .dockerignore and a docker/
directory with a startup script and PHP settings. The command has no options — there
is one image, for Swoole, and the mode is picked with a variable at startup:
| Startup | Mode |
|---|---|
docker compose up |
Production: opcache on, no watcher |
DEV=true docker compose up |
Development: restart on file change, opcache off |
PHP extensions and database drivers
These are installed by separate scripts in docker/dependencies/, not by editing the
Dockerfile. The build runs them in numeric-prefix order; four ship with the template:
| Script | Installs |
|---|---|
10-bcmath.sh |
bcmath — exact arithmetic (money, Number) |
20-pgsql.sh |
pdo_pgsql + pgsql — PostgreSQL |
30-mysql.sh |
pdo_mysql — MySQL / MariaDB |
40-redis.sh |
phpredis — the Redis client |
Delete the ones you do not need: what is not in the directory does not end up in the image.
Every script is self-contained — it installs whatever the build needs and removes it again. So it can be copied into another project or run by hand, and your own is written to the same pattern:
#!/bin/sh
set -e
# intl — date and number formatting, locale-aware collation.
if php -m | grep -qi '^intl$'; then
echo "intl already present — skip"
else
apk add --no-cache icu-libs \
&& apk add --no-cache --virtual .intl-deps $PHPIZE_DEPS icu-dev \
&& docker-php-ext-install -j"$(nproc)" intl \
&& apk del .intl-deps
fiThree things there matter:
- The
php -mcheck — the extension may already be in the base image, in which case the script does nothing and costs no build time. --virtual— the compiler and the headers are installed under one name,.intl-deps, and removed in a single command, so they never reach the final image. Only the runtime library stays (icu-libs), without which the extension will not load.$PHPIZE_DEPS— the extension-building toolchain the PHP base image defines (compiler,make,autoconf,re2c). No need to list the packages by hand.
A failing script stops the build
An error in any of the scripts fails the image build — deliberately. Otherwise you would get a green image with the extension missing and find out on the first query to the database, in production.
cfg completion — shell completion
| Flag | Action |
|---|---|
| (no flag) | Print the script to stdout |
-i |
Install it |
-if |
Install it, overwriting |
php call cfg completion -iThe shell is detected from $SHELL: zsh → ~/.zsh/completions/_call (an fpath line
is added to ~/.zshrc), otherwise bash → ~/.bash_completion.d/call.
Next
- Installation — where
cfg initsits in the startup chain - Configuration —
.envand configuration classes - Console — overview — every command