Environment configuration for CI/CD.

Sync .env files with GitHub Actions, GitLab CI/CD, HashiCorp Vault and Jenkins credentials. Review a plan before anything changes. Secret values are never printed.

curl -sSfL https://raw.githubusercontent.com/bakhod1r/env4ci/main/install.sh | sh

No Go needed. Also: brew install bakhod1r/tap/env4ci · scoop install env4ci · uses: bakhod1r/env4ci@v1 · go install

Safe by default

Built for people who've pasted a secret into the wrong field before.

Plan, then apply

diff shows every change as new, changed, unverifiable or remote only. push asks before it writes.

Values never printed

Plans and logs show keys and kinds only. GitHub secrets are encrypted on your machine with a libsodium sealed box.

Unknown means secret

Glob rules decide secret or variable. Keys that match no rule become secrets, so a value is never exposed by accident.

No surprise deletes

Keys that exist only on the remote are left alone unless you pass --prune.

Tokens stay out of files

Tokens come from GITHUB_TOKEN and GITLAB_TOKEN. The config file rejects unknown fields.

Credentials tested first

SSH keys log in to their server and registry tokens log in to ghcr.io or Docker Hub before anything is stored. If a check fails, nothing is written.

Branch-aware

Reads the repo from git remote and maps the current branch to its environment. A branch with no mapping is refused.

Pull without leaks

pull writes mode 0600, never overwrites a file, and adds it to .gitignore.

Shared, dev, production

Put shared values at repository level and per-environment values in each environment. The environment value wins when both have the same key.

shared
env4ci push github \
  -f .env.shared

GitHub  repo secrets/vars
GitLab  scope "*"
dev
env4ci push github \
  -f .env.dev -e dev

GitHub  environment "dev"
GitLab  scope "dev"
production
env4ci push github \
  -f .env.prod -e production

GitHub  environment "production"
GitLab  scope "production"

One small file

Run env4ci init to create it. Rules are checked top to bottom and the first match wins.

# env4ci.yaml
source: .env.production
default: secret
rules:
  - { pattern: "*SECRET*", type: secret }
  - { pattern: "*TOKEN*",  type: secret }
  - { pattern: "APP_*",    type: variable }
  - { pattern: "LOG_*",    type: variable }
targets:
  github: { repo: owner/name, environment: production }
  gitlab: { project: group/project, protected: true }

Commands

Provider commands take github, gitlab, vault or jenkins; default comes from env4ci.yaml or git remote.

initCreate env4ci.yaml (wizard on a terminal)
genAuth file + one gitignored env file per environment
scanList variables the CI files use
verifyLog in with SSH keys and registry tokens
diff <p>Plan only. Never writes anything.
push <p>Verify, confirm, apply the plan
pull <p>Write readable remote values to a .env file
check <p>Exit 2 if CI uses keys the provider lacks
rotate KEYNew value or --generate, verify, back up, push one key
leaksExit 2 if tracked files contain secret values
hookPre-commit hook running leaks --staged
makefileAdd make env-* targets
updateReplace the binary with the latest release
completionTab completion for bash, zsh, fish
help [cmd]One command's usage and flags; also man env4ci
+ new~ changed? unverifiable (write-only secret)- remote only