2026-07-19 15:31:42 +00:00
**NOTICE**: This repository has been moved to [https://code.adriano.fyi/me/ess ](https://code.adriano.fyi/me/ess ). Microsoft has shown little interest in stewarding what was once the best and largest open source community. This small act of migration is my way showing that we don't all support Microsoft's disinterest.
2023-09-26 13:51:15 +00:00
# ess (env sample sync)
2022-11-26 16:05:23 +00:00
2023-06-08 13:56:58 +00:00
[](https://app.gitter.im/#/room/#env-sample-sync-dev:gitter.im)
2024-10-25 20:03:42 +00:00
Automatically keep `env.sample` files in sync with `.env`
2022-11-26 16:05:23 +00:00
2023-05-29 16:54:11 +00:00
---
2022-11-26 16:05:23 +00:00
2025-04-11 00:28:54 +00:00
`ess` transforms environment files containing secrets (e.g. `.env` , `.envrc` ) into sample environment files (e.g.
2024-01-20 00:23:56 +00:00
`env.sample` ) that may be safely checked into git.
2022-11-26 16:05:23 +00:00
2024-01-20 00:23:56 +00:00
`ess` may be run manually by running the cli executable, or automatically by installing the pre-commit hook with `ess install`
2025-04-11 00:28:54 +00:00
in any git repository. Installing `ess` as a git hook ensures that project environment files are automatically and safely
revision controlled when they change.
2022-11-26 16:05:23 +00:00
2024-01-20 00:23:56 +00:00
Doing so allows environment configurations to be shared across teams without leaking secrets.
2025-04-11 00:28:54 +00:00
## How it works
2024-01-20 00:23:56 +00:00
By default, `ess` checks the local directory for environment files named `.env` . The env file name is controlled by
2025-04-11 00:28:54 +00:00
the `--env-file` switch. Next, the environment file is parsed for environment variables. Environment variables
2024-01-20 00:23:56 +00:00
may be of the following forms:
```
# Standard environment variables
FOO=bar baz
FOO="bar baz"
FOO='bar baz'
# Envrc environment variable
export FOO=bar baz
export FOO="bar baz"
export FOO='bar baz'
```
By default, variable values are replaced with innert values named after the variable, e.g. `FOO=bar` is replaced by `FOO=<FOO>` .
2025-04-11 00:28:54 +00:00
Example values may be provided with the `--example` switch, e.g. `--exmaple=FOO="enter your foo here"` will set `FOO` 's
value as follows `FOO="enter your foo here"` in the sample file.
2024-01-20 00:23:56 +00:00
2025-04-11 00:28:54 +00:00
Finally, when all variables are replaced, the sample file is written with the sanitized variable values, along with all
2024-01-20 00:23:56 +00:00
non-variable strings from the file. By default the sample file is named `env.sample` , which is controlled by the `--env-sample`
2025-04-11 00:28:54 +00:00
switch.
2024-01-20 00:23:56 +00:00
2025-04-11 00:28:54 +00:00
Because `ess` permits non-variable strings in environment files, it means that both comments and script code (in the case
of `.envrc` files) is included in environment sample files. This allows environment files to not only be checked into git, but
documented with comments.
2022-11-26 16:05:23 +00:00
2023-05-29 16:54:11 +00:00
# Installation & Usage
2023-09-26 13:51:15 +00:00
`ess` can be run in three ways:
2023-05-29 16:54:11 +00:00
1. Manually
2. As a native git-hook
3. As a [pre-commit plugin ](https://pre-commit.com/#install ) (a utility for organizing pre-commit hooks)
## Installation
2023-09-26 13:51:15 +00:00
Installation is required to run `ess` manually, or as a native git hook. See [pre-commit configuration]
2023-09-09 07:49:30 +00:00
(#running-as-a-pre-commit-plugin) for pre-commit usage.
2023-05-29 16:54:11 +00:00
**Install from the releases page**
2023-09-26 13:51:15 +00:00
Download [the latest release ](https://github.com/acaloiaro/ess/releases/latest ) and add it to your `$PATH` .
2023-05-29 16:54:11 +00:00
**Install with `go install` **
2022-11-26 16:05:23 +00:00
```bash
2023-09-26 13:51:15 +00:00
go install github.com/acaloiaro/ess@latest
2023-05-29 16:54:11 +00:00
```
2022-11-26 16:05:23 +00:00
2023-09-09 07:49:30 +00:00
**Nix Flake**
This application may be added as a flake input
**flake.nix**
```nix
2023-09-26 13:51:15 +00:00
inputs.ess = {
url = "github:acaloiaro/ess";
2023-09-09 07:49:30 +00:00
inputs.nixpkgs.follows = "nixpkgs";
};
```
**configuration.nix**
```nix
users.users.< USERNAME > .packages = [
...
2023-09-26 13:51:15 +00:00
inputs.ess.packages.${system}.default
2023-09-09 07:49:30 +00:00
];
```
2024-10-10 17:51:28 +00:00
Or simply run directly
2023-09-09 07:49:30 +00:00
```bash
2023-09-26 13:55:04 +00:00
nix run github:acaloiaro/ess
2023-09-09 07:49:30 +00:00
```
2023-05-29 16:54:11 +00:00
## Running manually
2023-09-26 13:51:15 +00:00
`ess` can be run with no arguments to use defaults.
2023-05-29 16:54:11 +00:00
**Sync `.env` with `env.sample` **
```bash
2023-09-26 13:51:15 +00:00
ess
2022-11-26 16:05:23 +00:00
```
2023-05-29 16:54:11 +00:00
**With a non-default `.env` and `env.sample` location**
2022-11-26 16:05:23 +00:00
```bash
2023-09-26 13:51:15 +00:00
ess --env-file=.env-file-name --sample-file=env-sample-file-name
2023-05-29 16:54:11 +00:00
```
2022-11-26 16:05:23 +00:00
2023-05-29 16:54:11 +00:00
**Provide example values for variables**
2023-09-26 13:51:15 +00:00
By default, `ess` uses the name of environment variables in `<brackets>` as example values in `env.sample` ,
2023-09-09 07:49:30 +00:00
e.g. `FOO=secret value` is replaced with `FOO=<FOO>` . This behavior is customizable wit the `--example` flag.
2023-05-29 16:54:11 +00:00
Add custom examples for variables `FOO` and `BAR` .
```bash
2023-09-26 13:51:15 +00:00
ess --example=FOO="must be a valid UUID" --example=BAR="bars must be a positive integer"
2023-05-29 16:54:11 +00:00
```
The above invocation yields the following `env.sample`
```bash
FOO=must be a valid UUID
BAR=bars must be a positive integer
```
## Running as a native git-hook
2023-09-26 13:51:15 +00:00
To add `ess` as a pre-commit git hook in a git repository, run:
2023-05-29 16:54:11 +00:00
```bash
2023-09-26 13:51:15 +00:00
ess install
2022-11-26 16:05:23 +00:00
```
2023-09-26 13:51:15 +00:00
This installs `ess` as a pre-commit git hook with default arguments.
2023-05-29 16:54:11 +00:00
The `install` command supports all [command flags ](#command-flags ).
2023-09-26 13:51:15 +00:00
If you need to change `ess` flags, simply run `ess install` again with the desired flags and
2023-09-09 07:49:30 +00:00
choose the overwrite [o] option when prompted what to do with the existing pre-commit hook.
2022-11-26 16:05:23 +00:00
2023-05-29 16:54:11 +00:00
## Running as a pre-commit plugin
2022-11-26 16:05:23 +00:00
2023-05-29 16:54:11 +00:00
This utility can be used as a [pre-commit plugin ](https://pre-commit.com/#install )
2022-11-26 16:05:23 +00:00
## Add configuration
```bash
2025-04-11 00:29:04 +00:00
cat < < EOF > .pre-commit-config.yaml
2022-11-26 16:05:23 +00:00
repos:
2023-09-26 13:51:15 +00:00
- repo: https://github.com/acaloiaro/ess.git
2026-07-19 15:32:37 +00:00
rev: v2.18.3
2022-11-26 16:05:23 +00:00
hooks:
2023-09-26 13:51:15 +00:00
- id: ess
2022-11-26 16:05:23 +00:00
EOF
pre-commit install
2023-05-29 16:54:11 +00:00
git add .pre-commit-config.yaml
```
See [pre-commit configuration examples ](#pre-commit-configuration-examples ) for additional pre-commit documentation.
# Background
2023-09-09 07:49:30 +00:00
It's important to document the environment variables required to run applications, both in production and development. A
great way to do so is with `env.sample` files, but sample files tend to get out of date very quickly.
2023-05-29 16:54:11 +00:00
2024-10-10 17:51:28 +00:00
For example, let's say you're adding a new feature to your application, and it requires the variable `FOO` to be set.
2023-09-09 07:49:30 +00:00
While you're developing locally, you likely have a `.env` file that looks something like:
2023-05-29 16:54:11 +00:00
```bash
APPLICATION_SECRET=supersekrit
# I got this FOO from the detailed process documented at: http:://wiki.example.com/how_to_get_a_foo
FOO="My super secret value for foo"
```
2023-09-09 07:49:30 +00:00
Working on large teams, it's common to share these `.env` files somewhere secure where all developers have access to
them. Retrieval is often integrated into application startup and/or bootstrap processes.
2023-05-29 16:54:11 +00:00
2023-09-09 07:49:30 +00:00
But working on open source projects or teams with less trust and less shared infrastructure, it's more common to share
2023-09-26 13:51:15 +00:00
an `env.sample` . `ess` automatically keeps the sample file in sync with `.env` , so you don't have to. Your
2023-09-09 07:49:30 +00:00
`.env` file stays the same, and is automatically converted to the following `env.sample` :
2023-05-29 16:54:11 +00:00
```bash
APPLICATION_SECRET=< APPLICATION_SECRET >
# I got this FOO from the detailed process documented at: http:://wiki.example.com/how_to_get_a_foo
FOO=< FOO >
2022-11-26 16:05:23 +00:00
```
2023-05-29 16:54:11 +00:00
It's even possible to provide default/example values for every environment variables with the `--example` [flag ](#command-flags ).
2022-11-26 16:05:23 +00:00
2023-05-29 16:54:11 +00:00
## Command Flags
2022-11-26 16:05:23 +00:00
2023-09-09 07:49:30 +00:00
| Name | Description | Example | Default |
| --------------- | --------------------------------------------------- | --------------------------------------------------------- | ----------------------------- |
2023-05-30 02:07:35 +00:00
| `--env-file` | The name of the environment file | `--env-file=.secrets` | `--env-file=.env` |
2024-10-25 20:18:58 +00:00
| `--debug` | Enable debugging | `--debug` | `false` |
| `--skip-git-add` | Skip performing `git add` after syncing | `--skip-git-add` | `false` |
2023-05-30 02:07:35 +00:00
| `--sample-file` | The name of the sample environment file | `--sample-file=secrets.example` | `--sample-file=env.sample` |
2024-10-25 20:18:58 +00:00
| `--example` | Provide examples for specific environment variables | `--example=FOO="Example FOO" --example=BAR="Example BAR"` | `--example=VAR=<VAR>` |
2022-11-26 16:05:23 +00:00
2023-05-29 16:54:11 +00:00
## Pre-commit Configuration Examples
2022-11-26 16:05:23 +00:00
### Default configuration
```yml
repos:
2023-09-26 13:51:15 +00:00
- repo: https://github.com/acaloiaro/ess.git
2026-07-19 15:32:37 +00:00
rev: v2.18.3
2022-11-26 16:05:23 +00:00
hooks:
2023-09-26 13:51:15 +00:00
- id: ess
2022-11-26 16:05:23 +00:00
```
### Customize `.env` and `env.sample` paths
```yml
repos:
2023-09-26 13:51:15 +00:00
- repo: https://github.com/acaloiaro/ess.git
2026-07-19 15:32:37 +00:00
rev: v2.18.3
2022-11-26 16:05:23 +00:00
hooks:
2023-09-26 13:51:15 +00:00
- id: ess
2022-11-26 16:05:23 +00:00
args: ['--env-file=.env_file', '--sample-file=env_file.sample']
```
### Customize variable example values
2024-10-10 17:51:28 +00:00
Sometimes environment variables need to conform to specific formats, and it's necessary to provide better documentation.
2023-09-09 07:49:30 +00:00
For this reason, environment variable examples may be provided in lieu of the default behavior, which is to use the
environment variable name surrounded by `<brackets like this>` in sample files.
2022-11-26 16:05:23 +00:00
```yml
repos:
2023-09-26 13:51:15 +00:00
- repo: https://github.com/acaloiaro/ess.git
2026-07-19 15:32:37 +00:00
rev: v2.18.3
2022-11-26 16:05:23 +00:00
hooks:
2023-09-26 13:51:15 +00:00
- id: ess
2022-11-26 16:05:23 +00:00
args: [--example=FOO="Provide your foo here", --example=BAR="You can fetch bars from https://example.com/bars"]
```
2024-01-20 00:23:56 +00:00
Example environment file
2022-11-26 16:05:23 +00:00
`.env`
```
FOO=the_value_of_my_secret_foo
BAR=the_value_of_my_secret_bar
```
Example sample file output
`env.sample`
```bash
FOO=Provide your foo here
BAR=You can fetch bars from https://example.com/bars
2026-07-19 15:31:42 +00:00
```