
Run any command with profile-based environment variables loaded from config outside your repo.
profy <profile> <command>
| Need |
profy behavior |
| Keep secrets out of git |
Reads env files from an external config home |
| Switch environments |
Uses profiles such as dev, sit, and prod |
| Merge env files |
Loads files in order; later files override earlier files |
| Fail early |
Checks required_keys before starting the command |
| Develop with reloads |
--watch-env restarts the command when env/config files change |
| Protect config-home path |
Stores it sealed; profy config hides it by default |
| Method |
Command |
| Go install |
go install github.com/dreamph/profy@latest |
| Local build |
git clone https://github.com/dreamph/profy.git && cd profy && go build -o profy . |
| Step |
Command or file |
Result |
| 1 |
profy setup --config-home /secure/profy-config |
Stores profySecret in macOS Keychain or Windows Credential Manager |
| 2 |
profy init |
Prompts for project_id and creates .profy.yml |
| 3 |
/secure/profy-config/<project_id>/profy.json |
Defines profiles and env files outside the repo |
| 4 |
profy verify |
Checks project file, setup, profile config, and env file paths |
| 5 |
profy dev go run ./cmd/app |
Runs the command with the dev profile |
profy init writes only the project reference:
Minimal external config:
/secure/profy-config/
myapp/
profy.json
base.env
dev.env
secret/
dev.env
Minimal profy.json:
{
"configs": {
"dev": {
"files": ["base.env", "dev.env", "secret/dev.env"],
"required_keys": ["APP_ENV"]
}
}
}
| Command |
Purpose |
Notes |
profy init |
Create .profy.yml |
Prompts for project_id; use --file only for a custom path |
profy setup --config-home PATH |
Seal config-home and store profySecret |
Use --force to replace existing setup |
profy verify |
Check local setup |
Does not print config-home |
profy config |
Print setup/project metadata |
Hides config-home |
profy config --show-config-home |
Print config-home |
Prompts for profySecret first |
profy config change-secret |
Rotate profySecret |
Requires current secret and new secret confirmation |
profy export <project_id> |
Export project config |
Prompts for profySecret; writes <project_id>.zip |
profy <profile> <command> |
Run a command with env vars |
Example: profy dev go run ./cmd/app |
profy --print-env <profile> |
Print redacted env output |
Does not run a command |
| Command |
Flag |
Default |
Description |
init |
--file PATH |
.profy.yml |
Project reference file to create |
init |
--force |
false |
Overwrite an existing project reference file |
setup |
--config-home PATH |
$PROFY_CONFIG_HOME or ~/.profy |
External config directory to seal |
setup |
--force |
false |
Replace existing ~/.profy/settings.json |
verify |
--project-file FILE |
.profy.yml |
Project reference file to check |
verify |
--config-home PATH |
resolution order below |
Check a config home without credential setup |
config |
--project-file FILE |
.profy.yml |
Project reference file to read |
config |
--show-config-home |
false |
Ask for profySecret and print config-home |
run |
--project-file FILE |
.profy.yml |
Project reference file to read |
run |
--config-home PATH |
resolution order below |
External config directory |
run |
--override |
false |
Env files override existing OS env vars |
run |
--watch-env |
false |
Restart command when env/config files change |
run |
--watch-interval DURATION |
1s |
Poll interval, for example 500ms |
run |
-v, --verbose |
false |
Print project, profile, and command |
Config-home resolution order:
| Priority |
Source |
| 1 |
--config-home |
| 2 |
PROFY_CONFIG_HOME |
| 3 |
Sealed path in ~/.profy/settings.json, opened with the OS credential store |
| 4 |
~/.profy |
| File |
Location |
Purpose |
.profy.yml |
Project repo |
Stores project_id only |
settings.json |
~/.profy/settings.json |
Stores sealed config-home metadata |
profy.json |
External config home |
Defines profiles |
.env, .yml, .yaml |
External config home |
Env values loaded by profiles |
Project config can be stored in either layout:
| Layout |
When used |
<config-home>/profy.json |
Direct config home |
<config-home>/<project_id>/profy.json |
Project subdirectory layout |
Nested project IDs are supported, for example dir1/myapp.
| Field |
Type |
Description |
files |
[]string |
Env/YAML files to load in order |
required_keys |
[]string |
Keys that must be present and non-empty |
vault |
[]object |
Optional HashiCorp Vault KV sources |
infisical |
[]object |
Optional Infisical sources |
Load order:
| Order |
Source |
| 1 |
Existing OS environment |
| 2 |
Profile files |
| 3 |
Vault sources |
| 4 |
Infisical sources |
| 5 |
Variable expansion |
| 6 |
required_keys validation |
| Format |
Supported values |
.env |
KEY=value, quotes, export, comments, variable expansion |
| YAML |
Top-level scalar values only |
APP_ENV=dev
APP_PORT=8080
DB_DSN=postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}
APP_ENV: dev
APP_PORT: 8080
FEATURE_FLAG: true
EMPTY_VALUE: null
| Task |
Command |
Notes |
| Check setup without leaking paths |
profy verify |
Prints status only |
| Show config-home |
profy config --show-config-home |
Requires profySecret |
| Rotate secret |
profy config change-secret |
Re-seals config-home |
| Export config |
profy export myapp |
Requires profySecret; refuses to overwrite existing zip |
If profySecret is forgotten, profy cannot open the sealed config-home path. If you still know the config-home path, run profy setup --config-home PATH --force to create a new setup.
| Use case |
Command |
| Run dev app |
profy dev go run ./cmd/app |
| Run production binary |
profy prod ./myapp |
Hot reload with air |
profy dev air -c .air.toml |
| Restart when env changes |
profy --watch-env dev go run ./cmd/app |
| Print redacted env |
profy --print-env dev |
| Use a custom config home |
profy --config-home /secure/profy-config dev go run ./cmd/app |
| Verify bundled demo |
go run . verify --config-home examples/external-config --project-file examples/app/.profy.yml |
| Run bundled demo |
go run . --config-home examples/external-config --project-file examples/app/.profy.yml dev go run ./examples/app |
| Code |
Meaning |
0 |
Success |
1 |
Runtime/config/setup error |
2 |
Invalid usage |
MIT