@akshxy/envgit 0.4.0 → 0.4.2

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.
Files changed (3) hide show
  1. package/README.md +145 -55
  2. package/package.json +1 -1
  3. package/src/envfile.js +1 -4
package/README.md CHANGED
@@ -1,14 +1,23 @@
1
1
  # envgit
2
2
 
3
- Encrypted per-project environment variable manager. Store secrets safely alongside your code — encrypted at rest, never in plaintext.
3
+ Encrypted per-project environment variable manager. Commit your secrets safely — encrypted at rest, decrypted only on machines that have the key.
4
4
 
5
- ```
5
+ ```bash
6
6
  npm install -g @akshxy/envgit
7
7
  ```
8
8
 
9
+ ---
10
+
9
11
  ## Why
10
12
 
11
- `.env` files get committed by accident. `envgit` keeps your secrets encrypted in `.envgit/` so you can safely commit them to git and share them with your team — only people with the key can decrypt them.
13
+ `.env` files get committed by accident. Sharing secrets over Slack or email is a disaster waiting to happen. `envgit` fixes both:
14
+
15
+ - Secrets are encrypted with **AES-256-GCM** and live in `.envgit/` — safe to commit
16
+ - The key lives on **your machine only** (`~/.config/envgit/keys/`) — never touches the repo
17
+ - Teammates just run `envgit keygen --set <key>` after cloning — no manual file management
18
+ - `envgit unpack dev` writes a clean, **beautifully formatted `.env`** grouped by service
19
+
20
+ ---
12
21
 
13
22
  ## Quick start
14
23
 
@@ -16,44 +25,125 @@ npm install -g @akshxy/envgit
16
25
  # 1. Initialize in your project
17
26
  envgit init
18
27
 
19
- # 2. Set some variables
20
- envgit set API_KEY=abc123 DB_PASS=secret
28
+ # 2. Set variables
29
+ envgit set API_KEY=abc123 DB_URL=postgres://localhost/mydb
30
+
31
+ # 3. Or load from an existing .env file
32
+ envgit set -f .env.local
21
33
 
22
- # 3. Commit the encrypted store (not the key!)
34
+ # 4. Commit the encrypted store key never included
23
35
  git add .envgit/
24
- git commit -m "add encrypted env"
36
+ git commit -m "chore: add encrypted env"
37
+
38
+ # 5. Write .env locally whenever you need it
39
+ envgit unpack dev
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Team workflow
45
+
46
+ ```bash
47
+ # ── Developer A (project owner) ──────────────────────────
48
+ envgit init
49
+ envgit set DB_URL=postgres://... OPENAI_API_KEY=sk-...
50
+ git add .envgit/ && git commit -m "chore: encrypted env"
25
51
 
26
- # 4. Share your key with teammates
27
52
  envgit keygen --show
28
- # teammate runs: envgit keygen --set <key>
53
+ # Prints your key send it to teammates via 1Password, Bitwarden, etc.
29
54
 
30
- # 5. Write .env when you need it locally
31
- envgit unpack dev
55
+ # ── Developer B (teammate, after cloning) ─────────────────
56
+ envgit keygen --set <key-from-teammate>
57
+ # Key is saved to ~/.config/envgit/keys/<project-id>.key automatically
58
+ # No file paths to think about — it just works
59
+
60
+ envgit verify # confirm the key works
61
+ envgit unpack dev # writes .env
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Formatted `.env` output
67
+
68
+ When you run `envgit unpack`, the `.env` is written with sections grouped by service — no more chaotic unsorted files:
69
+
70
+ ```bash
71
+ # ──────────────────────────────────────────────────
72
+ # envgit — encrypted environment manager
73
+ # Project : myapp
74
+ # Env : dev
75
+ # Edit : envgit set KEY=VALUE --env dev
76
+ # ──────────────────────────────────────────────────
77
+
78
+ # ── App / Config ────────────────────────────────
79
+ NODE_ENV=development
80
+ PORT=3000
81
+
82
+ # ── AI / Anthropic ──────────────────────────────
83
+ ANTHROPIC_API_KEY=sk-ant-...
84
+
85
+ # ── AI / OpenAI ─────────────────────────────────
86
+ OPENAI_API_KEY=sk-...
87
+
88
+ # ── Auth / Clerk ────────────────────────────────
89
+ CLERK_SECRET_KEY=sk_test_...
90
+
91
+ # ── Auth / NextAuth ─────────────────────────────
92
+ NEXTAUTH_SECRET=...
93
+ NEXTAUTH_URL=http://localhost:3000
94
+
95
+ # ── AWS ─────────────────────────────────────────
96
+ AWS_ACCESS_KEY_ID=AKIA...
97
+ AWS_REGION=us-east-1
98
+ AWS_SECRET_ACCESS_KEY=...
99
+
100
+ # ── Cache / Redis ───────────────────────────────
101
+ REDIS_URL=redis://localhost:6379
102
+
103
+ # ── Database / PostgreSQL ───────────────────────
104
+ DATABASE_URL=postgres://localhost/mydb
105
+
106
+ # ── Next.js / Public (client-side) ──────────────
107
+ NEXT_PUBLIC_API_URL=http://localhost:3000/api
108
+
109
+ # ── Payments / Stripe ───────────────────────────
110
+ STRIPE_SECRET_KEY=sk_test_...
111
+ STRIPE_WEBHOOK_SECRET=whsec_...
112
+
113
+ # ── Supabase ────────────────────────────────────
114
+ SUPABASE_ANON_KEY=eyJ...
115
+ SUPABASE_URL=https://xyz.supabase.co
32
116
  ```
