envrcctl 0.0.1__tar.gz

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.
@@ -0,0 +1,11 @@
1
+
2
+ .venv/
3
+ .agent/
4
+ .rules
5
+ __pycache__/
6
+ *.py[cod]
7
+ .pytest_cache/
8
+ .coverage
9
+ htmlcov/
10
+ .DS_Store
11
+ .envrc
envrcctl-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rio Fujita
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,272 @@
1
+ Metadata-Version: 2.4
2
+ Name: envrcctl
3
+ Version: 0.0.1
4
+ Summary: Manage .envrc with managed blocks and OS-backed secrets.
5
+ License: MIT License
6
+
7
+ Copyright (c) 2026 Rio Fujita
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+ License-File: LICENSE
27
+ Requires-Python: >=3.14
28
+ Requires-Dist: typer>=0.24.1
29
+ Description-Content-Type: text/markdown
30
+
31
+ # envrcctl
32
+
33
+ envrcctl is a CLI tool that manages `.envrc` files safely through a managed
34
+ block, with secrets stored in your OS key store instead of the file.
35
+
36
+ It is designed for macOS first, with Linux support via SecretService.
37
+
38
+ ## Features
39
+
40
+ - Safe, structured edits to `.envrc` (managed block only)
41
+ - Non-secret environment variables (CRUD)
42
+ - Secrets stored in Keychain (macOS) or SecretService (Linux)
43
+ - Inheritance control (`source_up` on/off)
44
+ - Exec-based secret injection (`envrcctl exec -- ...`)
45
+ - Secret injection for direnv (`eval "$(envrcctl inject)"`, TTY-guarded)
46
+ - Secret kinds (runtime/admin), with exec injecting runtime only
47
+ - Secret get with clipboard default and TTY guard
48
+ - Diagnostics and migration helpers
49
+ - Shell completion scripts
50
+
51
+ ## Requirements
52
+
53
+ - Python 3.14+
54
+ - `direnv`
55
+ - macOS Keychain (built-in) or Linux SecretService (`secret-tool`)
56
+
57
+ ## Installation
58
+
59
+ ### macOS (Homebrew)
60
+
61
+ Tap and install:
62
+
63
+ ```sh
64
+ brew tap rioriost/envrcctl
65
+ brew install envrcctl
66
+ ```
67
+
68
+ After release, Homebrew will download the release from GitHub.
69
+
70
+ Install direnv with Homebrew:
71
+
72
+ ```sh
73
+ brew install direnv
74
+ ```
75
+
76
+ ### Linux (pipx, recommended)
77
+
78
+ ```sh
79
+ pipx install envrcctl
80
+ ```
81
+
82
+ ### Linux (uv)
83
+
84
+ ```sh
85
+ uv tool install envrcctl
86
+ ```
87
+
88
+ ### From source (macOS/Linux)
89
+
90
+ ```sh
91
+ git clone <REPO_URL>
92
+ cd envrcctl
93
+ uv sync
94
+ uv run python -m envrcctl.main --help
95
+ ```
96
+
97
+ ## Quick Start
98
+
99
+ 1. Initialize a managed block in `.envrc`:
100
+
101
+ ```sh
102
+ envrcctl init
103
+ ```
104
+
105
+ If `.envrc` already exists, you'll be prompted to confirm. Use `--yes` to skip the prompt in non-interactive runs.
106
+
107
+ 2. Add non-secret variables:
108
+
109
+ ```sh
110
+ envrcctl set FOO bar
111
+ envrcctl get FOO
112
+ envrcctl list
113
+ ```
114
+
115
+ 3. Enable inheritance:
116
+
117
+ ```sh
118
+ envrcctl inherit on
119
+ ```
120
+
121
+ 4. Store a secret:
122
+
123
+ ```sh
124
+ envrcctl secret set OPENAI_API_KEY --account openai:prod
125
+ ```
126
+
127
+ 5. Ensure your `.envrc` includes:
128
+
129
+ ```sh
130
+ eval "$(envrcctl inject)"
131
+ ```
132
+
133
+ 6. Allow direnv:
134
+
135
+ ```sh
136
+ direnv allow
137
+ ```
138
+
139
+ ## Commands
140
+
141
+ ### Non-secret variables
142
+
143
+ ```sh
144
+ envrcctl set VAR value
145
+ envrcctl unset VAR
146
+ envrcctl get VAR
147
+ envrcctl list
148
+ ```
149
+
150
+ ### Secrets
151
+
152
+ ```sh
153
+ envrcctl secret set OPENAI_API_KEY --account openai:prod --kind runtime
154
+ envrcctl secret set OPENAI_API_KEY --account openai:admin --kind admin
155
+ envrcctl secret unset OPENAI_API_KEY
156
+ envrcctl secret list
157
+ envrcctl secret get OPENAI_API_KEY
158
+ envrcctl secret get OPENAI_API_KEY --plain
159
+ ```
160
+
161
+ For CI-safe input:
162
+
163
+ ```sh
164
+ echo -n "$OPENAI_API_KEY" | envrcctl secret set OPENAI_API_KEY --account openai:prod --stdin
165
+ ```
166
+
167
+ ### Exec secrets without stdout
168
+
169
+ ```sh
170
+ envrcctl exec -- python script.py
171
+ envrcctl exec -k OPENAI_API_KEY -- python script.py
172
+ ```
173
+
174
+ Exec injects runtime secrets only.
175
+
176
+ ### Inject secrets for direnv
177
+
178
+ ```sh
179
+ envrcctl inject
180
+ ```
181
+
182
+ Non-interactive runs are blocked unless `--force` is provided.
183
+
184
+ ### Effective view (masked)
185
+
186
+ ```sh
187
+ envrcctl eval
188
+ ```
189
+
190
+ ### Diagnostics
191
+
192
+ ```sh
193
+ envrcctl doctor
194
+ ```
195
+
196
+ ### Migration
197
+
198
+ ```sh
199
+ envrcctl migrate
200
+ ```
201
+
202
+ You'll be prompted when unmanaged exports or secret refs are detected. Use `--yes` to confirm in non-interactive runs.
203
+
204
+ ## Backend Selection (macOS/Linux)
205
+
206
+ envrcctl selects a backend automatically by platform, or via `ENVRCCTL_BACKEND`.
207
+
208
+ Supported schemes:
209
+
210
+ - `kc` — macOS Keychain
211
+ - `ss` — SecretService via `secret-tool`
212
+
213
+ Example:
214
+
215
+ ```sh
216
+ ENVRCCTL_BACKEND=ss envrcctl secret set OPENAI_API_KEY --account openai:prod
217
+ ```
218
+
219
+ Secret references are stored as:
220
+
221
+ ```
222
+ <scheme>:<service>:<account>:<kind>
223
+ ```
224
+
225
+ `kind` is `runtime` or `admin` (default: `runtime`).
226
+
227
+ Example:
228
+
229
+ ```
230
+ kc:st.rio.envrcctl:openai:prod:runtime
231
+ kc:st.rio.envrcctl:openai:admin:admin
232
+ ```
233
+
234
+ ## Shell Completion
235
+
236
+ ```sh
237
+ envrcctl --install-completion
238
+ envrcctl --show-completion bash
239
+ envrcctl --show-completion zsh
240
+ envrcctl --show-completion fish
241
+ ```
242
+
243
+ Generated scripts are stored under `completions/`. To refresh:
244
+
245
+ ```sh
246
+ uv run python scripts/generate_completions.py
247
+ ```
248
+
249
+ ## Security Notes
250
+
251
+ - Secrets are never written to `.envrc`
252
+ - Secrets are never passed in CLI arguments
253
+ - `.envrc` updates are atomic
254
+ - `inject` is blocked in non-interactive environments unless `--force` is provided
255
+ - `secret get` is clipboard-only by default; plaintext output is TTY-guarded
256
+ - The tool refuses to write to world-writable `.envrc`
257
+
258
+ ## Development
259
+
260
+ ```sh
261
+ uv sync
262
+ .venv/bin/envrcctl --help
263
+ ```
264
+
265
+ ## Acknowledgements
266
+
267
+ Based on the article below, I added commands such as `exec`. Thank you for the helpful hints.
268
+ “[もう.envにAPIキーを平文で置くのはやめた — macOS Keychain管理CLI「LLM Key Ring」](https://zenn.dev/yottayoshida/articles/llm-key-ring-secure-api-key-management)”
269
+
270
+ ## License
271
+
272
+ MIT
@@ -0,0 +1,242 @@
1
+ # envrcctl
2
+
3
+ envrcctl is a CLI tool that manages `.envrc` files safely through a managed
4
+ block, with secrets stored in your OS key store instead of the file.
5
+
6
+ It is designed for macOS first, with Linux support via SecretService.
7
+
8
+ ## Features
9
+
10
+ - Safe, structured edits to `.envrc` (managed block only)
11
+ - Non-secret environment variables (CRUD)
12
+ - Secrets stored in Keychain (macOS) or SecretService (Linux)
13
+ - Inheritance control (`source_up` on/off)
14
+ - Exec-based secret injection (`envrcctl exec -- ...`)
15
+ - Secret injection for direnv (`eval "$(envrcctl inject)"`, TTY-guarded)
16
+ - Secret kinds (runtime/admin), with exec injecting runtime only
17
+ - Secret get with clipboard default and TTY guard
18
+ - Diagnostics and migration helpers
19
+ - Shell completion scripts
20
+
21
+ ## Requirements
22
+
23
+ - Python 3.14+
24
+ - `direnv`
25
+ - macOS Keychain (built-in) or Linux SecretService (`secret-tool`)
26
+
27
+ ## Installation
28
+
29
+ ### macOS (Homebrew)
30
+
31
+ Tap and install:
32
+
33
+ ```sh
34
+ brew tap rioriost/envrcctl
35
+ brew install envrcctl
36
+ ```
37
+
38
+ After release, Homebrew will download the release from GitHub.
39
+
40
+ Install direnv with Homebrew:
41
+
42
+ ```sh
43
+ brew install direnv
44
+ ```
45
+
46
+ ### Linux (pipx, recommended)
47
+
48
+ ```sh
49
+ pipx install envrcctl
50
+ ```
51
+
52
+ ### Linux (uv)
53
+
54
+ ```sh
55
+ uv tool install envrcctl
56
+ ```
57
+
58
+ ### From source (macOS/Linux)
59
+
60
+ ```sh
61
+ git clone <REPO_URL>
62
+ cd envrcctl
63
+ uv sync
64
+ uv run python -m envrcctl.main --help
65
+ ```
66
+
67
+ ## Quick Start
68
+
69
+ 1. Initialize a managed block in `.envrc`:
70
+
71
+ ```sh
72
+ envrcctl init
73
+ ```
74
+
75
+ If `.envrc` already exists, you'll be prompted to confirm. Use `--yes` to skip the prompt in non-interactive runs.
76
+
77
+ 2. Add non-secret variables:
78
+
79
+ ```sh
80
+ envrcctl set FOO bar
81
+ envrcctl get FOO
82
+ envrcctl list
83
+ ```
84
+
85
+ 3. Enable inheritance:
86
+
87
+ ```sh
88
+ envrcctl inherit on
89
+ ```
90
+
91
+ 4. Store a secret:
92
+
93
+ ```sh
94
+ envrcctl secret set OPENAI_API_KEY --account openai:prod
95
+ ```
96
+
97
+ 5. Ensure your `.envrc` includes:
98
+
99
+ ```sh
100
+ eval "$(envrcctl inject)"
101
+ ```
102
+
103
+ 6. Allow direnv:
104
+
105
+ ```sh
106
+ direnv allow
107
+ ```
108
+
109
+ ## Commands
110
+
111
+ ### Non-secret variables
112
+
113
+ ```sh
114
+ envrcctl set VAR value
115
+ envrcctl unset VAR
116
+ envrcctl get VAR
117
+ envrcctl list
118
+ ```
119
+
120
+ ### Secrets
121
+
122
+ ```sh
123
+ envrcctl secret set OPENAI_API_KEY --account openai:prod --kind runtime
124
+ envrcctl secret set OPENAI_API_KEY --account openai:admin --kind admin
125
+ envrcctl secret unset OPENAI_API_KEY
126
+ envrcctl secret list
127
+ envrcctl secret get OPENAI_API_KEY
128
+ envrcctl secret get OPENAI_API_KEY --plain
129
+ ```
130
+
131
+ For CI-safe input:
132
+
133
+ ```sh
134
+ echo -n "$OPENAI_API_KEY" | envrcctl secret set OPENAI_API_KEY --account openai:prod --stdin
135
+ ```
136
+
137
+ ### Exec secrets without stdout
138
+
139
+ ```sh
140
+ envrcctl exec -- python script.py
141
+ envrcctl exec -k OPENAI_API_KEY -- python script.py
142
+ ```
143
+
144
+ Exec injects runtime secrets only.
145
+
146
+ ### Inject secrets for direnv
147
+
148
+ ```sh
149
+ envrcctl inject
150
+ ```
151
+
152
+ Non-interactive runs are blocked unless `--force` is provided.
153
+
154
+ ### Effective view (masked)
155
+
156
+ ```sh
157
+ envrcctl eval
158
+ ```
159
+
160
+ ### Diagnostics
161
+
162
+ ```sh
163
+ envrcctl doctor
164
+ ```
165
+
166
+ ### Migration
167
+
168
+ ```sh
169
+ envrcctl migrate
170
+ ```
171
+
172
+ You'll be prompted when unmanaged exports or secret refs are detected. Use `--yes` to confirm in non-interactive runs.
173
+
174
+ ## Backend Selection (macOS/Linux)
175
+
176
+ envrcctl selects a backend automatically by platform, or via `ENVRCCTL_BACKEND`.
177
+
178
+ Supported schemes:
179
+
180
+ - `kc` — macOS Keychain
181
+ - `ss` — SecretService via `secret-tool`
182
+
183
+ Example:
184
+
185
+ ```sh
186
+ ENVRCCTL_BACKEND=ss envrcctl secret set OPENAI_API_KEY --account openai:prod
187
+ ```
188
+
189
+ Secret references are stored as:
190
+
191
+ ```
192
+ <scheme>:<service>:<account>:<kind>
193
+ ```
194
+
195
+ `kind` is `runtime` or `admin` (default: `runtime`).
196
+
197
+ Example:
198
+
199
+ ```
200
+ kc:st.rio.envrcctl:openai:prod:runtime
201
+ kc:st.rio.envrcctl:openai:admin:admin
202
+ ```
203
+
204
+ ## Shell Completion
205
+
206
+ ```sh
207
+ envrcctl --install-completion
208
+ envrcctl --show-completion bash
209
+ envrcctl --show-completion zsh
210
+ envrcctl --show-completion fish
211
+ ```
212
+
213
+ Generated scripts are stored under `completions/`. To refresh:
214
+
215
+ ```sh
216
+ uv run python scripts/generate_completions.py
217
+ ```
218
+
219
+ ## Security Notes
220
+
221
+ - Secrets are never written to `.envrc`
222
+ - Secrets are never passed in CLI arguments
223
+ - `.envrc` updates are atomic
224
+ - `inject` is blocked in non-interactive environments unless `--force` is provided
225
+ - `secret get` is clipboard-only by default; plaintext output is TTY-guarded
226
+ - The tool refuses to write to world-writable `.envrc`
227
+
228
+ ## Development
229
+
230
+ ```sh
231
+ uv sync
232
+ .venv/bin/envrcctl --help
233
+ ```
234
+
235
+ ## Acknowledgements
236
+
237
+ Based on the article below, I added commands such as `exec`. Thank you for the helpful hints.
238
+ “[もう.envにAPIキーを平文で置くのはやめた — macOS Keychain管理CLI「LLM Key Ring」](https://zenn.dev/yottayoshida/articles/llm-key-ring-secure-api-key-management)”
239
+
240
+ ## License
241
+
242
+ MIT
@@ -0,0 +1,11 @@
1
+
2
+ _envrcctl_completion() {
3
+ local IFS=$'
4
+ '
5
+ COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \
6
+ COMP_CWORD=$COMP_CWORD \
7
+ _ENVRCCTL_COMPLETE=complete_bash $1 ) )
8
+ return 0
9
+ }
10
+
11
+ complete -o default -F _envrcctl_completion envrcctl
@@ -0,0 +1 @@
1
+ complete --command envrcctl --no-files --arguments "(env _ENVRCCTL_COMPLETE=complete_fish _TYPER_COMPLETE_FISH_ACTION=get-args _TYPER_COMPLETE_ARGS=(commandline -cp) envrcctl)" --condition "env _ENVRCCTL_COMPLETE=complete_fish _TYPER_COMPLETE_FISH_ACTION=is-args _TYPER_COMPLETE_ARGS=(commandline -cp) envrcctl"
@@ -0,0 +1,8 @@
1
+
2
+ #compdef envrcctl
3
+
4
+ _envrcctl_completion() {
5
+ eval $(env _TYPER_COMPLETE_ARGS="${words[1,$CURRENT]}" _ENVRCCTL_COMPLETE=complete_zsh envrcctl)
6
+ }
7
+
8
+ compdef _envrcctl_completion envrcctl
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "envrcctl"
3
+ version = "0.0.1"
4
+ description = "Manage .envrc with managed blocks and OS-backed secrets."
5
+ readme = "README.md"
6
+ license = { file = "LICENSE" }
7
+ requires-python = ">=3.14"
8
+ dependencies = [
9
+ "typer>=0.24.1",
10
+ ]
11
+
12
+ [project.scripts]
13
+ envrcctl = "envrcctl.main:main"
14
+
15
+ [build-system]
16
+ requires = ["hatchling>=1.24.2"]
17
+ build-backend = "hatchling.build"
18
+
19
+ [tool.hatch.build.targets.wheel]
20
+ packages = ["src/envrcctl"]
21
+ include = ["completions/**"]
22
+
23
+ [tool.hatch.build.targets.sdist]
24
+ include = ["src/envrcctl/**", "completions/**", "README.md", "LICENSE", "pyproject.toml"]
25
+
26
+ [dependency-groups]
27
+ dev = [
28
+ "pytest>=9.0.2",
29
+ "pytest-cov>=7.0.0",
30
+ "bandit>=1.7.10",
31
+ ]
@@ -0,0 +1 @@
1
+ """envrcctl package."""