Patches .env files automatically on git checkout — keeping local environments in sync with the current branch.
git checkout feat-login
# bight: .env → DB_NAME=myapp_feat-login
# bight: .env → JWT_SECRET=***Only the listed vars are touched. The rest of your .env is left untouched.
With Homebrew:
brew install andrewadev/tap/bightWith Go:
go install github.com/AndrewADev/bight@latestFrom a release binary:
Download the binary for your platform from the releases page:
| Platform | File |
|---|---|
| macOS (Apple Silicon) | bight-darwin-arm64 |
| macOS (Intel) | bight-darwin-amd64 |
| Linux (x86-64) | bight-linux-amd64 |
| Linux (ARM64) | bight-linux-arm64 |
| Windows | bight-windows-amd64.exe |
Then make it executable and put it on your PATH:
chmod +x bight-darwin-arm64
mv bight-darwin-arm64 /usr/local/bin/bightEach release includes a checksums.txt for verification:
sha256sum -c checksums.txt --ignore-missingRun once per repo, after cloning:
bight installThis writes the git hook and walks you through creating a .bight.yml config:
bight: hook installed
bight: no config file found. Create .bight.yml? [Y/n]
Project name [myapp]:
Env file path [.env]:
Add env vars to track? [Y/n]
(blank name to finish)
Var name: DB_NAME
Strategy:
1) template - interpolate branch/project name (default)
2) random - fresh random value on each checkout
Choice [1]: 1
Var name:
bight: created .bight.yml
bight doctorbight doctor:
[ok] git repo detected
[ok] config: .bight.yml loaded
[ok] config: project = "myapp", 1 env file(s)
[ok] hook: installed
[ok] env file: .env
[ok] vars: all strategies valid
[ok] vars: all triggers valid
bight run --dry-run
# bight (dry-run): .env → DB_NAME=myapp_mainNo files are touched. When you're happy with what you see, you're done — the hook fires on every checkout from here on.
git checkout -b feat-login
# bight: .env → DB_NAME=myapp_feat-loginbight install generates a starter config, but you can hand-edit .bight.yml at any time:
project: myapp
defaults:
branch_template: "{{.Project}}_{{.Branch}}" # used by the template strategy
env_files:
- path: .env
backup: true # write .env.bak before patching (optional, default false)
vars:
- name: DB_NAME
strategy: template # renders to e.g. myapp_feat-login
on: checkout
- name: JWT_SECRET
strategy: random # fresh 64-char hex string on every branch switch
on: checkout
sensitive: true # mask value in console outputIf your config isn't named .bight.yml or lives at a non-standard path, use --config:
bight run --config path/to/custom.bight.yml
bight doctor --config path/to/custom.bight.yml--config is a global flag — it works with any subcommand that reads config.
To apply env patching for the current branch without switching:
bight runTip: to test how another branch would be patched, suppress the hook when switching so bight doesn't fire automatically, then use --dry-run:
git -c core.hooksPath=/dev/null checkout other-branch
bight run --dry-run| Strategy | Output | Typical use |
|---|---|---|
template |
Rendered from {{.Project}} / {{.Branch}} |
DB_NAME |
random |
Fresh 32-byte hex string | JWT_SECRET, tokens |
deterministic |
Stable 64-char hex derived from project + branch | DB_NAME (same value across machines) |
Mark a var sensitive: true to prevent its value from appearing in console output. The value is still written to the .env file normally — only the terminal display is affected.
- name: JWT_SECRET
strategy: random
on: checkout
sensitive: trueOutput with sensitive: true:
bight: .env → JWT_SECRET=***
Set backup: true on an env file entry to write a copy of the file to {path}.bak before each patch is applied. Useful for inspecting what changed or recovering a previous value.
env_files:
- path: .env
backup: true
vars:
- name: DB_NAME
strategy: template
on: checkoutThe backup is a verbatim copy of the file as it was immediately before patching. It is overwritten on each checkout — only the most recent pre-patch state is kept.
Full comment preservation is not supported, as the package we use, godotenv, strips comments on rewrite. As a partial workaround, defaults.collect-comments re-appends comments collected before the patch was applied:
Note: This is a best-effort feature. Comments are collected from the file before patching and re-appended at the end afterwards — their original positions are not restored, and inline comments (
KEY=val # note) are lost entirely.
| Value | Behavior |
|---|---|
all |
Re-appends every full-line comment |
blocks-only |
Re-appends only contiguous comment blocks (≥ 2 lines) — skips isolated # notes |
unset / none |
Comments are not preserved (default) |
defaults:
collect-comments: blocks-onlyComments are always written after the key=value pairs.
| Value | When |
|---|---|
checkout |
Every branch switch |
Settings in ~/.bight.yml apply across all repos and are overridden field-by-field by the repo's .bight.yml. Only defaults fields are supported globally — env_files and vars must be defined in the repo config. If a repo has no .bight.yml, bight does nothing — the global config alone is not enough to trigger patching.
defaults:
branch_template: "{{.Project}}_{{.Branch}}"
collect-comments: blocks-onlySee DEVELOPING.md