33
117
 
118
+ Supports 100+ services out of the box: OpenAI, Anthropic, Groq, Stripe, Supabase, Clerk, Auth0, NextAuth, AWS, GCP, Azure, Redis, Upstash, Resend, SendGrid, Twilio, Sentry, Datadog, PostHog, Segment, Algolia, Pinecone, Cloudinary, and many more.
119
+
120
+ ---
121
+
34
122
  ## Commands
35
123
 
36
124
  ### Key management
37
125
 
38
126
  | Command | Description |
39
127
  |---------|-------------|
40
- | `envgit init` | Initialize in current project, generates key |
41
- | `envgit keygen` | Generate a new key and save it |
42
- | `envgit keygen --show` | Print current key for sharing with teammates |
43
- | `envgit keygen --set <key>` | Save a key received from a teammate |
44
- | `envgit rotate-key` | Generate new key, re-encrypt all environments |
45
- | `envgit verify` | Check all environments decrypt correctly |
128
+ | `envgit init` | Initialize project, generate key, save to `~/.config/envgit/keys/` |
129
+ | `envgit keygen` | Generate a new key for the current project |
130
+ | `envgit keygen --show` | Print current key to share with teammates |
131
+ | `envgit keygen --set <key>` | Save a teammate's key for the current project |
132
+ | `envgit rotate-key` | Generate new key and re-encrypt all environments |
133
+ | `envgit verify` | Confirm all environments decrypt with the current key |
46
134
 
47
135
  ### Variables
48
136
 
49
137
  | Command | Description |
50
138
  |---------|-------------|
51
139
  | `envgit set KEY=VALUE ...` | Set one or more variables |
140
+ | `envgit set -f .env` | Import all variables from a `.env` file |
141
+ | `envgit set -f .env --env prod` | Import into a specific environment |
52
142
  | `envgit get KEY` | Print a single value |
53
143
  | `envgit delete KEY` | Remove a variable |
54
144
  | `envgit rename OLD NEW` | Rename a variable |
55
- | `envgit list` | List all keys in active environment |
56
- | `envgit list --show-values` | List keys and values |
145
+ | `envgit list` | List all keys in the active environment |
146
+ | `envgit list --show-values` | List keys and their values |
57
147
 
58
148
  ### Environments
59
149
 
@@ -61,68 +151,68 @@ envgit unpack dev
61
151
  |---------|-------------|
62
152
  | `envgit envs` | List all environments with variable counts |
63
153
  | `envgit add-env <name>` | Create a new environment |
64
- | `envgit unpack <env>` | Decrypt env and write `.env` file |
154
+ | `envgit unpack <env>` | Decrypt and write a formatted `.env` file |
65
155
  | `envgit copy KEY --from dev --to prod` | Copy a variable between environments |
66
- | `envgit diff dev prod` | Show differences between two environments |
67
- | `envgit diff dev prod --show-values` | Include values in diff |
156
+ | `envgit diff dev prod` | Show what's different between two environments |
157
+ | `envgit diff dev prod --show-values` | Include values in the diff |
68
158
 
69
159
  ### Export & run
70
160
 
71
161
  | Command | Description |
72
162
  |---------|-------------|
73
- | `envgit export` | Print as `KEY=VALUE` lines (pipeable) |
163
+ | `envgit export` | Print `KEY=VALUE` lines to stdout (pipeable) |
74
164
  | `envgit export --format json` | Print as JSON |
75
165
  | `envgit export --format shell` | Print as `export KEY="VALUE"` (eval-able) |
