Introduction
Dev, staging, and prod settings have a way of sprawling — the same host, port, and database name copy-pasted across a dozen scripts, drifting apart until a deploy points at the wrong database. This post keeps every environment in one config.yaml and selects it at runtime with --config, so a single command behaves correctly everywhere with no duplication.
Install the package
aux4 aux4 pkger install aux4/config
Step 1: one file, one section per environment
Everything lives under a top-level config: key, with a named section per environment. Create config.yaml:
config:
dev:
host: localhost
port: 3000
database: app_dev
staging:
host: staging.internal
port: 3000
database: app_staging
prod:
host: db.example.com
port: 5432
database: app_prod
Step 2: read values
aux4 config get reads a whole section as JSON, or a single value by path (nested paths use /):
aux4 config get --file config.yaml dev
{ "host": "localhost", "port": 3000, "database": "app_dev" }
aux4 config get --file config.yaml prod/port
5432
aux4 config set --file config.yaml --name staging/host --value staging.example.com writes a value back (creating nested paths as needed).
Step 3: the payoff — one command, every environment
Here's where it pays off. When a command runs with --configFile and --config, aux4 loads that section and auto-fills any command variable whose name matches a key — no glue code. Create .aux4:
{
"profiles": [
{
"name": "main",
"commands": [
{
"name": "connect",
"execute": [
"log:connecting to ${database} at ${host}:${port}"
],
"help": {
"text": "Connect to a database server",
"variables": [
{
"name": "host",
"text": "The server host"
},
{
"name": "port",
"text": "The server port"
},
{
"name": "database",
"text": "The database name"
}
]
}
}
]
}
]
}
The command declares host, port, and database but sets none of them. --config picks the section that fills them:
aux4 connect --configFile config.yaml --config dev
connecting to app_dev at localhost:3000
aux4 connect --configFile config.yaml --config prod
connecting to app_prod at db.example.com:5432
Same command, same variables — the environment is the only thing that changes. There's no if dev … elif prod anywhere; --config prod simply hands the command prod's values.
Step 4: shared defaults, defined once
Settings common to every environment shouldn't be repeated three times. Put them in a defaults.json:
{ "sslmode": "require", "poolSize": 10 }
Then merge them into each section (config merge reads JSON on stdin; --save writes the result back):
cat defaults.json | aux4 config merge --file config.yaml --name dev --save
cat defaults.json | aux4 config merge --file config.yaml --name staging --save
cat defaults.json | aux4 config merge --file config.yaml --name prod --save
Add ${sslmode} and ${poolSize} (with matching variables) to the connect command, and every environment now carries the shared defaults on top of its own values:
aux4 connect --configFile config.yaml --config prod
connecting to app_prod at db.example.com:5432 (sslmode=require, pool=10)
Change a default once and re-merge — every environment stays in sync.
Conclusion
aux4/config collapses your environment sprawl into one file: sections for dev, staging, and prod, selected with --config, feeding a command's variables automatically. No copy-paste, no environment branching, and no more deploys pointed at the wrong database — just one config, everywhere.