@jondotsoy/envs 0.1.7 → 0.1.9-demo.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  CLI that keeps the `.env` values of every git worktree in a single file (`.envs/values.yml`). Edit all values together and distribute them to each worktree, or collect them from the existing `.env` files.
4
4
 
5
- Requires [Bun](https://bun.com) and git.
5
+ Requires [Bun](https://bun.com) and git. See [docs/features.md](docs/features.md) for a summary of all features.
6
6
 
7
7
  ![Each worktree keeps its own .env; envs edit and envs push sync the shared values across them](docs/assets/images/worktrees-sync.svg)
8
8
 
@@ -36,13 +36,22 @@ The examples below use `envs`; without a global install, replace it with `bunx @
36
36
 
37
37
  Run the commands inside the repo or any of its worktrees. Inside a worktree, `.envs/` always lives in the main repo.
38
38
 
39
+ ![Web editor started with envs edit --ui](docs/assets/images/edit-ui.png)
40
+
41
+ A walkthrough with a screenshot of each action is in [docs/ui.md](docs/ui.md) (in Spanish).
42
+
39
43
  | Command | What it does |
40
44
  | --- | --- |
41
45
  | `envs edit` | Runs `init` if `.envs/values.yml` does not exist yet, then runs `pull`, opens `values.yml` with `code -w` and, when the editor closes, runs `push`. If the editor fails, it does not `push`. |
46
+ | `envs edit --ui` | Same `init` and `pull`, but instead of VS Code it starts a local server (`127.0.0.1`, random port) and opens a React web editor with the values of `values.yml` (worktree profiles, defaults and per-worktree values). The **Save** button in the top right corner writes `values.yml` and runs `push`. Its **History** panel lists the history points (newest first); hovering or clicking a point shows what restoring it would change in the editor (red: removed, green: changed or added), and its **Restore** button, after a confirmation, runs `envs restore` for that point. Stop the server with Ctrl+C. |
42
47
  | `envs init` | Creates `.envs/`, `.envs/.gitignore` (containing `*`) and an empty `.envs/values.yml`. Does not overwrite existing files. |
43
48
  | `envs pull` | Reads the `.env` of the main repo and of each worktree and writes it to `values.yml`. Variables that are no longer in a `.env` are removed from `values.yml` for that worktree. |
44
49
  | `envs push` | Writes `values.yml` to the `.env` of each worktree. Updates existing variables in place, appends new ones at the end, and keeps comments and variables that are not in `values.yml`. |
45
50
  | `envs use [profile]` | Sets the profile of the current worktree (`uses.<worktree>`) and pushes that worktree. Without arguments it lists the profile of each worktree. The profile must already exist in `values.yml`. |
51
+ | `envs restore <hash>` | Restores `values.yml` to the state it had after the history point `<hash>` (a unique prefix is enough), adds a new point with the difference and runs `push`. Existing points are never removed. See [docs/history.md](docs/history.md). |
52
+ | `envs config set <key> <value>` | Saves a setting in `.envs/config.yml` (created on demand with mode `600`, along with `.envs/.gitignore` if missing). `true`, `false` and numbers are stored as such; the rest as strings. |
53
+ | `envs config get [key]` | Prints the value of a setting, or every `key=value` when no key is given. Exits with code 1 if the key does not exist. |
54
+ | `envs config delete <key>` | Removes a setting. Exits with code 1 if the key does not exist. |
46
55
  | `envs lint` | Checks security and prints a warning for each problem. Exits with code 1 if there is any (useful in CI). See below. |
47
56
  | `envs help` | Shows the help (also `--help`, `-h`, or no command). |
48
57
 
@@ -93,6 +102,65 @@ It never prints values, only the variable and its location (`envs.DB_PASSWORD.ma
93
102
  | `secret-pattern` | Value with a known secret format (AWS, GitHub, Slack, `sk-…`, private key). |
94
103
  | `url-credentials`, `insecure-url` | Remote URL with an embedded password, or using `http://`, `ws://` or `ftp://`. |
95
104
 
105
+ ## History
106
+
107
+ See [docs/history.md](docs/history.md) for the full documentation (in Spanish).
108
+
109
+ `envs` keeps a record of how `values.yml` evolved. It works with two separate concepts:
110
+
111
+ | Concept | Where | What it is |
112
+ | --- | --- | --- |
113
+ | **Snapshot** | `.envs/values.yml` | The complete current state: every profile, default and per-worktree value. It is the file you edit, and it is the only thing `push` reads. |
114
+ | **Changes** | `.envs/history.ndjson` | An append-only log. Each line is a *point* holding only what changed between two states, never a full copy of the file. |
115
+
116
+ The snapshot answers "what are the values now?"; the changes answer "what changed, when, and from what?". The history never replaces `values.yml`: if you delete `history.ndjson`, `envs` keeps working and the next `pull` starts a new history.
117
+
118
+ ### A point
119
+
120
+ One JSON object per line:
121
+
122
+ ```json
123
+ {"hash":"3f9a1c0b7d2e","prev":"e7c8ebe462f1","timestamp":"2026-01-01T00:02:00.000Z","changes":[{"path":["profiles","default","envs","PORT","feature-x"],"from":3001,"to":3002}]}
124
+ ```
125
+
126
+ - `changes` lists the differences. `path` locates the value inside the snapshot (`uses.<worktree>`, `profiles.<profile>.defaults.<VAR>` or `profiles.<profile>.envs.<VAR>.<worktree>`). `from` is absent when the entry was added and `to` is absent when it was removed.
127
+ - `prev` is the hash of the previous point (`null` for the first one) and `hash` is the first 12 hex characters of the sha256 of `prev`, `timestamp` and `changes`. The file is a hash chain: altering or removing a point breaks every later one.
128
+
129
+ ### When a point is added
130
+
131
+ A point is written only when `values.yml` actually changed.
132
+
133
+ - The **first** `envs pull` (also run by `envs edit`) creates the first point. Its `changes` describe the whole initial snapshot, as if it had been built from nothing.
134
+ - Any later `envs pull` adds a point with what it changed, for example after you edited a worktree's `.env` by hand.
135
+ - `envs edit` adds a point with what you changed in the editor, and so does Save in `envs edit --ui`.
136
+ - `envs use <profile>` adds a point with the profile change.
137
+
138
+ ### Reading it
139
+
140
+ Applying the points in order, from the first one, rebuilds the snapshot as it was after each of them. Because the first point contains the whole initial state, the result after the last point equals `values.yml`. The exception is a manual edit of `values.yml` made outside these commands: it is part of the snapshot but has no point.
141
+
142
+ ### Turning it off
143
+
144
+ The history is active by default. It reads the `history` setting of `.envs/config.yml`: only an explicit `false` turns it off, and `values.yml` keeps being updated as usual.
145
+
146
+ ```sh
147
+ envs config set history false # stop recording
148
+ envs config set history true # record again (or `envs config delete history`)
149
+ ```
150
+
151
+ Changes made while it is off get no point: when you turn it on again, the next point starts from the `values.yml` of that moment.
152
+
153
+ ### In the web editor
154
+
155
+ The **History** panel of `envs edit --ui` lists the points, newest first, with their short hash, time and number of changes. Hovering a point, or clicking it to keep it selected (a click never restores), compares the state after that point with the values in the editor, grouped by worktree profiles and by profile (`defaults`, `envs`):
156
+
157
+ - **red**: the entry exists now and would be removed;
158
+ - **green**: the entry would change (current value → value at that point) or would be added.
159
+
160
+ When they are equal it says "No differences". **Restore** asks for confirmation (and warns that unsaved editor changes will be lost), then restores the point like `envs restore`: a new point is appended, none is removed, and the editor and the panel reload. With the history off the panel shows an empty state and offers no restore.
161
+
162
+ The file is created with mode `600` because it holds variable values. Like the rest of `.envs/`, it is ignored by git.
163
+
96
164
  ## `values.yml` format
97
165
 
98
166
  ```yaml