The show and expand commands resolve shell-style variables ($PORT, ${DATABASE_URL}, and so on) inside a process command before printing it. This page explains where the values come from and the order they are tried in.
A line like web: bundle exec puma -p $PORT is what you commit to source control. What actually runs in production is bundle exec puma -p 5000 (or whatever port the platform assigned). When you debug a deploy, what you usually want to see is the expanded form, not the template. That is what show and expand produce.
Expansion uses Go's os.Expand semantics, so anything matching $NAME or ${NAME} is a candidate. Two names are always populated by procfile-util, regardless of any flag:
| Name | Source |
|---|---|
PORT |
The value of --default-port, default 5000. |
PS |
The name of the process type currently being expanded (for example, web). |
Anything else expands to an empty string unless you opt in with --env-file, --allow-getenv, or both.
When a variable is referenced, procfile-util checks sources in this order and stops at the first hit:
--env-file <path>, if provided. The file is parsed withgodotenv, soKEY=valueandexport KEY=valuelines both work.- The current process environment, but only when
--allow-getenvis set. Without that flag, the env is treated as if it were empty. - The built-in defaults above (
PORTfrom--default-port,PSfrom the process name).
If no source supplies a value, the variable expands to an empty string.
Given this Procfile:
web: bundle exec puma -p $PORT --environment $RAILS_ENV
worker: bundle exec sidekiq -e $RAILS_ENV
procfile-util show --process-type web
# bundle exec puma -p 5000 --environmentPORT falls back to the default port. RAILS_ENV is unset and expands to an empty string.
procfile-util show --process-type web --default-port 8080
# bundle exec puma -p 8080 --environmentRAILS_ENV=production procfile-util show --process-type web --allow-getenv
# bundle exec puma -p 5000 --environment productionRAILS_ENV is now read from your shell. --allow-getenv is opt-in because it lets the surrounding shell influence command rendering, which is convenient locally but a hazard in CI where unrelated environment variables may bleed in.
Given a .env file containing:
RAILS_ENV=staging
PORT=4000
procfile-util show --process-type web --env-file .env
# bundle exec puma -p 4000 --environment stagingValues in .env win even over the --default-port fallback because the env file is the highest-priority source.
RAILS_ENV=production procfile-util show \
--process-type web \
--env-file .env.shared \
--allow-getenv \
--default-port 8080Resolution order for each variable: .env.shared first; then the shell environment (because --allow-getenv is set); then the built-in defaults (PORT falls back to 8080 if it is in neither file nor shell).
expand applies the same rules to every entry and prints the full Procfile with substitutions applied:
procfile-util expand --env-file .env.ci
# web: bundle exec puma -p 4000 --environment staging
# worker: bundle exec sidekiq -e stagingThis is the form to use in CI when you want to assert that the rendered Procfile matches an expected snapshot.