76
- | `envgit run -- node server.js` | Run a command with env vars injected |
166
+ | `envgit export --env prod` | Export a specific environment |
167
+ | `envgit run -- node server.js` | Run a command with env vars injected, nothing written to disk |
77
168
  | `envgit import --file .env.local` | Encrypt an existing `.env` file |
78
169
 
79
170
  ### Status
80
171
 
81
172
  | Command | Description |
82
173
  |---------|-------------|
83
- | `envgit status` | Show project, active env, key source, .env state |
174
+ | `envgit status` | Show project root, active env, key location, `.env` state |
175
+
176
+ ---
84
177
 
85
- ## All options support `--env <name>`
178
+ ## `--env` flag
86
179
 
87
- Most commands default to the active environment. Pass `--env` to target a specific one:
180
+ Most commands default to the active environment. Pass `--env` to target any environment explicitly:
88
181
 
89
182
  ```bash
90
- envgit set API_KEY=prod-key --env prod
183
+ envgit set STRIPE_KEY=sk_live_... --env prod
91
184
  envgit list --env staging
92
- envgit export --env prod --format json
185
+ envgit export --env prod --format json | jq .
186
+ envgit run --env prod -- node scripts/migrate.js
93
187
  ```
94
188
 
95
- ## Team workflow
189
+ ---
190
+
191
+ ## CI / CD
192
+
193
+ Set `ENVGIT_KEY` instead of using a key file:
96
194
 
97
195
  ```bash
98
- # Developer A (project owner)
99
- envgit init
100
- envgit set DB_URL=postgres://... API_KEY=...
101
- git add .envgit/ && git commit -m "encrypted env"
102
- envgit keygen --show # share this key securely with teammates
196
+ # GitHub Actions
197
+ - name: Decrypt env
198
+ env:
199
+ ENVGIT_KEY: ${{ secrets.ENVGIT_KEY }}
200
+ run: envgit export --env prod --format shell >> $GITHUB_ENV
201
+ ```
103
202
 
104
- # Developer B (teammate)
105
- git clone <repo>
106
- envgit keygen --set <key-from-teammate>
107
- envgit unpack dev # writes .env
203
+ ```bash
204
+ # Local one-liner
205
+ ENVGIT_KEY=$(cat ~/.config/envgit/keys/<id>.key) envgit run -- node server.js
108
206
  ```
109
207
 
208
+ ---
209
+
110
210
  ## Security
111
211
 
112
- - **AES-256-GCM** — authenticated encryption, tamper-proof
113
- - **32-byte random key** from OS cryptographic RNG
114
- - **Fresh random IV** per encryption — same value encrypts differently each time
115
- - **Key file locked to `0o600`** unreadable by other users
116
- - **Permission check on load** — errors if `.envgit.key` is world-readable
212
+ - **AES-256-GCM** — authenticated encryption, any tampering is detected
213
+ - **32 bytes of entropy** from the OS cryptographic RNG (`crypto.randomBytes`)
214
+ - **Fresh random IV per write**encrypting the same value twice produces different ciphertext
215
+ - **Key stored at `~/.config/envgit/keys/`**never in the repo, never in `.env`
216
+ - **File permissions enforced** — key files are locked to `0600`, errors if too permissive
117
217
  - **Key bytes zeroized** from memory immediately after use
118
-
119
- The key (`~/.envgit.key`) is gitignored automatically. Never commit it.
120
-
121
- ## Environment variable
122
-
123
- Set `ENVGIT_KEY` instead of using a key file — useful in CI:
124
-
125
- ```bash
126
- export ENVGIT_KEY=$(cat .envgit.key)
127
- envgit export --format shell | source /dev/stdin
128
- ```
218
+ - **No plaintext ever written** except when you explicitly run `envgit unpack`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akshxy/envgit",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Encrypted per-project environment variable manager",
5
5
  "type": "module",
6
6
  "bin": {
package/src/envfile.js CHANGED
@@ -442,13 +442,10 @@ export function writeEnvFile(filePath, vars, { envName, projectRoot } = {}) {
442
442
  }
443
443
 
444
444
  const grouped = groupAndSort(vars);
445
- const maxKeyLen = Math.max(...entries.map(([k]) => k.length));
446
-
447
445
  for (const [section, sectionVars] of grouped) {
448
446
  lines.push(`# ── ${section} ${'─'.repeat(Math.max(0, 44 - section.length))}`);
449
447
  for (const [k, v] of sectionVars) {
450
- const padding = ' '.repeat(maxKeyLen - k.length);
451
- lines.push(`${k}${padding} = ${formatValue(v)}`);
448
+ lines.push(`${k}=${formatValue(v)}`);
452
449
  }
453
450
  lines.push('');
454
451
  }