devnomads-cli 0.9.1__tar.gz → 0.11.0__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.
Files changed (24) hide show
  1. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/PKG-INFO +91 -12
  2. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/README.md +88 -9
  3. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/devnomads_cli.egg-info/PKG-INFO +91 -12
  4. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/devnomads_cli.egg-info/SOURCES.txt +2 -1
  5. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/devnomads_cli.egg-info/requires.txt +2 -2
  6. devnomads_cli-0.11.0/dncli.py +9196 -0
  7. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/pyproject.toml +3 -3
  8. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/tests/test_cli.py +89 -1
  9. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/tests/test_config.py +53 -0
  10. devnomads_cli-0.11.0/tests/test_generate.py +356 -0
  11. devnomads_cli-0.11.0/tests/test_generated_cli.py +609 -0
  12. devnomads_cli-0.11.0/tests/test_versions.py +157 -0
  13. devnomads_cli-0.9.1/dncli.py +0 -4945
  14. devnomads_cli-0.9.1/tests/test_generate.py +0 -172
  15. devnomads_cli-0.9.1/tests/test_generated_cli.py +0 -295
  16. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/LICENSE +0 -0
  17. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/devnomads_cli.egg-info/dependency_links.txt +0 -0
  18. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/devnomads_cli.egg-info/entry_points.txt +0 -0
  19. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/devnomads_cli.egg-info/top_level.txt +0 -0
  20. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/setup.cfg +0 -0
  21. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/tests/test_cert.py +0 -0
  22. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/tests/test_helpers.py +0 -0
  23. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/tests/test_hook.py +0 -0
  24. {devnomads_cli-0.9.1 → devnomads_cli-0.11.0}/tests/test_transfer.py +0 -0
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devnomads-cli
3
- Version: 0.9.1
3
+ Version: 0.11.0
4
4
  Summary: Manage your DevNomads services from the command line
5
5
  Author-email: DevNomads <support@devnomads.nl>
6
6
  License: MIT
7
7
  Requires-Python: >=3.10
8
8
  Description-Content-Type: text/markdown
9
9
  License-File: LICENSE
10
- Requires-Dist: typer>=0.12
10
+ Requires-Dist: typer>=0.19
11
11
  Requires-Dist: httpx>=0.27
12
12
  Requires-Dist: rich>=13
13
13
  Requires-Dist: cryptography>=42
14
- Requires-Dist: devnomads[acme]>=0.5.0
14
+ Requires-Dist: devnomads[acme]>=0.6.0
15
15
  Dynamic: license-file
16
16
 
17
17
  # dncli
@@ -26,18 +26,43 @@ as **`devnomads-cli`**.
26
26
 
27
27
  ## Install
28
28
 
29
+ Install dncli with [uv](https://docs.astral.sh/uv/). It gives dncli
30
+ its own isolated environment and puts the `dncli` command on your
31
+ PATH:
32
+
29
33
  ```sh
30
- pip install devnomads-cli
34
+ uv tool install devnomads-cli
31
35
  ```
32
36
 
33
- For a global, isolated install (recommended on workstations), use
34
- [uv](https://docs.astral.sh/uv/) or pipx instead - same result, no
35
- interference with system packages:
37
+ No uv yet? Install it first:
38
+
39
+ ```sh
40
+ curl -LsSf https://astral.sh/uv/install.sh | sh # macOS, Linux
41
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" # Windows
42
+ ```
43
+
44
+ pipx (`pipx install devnomads-cli`) and pip (`pip install
45
+ devnomads-cli`) work as well.
46
+
47
+ ### Updates
48
+
49
+ Update with:
36
50
 
37
51
  ```sh
38
- uv tool install devnomads-cli # or: pipx install devnomads-cli
52
+ uv tool upgrade devnomads-cli
39
53
  ```
40
54
 
55
+ dncli checks PyPI at most once a day and tells you when a new version
56
+ is out, with the command to update the way you installed it. It only
57
+ does so on an interactive terminal, never in pipes, scripts or CI; set
58
+ `DN_NO_UPDATE_CHECK=1` to turn it off.
59
+
60
+ dncli also warns when the DevNomads API reports a major version it was
61
+ not built for, and tells you when the API no longer supports your
62
+ dncli version. Update dncli in both cases.
63
+
64
+ ### Shell completion
65
+
41
66
  Enable shell completion (bash, zsh, fish, PowerShell):
42
67
 
43
68
  ```sh
@@ -65,7 +90,8 @@ dncli containers show <id>
65
90
 
66
91
  Every DevNomads product has its own command group - `apps`,
67
92
  `buckets`, `containers`, `databases`, `domains`, `emails`,
68
- `forwards`, `proxies`, `servers`, `sites` and more. Explore with
93
+ `forwards`, `proxies`, `servers`, `sites` and more, plus `keys` for
94
+ your SSH keys and `jobs` for background work. Explore with
69
95
  `dncli --help` and `dncli <group> --help`.
70
96
 
71
97
  Commands accept any unambiguous prefix: `dncli e l` is `dncli emails
@@ -81,6 +107,18 @@ dncli dns records set example.com www A 192.0.2.1 --ttl 3600
81
107
  dncli dns records delete example.com www A
82
108
  ```
83
109
 
110
+ Anywhere a zone is expected you may pass the service id of a domain
111
+ instead of its name, so the ids from `dncli domains list` work here
112
+ too:
113
+
114
+ ```sh
115
+ dncli dns records list 42
116
+ ```
117
+
118
+ An id always means that domain's own zone. A delegated subzone such
119
+ as `foo.example.com` has no domain service of its own, so address it
120
+ by name.
121
+
84
122
  ## Moving a zone from another provider
85
123
 
86
124
  `dncli dns transfer` copies a zone from your current DNS provider
@@ -108,6 +146,17 @@ dncli services list --profile acme
108
146
  export DN_PROFILE=acme
109
147
  ```
110
148
 
149
+ Manage stored profiles:
150
+
151
+ ```sh
152
+ dncli configure list # profiles, with keys masked
153
+ dncli configure set-key acme # replace a profile's API key
154
+ dncli configure delete acme # remove a profile
155
+ ```
156
+
157
+ `set-key --stdin` reads the new key from standard input, and
158
+ `delete --yes` skips the question, for use in scripts.
159
+
111
160
  ## Scripting
112
161
 
113
162
  Output is a human-readable table on a terminal and JSON when piped,
@@ -131,9 +180,23 @@ fields, and reports an error on an unknown column name.
131
180
 
132
181
  Commands that take a service id also accept a unique entity name and
133
182
  resolve it for you, so `dncli domains show example.com` works as well
134
- as `dncli domains show 1234`. A purely numeric value is always treated
135
- as an id; an entity that matches more than one service is rejected, so
136
- pass the id when an entity is not unique.
183
+ as `dncli domains show 1234`. Names match regardless of case. A purely
184
+ numeric value is always treated as an id; an entity that matches more
185
+ than one service is rejected, so pass the id when an entity is not
186
+ unique. Other references, such as cluster, key or user ids, take the
187
+ numeric id only.
188
+
189
+ Some changes run in the background: creating a site, server, proxy or
190
+ domain, for example, queues one or more jobs in a batch. Such a command
191
+ prints the queued jobs and returns right away; add `--wait` to follow
192
+ the batch until every job has finished and see how each one ended.
193
+ With `--wait` the exit status is 0 only when every job completed. You
194
+ can look a batch up later with `dncli jobs batches show <batch_id>`.
195
+
196
+ The exit status is 0 when the API accepted the request and 1 for any
197
+ error response, so `dncli ... && next-step` is safe in scripts. Every
198
+ command takes `--timeout <seconds>` (default 300) for how long to wait
199
+ for the API, including the time spent waiting on `--wait`.
137
200
 
138
201
  In CI and pipelines, skip the credentials file and pass the key via
139
202
  the environment:
@@ -143,6 +206,22 @@ export DN_API_KEY=... # beats any stored profile
143
206
  dncli services list | jq -r '.[].entity'
144
207
  ```
145
208
 
209
+ ## AI agents
210
+
211
+ dncli ships with a skill that teaches AI coding agents how to use it
212
+ safely: where ids come from, what costs money or deletes data, and to
213
+ ask before changing anything. It works with Claude Code, Codex, Gemini
214
+ CLI, GitHub Copilot, Cursor and OpenCode:
215
+
216
+ ```sh
217
+ dncli skill install # every agent found on this machine
218
+ dncli skill install --agent codex # a specific agent; repeat for more
219
+ dncli skill install --project # into the current project instead
220
+ ```
221
+
222
+ Run it again after upgrading dncli to update the skill; `dncli skill
223
+ show` prints it.
224
+
146
225
  ## Certificates
147
226
 
148
227
  `dncli` issues Let's Encrypt certificates using the DNS-01 challenge:
@@ -10,18 +10,43 @@ as **`devnomads-cli`**.
10
10
 
11
11
  ## Install
12
12
 
13
+ Install dncli with [uv](https://docs.astral.sh/uv/). It gives dncli
14
+ its own isolated environment and puts the `dncli` command on your
15
+ PATH:
16
+
13
17
  ```sh
14
- pip install devnomads-cli
18
+ uv tool install devnomads-cli
15
19
  ```
16
20
 
17
- For a global, isolated install (recommended on workstations), use
18
- [uv](https://docs.astral.sh/uv/) or pipx instead - same result, no
19
- interference with system packages:
21
+ No uv yet? Install it first:
22
+
23
+ ```sh
24
+ curl -LsSf https://astral.sh/uv/install.sh | sh # macOS, Linux
25
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" # Windows
26
+ ```
27
+
28
+ pipx (`pipx install devnomads-cli`) and pip (`pip install
29
+ devnomads-cli`) work as well.
30
+
31
+ ### Updates
32
+
33
+ Update with:
20
34
 
21
35
  ```sh
22
- uv tool install devnomads-cli # or: pipx install devnomads-cli
36
+ uv tool upgrade devnomads-cli
23
37
  ```
24
38
 
39
+ dncli checks PyPI at most once a day and tells you when a new version
40
+ is out, with the command to update the way you installed it. It only
41
+ does so on an interactive terminal, never in pipes, scripts or CI; set
42
+ `DN_NO_UPDATE_CHECK=1` to turn it off.
43
+
44
+ dncli also warns when the DevNomads API reports a major version it was
45
+ not built for, and tells you when the API no longer supports your
46
+ dncli version. Update dncli in both cases.
47
+
48
+ ### Shell completion
49
+
25
50
  Enable shell completion (bash, zsh, fish, PowerShell):
26
51
 
27
52
  ```sh
@@ -49,7 +74,8 @@ dncli containers show <id>
49
74
 
50
75
  Every DevNomads product has its own command group - `apps`,
51
76
  `buckets`, `containers`, `databases`, `domains`, `emails`,
52
- `forwards`, `proxies`, `servers`, `sites` and more. Explore with
77
+ `forwards`, `proxies`, `servers`, `sites` and more, plus `keys` for
78
+ your SSH keys and `jobs` for background work. Explore with
53
79
  `dncli --help` and `dncli <group> --help`.
54
80
 
55
81
  Commands accept any unambiguous prefix: `dncli e l` is `dncli emails
@@ -65,6 +91,18 @@ dncli dns records set example.com www A 192.0.2.1 --ttl 3600
65
91
  dncli dns records delete example.com www A
66
92
  ```
67
93
 
94
+ Anywhere a zone is expected you may pass the service id of a domain
95
+ instead of its name, so the ids from `dncli domains list` work here
96
+ too:
97
+
98
+ ```sh
99
+ dncli dns records list 42
100
+ ```
101
+
102
+ An id always means that domain's own zone. A delegated subzone such
103
+ as `foo.example.com` has no domain service of its own, so address it
104
+ by name.
105
+
68
106
  ## Moving a zone from another provider
69
107
 
70
108
  `dncli dns transfer` copies a zone from your current DNS provider
@@ -92,6 +130,17 @@ dncli services list --profile acme
92
130
  export DN_PROFILE=acme
93
131
  ```
94
132
 
133
+ Manage stored profiles:
134
+
135
+ ```sh
136
+ dncli configure list # profiles, with keys masked
137
+ dncli configure set-key acme # replace a profile's API key
138
+ dncli configure delete acme # remove a profile
139
+ ```
140
+
141
+ `set-key --stdin` reads the new key from standard input, and
142
+ `delete --yes` skips the question, for use in scripts.
143
+
95
144
  ## Scripting
96
145
 
97
146
  Output is a human-readable table on a terminal and JSON when piped,
@@ -115,9 +164,23 @@ fields, and reports an error on an unknown column name.
115
164
 
116
165
  Commands that take a service id also accept a unique entity name and
117
166
  resolve it for you, so `dncli domains show example.com` works as well
118
- as `dncli domains show 1234`. A purely numeric value is always treated
119
- as an id; an entity that matches more than one service is rejected, so
120
- pass the id when an entity is not unique.
167
+ as `dncli domains show 1234`. Names match regardless of case. A purely
168
+ numeric value is always treated as an id; an entity that matches more
169
+ than one service is rejected, so pass the id when an entity is not
170
+ unique. Other references, such as cluster, key or user ids, take the
171
+ numeric id only.
172
+
173
+ Some changes run in the background: creating a site, server, proxy or
174
+ domain, for example, queues one or more jobs in a batch. Such a command
175
+ prints the queued jobs and returns right away; add `--wait` to follow
176
+ the batch until every job has finished and see how each one ended.
177
+ With `--wait` the exit status is 0 only when every job completed. You
178
+ can look a batch up later with `dncli jobs batches show <batch_id>`.
179
+
180
+ The exit status is 0 when the API accepted the request and 1 for any
181
+ error response, so `dncli ... && next-step` is safe in scripts. Every
182
+ command takes `--timeout <seconds>` (default 300) for how long to wait
183
+ for the API, including the time spent waiting on `--wait`.
121
184
 
122
185
  In CI and pipelines, skip the credentials file and pass the key via
123
186
  the environment:
@@ -127,6 +190,22 @@ export DN_API_KEY=... # beats any stored profile
127
190
  dncli services list | jq -r '.[].entity'
128
191
  ```
129
192
 
193
+ ## AI agents
194
+
195
+ dncli ships with a skill that teaches AI coding agents how to use it
196
+ safely: where ids come from, what costs money or deletes data, and to
197
+ ask before changing anything. It works with Claude Code, Codex, Gemini
198
+ CLI, GitHub Copilot, Cursor and OpenCode:
199
+
200
+ ```sh
201
+ dncli skill install # every agent found on this machine
202
+ dncli skill install --agent codex # a specific agent; repeat for more
203
+ dncli skill install --project # into the current project instead
204
+ ```
205
+
206
+ Run it again after upgrading dncli to update the skill; `dncli skill
207
+ show` prints it.
208
+
130
209
  ## Certificates
131
210
 
132
211
  `dncli` issues Let's Encrypt certificates using the DNS-01 challenge:
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devnomads-cli
3
- Version: 0.9.1
3
+ Version: 0.11.0
4
4
  Summary: Manage your DevNomads services from the command line
5
5
  Author-email: DevNomads <support@devnomads.nl>
6
6
  License: MIT
7
7
  Requires-Python: >=3.10
8
8
  Description-Content-Type: text/markdown
9
9
  License-File: LICENSE
10
- Requires-Dist: typer>=0.12
10
+ Requires-Dist: typer>=0.19
11
11
  Requires-Dist: httpx>=0.27
12
12
  Requires-Dist: rich>=13
13
13
  Requires-Dist: cryptography>=42
14
- Requires-Dist: devnomads[acme]>=0.5.0
14
+ Requires-Dist: devnomads[acme]>=0.6.0
15
15
  Dynamic: license-file
16
16
 
17
17
  # dncli
@@ -26,18 +26,43 @@ as **`devnomads-cli`**.
26
26
 
27
27
  ## Install
28
28
 
29
+ Install dncli with [uv](https://docs.astral.sh/uv/). It gives dncli
30
+ its own isolated environment and puts the `dncli` command on your
31
+ PATH:
32
+
29
33
  ```sh
30
- pip install devnomads-cli
34
+ uv tool install devnomads-cli
31
35
  ```
32
36
 
33
- For a global, isolated install (recommended on workstations), use
34
- [uv](https://docs.astral.sh/uv/) or pipx instead - same result, no
35
- interference with system packages:
37
+ No uv yet? Install it first:
38
+
39
+ ```sh
40
+ curl -LsSf https://astral.sh/uv/install.sh | sh # macOS, Linux
41
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" # Windows
42
+ ```
43
+
44
+ pipx (`pipx install devnomads-cli`) and pip (`pip install
45
+ devnomads-cli`) work as well.
46
+
47
+ ### Updates
48
+
49
+ Update with:
36
50
 
37
51
  ```sh
38
- uv tool install devnomads-cli # or: pipx install devnomads-cli
52
+ uv tool upgrade devnomads-cli
39
53
  ```
40
54
 
55
+ dncli checks PyPI at most once a day and tells you when a new version
56
+ is out, with the command to update the way you installed it. It only
57
+ does so on an interactive terminal, never in pipes, scripts or CI; set
58
+ `DN_NO_UPDATE_CHECK=1` to turn it off.
59
+
60
+ dncli also warns when the DevNomads API reports a major version it was
61
+ not built for, and tells you when the API no longer supports your
62
+ dncli version. Update dncli in both cases.
63
+
64
+ ### Shell completion
65
+
41
66
  Enable shell completion (bash, zsh, fish, PowerShell):
42
67
 
43
68
  ```sh
@@ -65,7 +90,8 @@ dncli containers show <id>
65
90
 
66
91
  Every DevNomads product has its own command group - `apps`,
67
92
  `buckets`, `containers`, `databases`, `domains`, `emails`,
68
- `forwards`, `proxies`, `servers`, `sites` and more. Explore with
93
+ `forwards`, `proxies`, `servers`, `sites` and more, plus `keys` for
94
+ your SSH keys and `jobs` for background work. Explore with
69
95
  `dncli --help` and `dncli <group> --help`.
70
96
 
71
97
  Commands accept any unambiguous prefix: `dncli e l` is `dncli emails
@@ -81,6 +107,18 @@ dncli dns records set example.com www A 192.0.2.1 --ttl 3600
81
107
  dncli dns records delete example.com www A
82
108
  ```
83
109
 
110
+ Anywhere a zone is expected you may pass the service id of a domain
111
+ instead of its name, so the ids from `dncli domains list` work here
112
+ too:
113
+
114
+ ```sh
115
+ dncli dns records list 42
116
+ ```
117
+
118
+ An id always means that domain's own zone. A delegated subzone such
119
+ as `foo.example.com` has no domain service of its own, so address it
120
+ by name.
121
+
84
122
  ## Moving a zone from another provider
85
123
 
86
124
  `dncli dns transfer` copies a zone from your current DNS provider
@@ -108,6 +146,17 @@ dncli services list --profile acme
108
146
  export DN_PROFILE=acme
109
147
  ```
110
148
 
149
+ Manage stored profiles:
150
+
151
+ ```sh
152
+ dncli configure list # profiles, with keys masked
153
+ dncli configure set-key acme # replace a profile's API key
154
+ dncli configure delete acme # remove a profile
155
+ ```
156
+
157
+ `set-key --stdin` reads the new key from standard input, and
158
+ `delete --yes` skips the question, for use in scripts.
159
+
111
160
  ## Scripting
112
161
 
113
162
  Output is a human-readable table on a terminal and JSON when piped,
@@ -131,9 +180,23 @@ fields, and reports an error on an unknown column name.
131
180
 
132
181
  Commands that take a service id also accept a unique entity name and
133
182
  resolve it for you, so `dncli domains show example.com` works as well
134
- as `dncli domains show 1234`. A purely numeric value is always treated
135
- as an id; an entity that matches more than one service is rejected, so
136
- pass the id when an entity is not unique.
183
+ as `dncli domains show 1234`. Names match regardless of case. A purely
184
+ numeric value is always treated as an id; an entity that matches more
185
+ than one service is rejected, so pass the id when an entity is not
186
+ unique. Other references, such as cluster, key or user ids, take the
187
+ numeric id only.
188
+
189
+ Some changes run in the background: creating a site, server, proxy or
190
+ domain, for example, queues one or more jobs in a batch. Such a command
191
+ prints the queued jobs and returns right away; add `--wait` to follow
192
+ the batch until every job has finished and see how each one ended.
193
+ With `--wait` the exit status is 0 only when every job completed. You
194
+ can look a batch up later with `dncli jobs batches show <batch_id>`.
195
+
196
+ The exit status is 0 when the API accepted the request and 1 for any
197
+ error response, so `dncli ... && next-step` is safe in scripts. Every
198
+ command takes `--timeout <seconds>` (default 300) for how long to wait
199
+ for the API, including the time spent waiting on `--wait`.
137
200
 
138
201
  In CI and pipelines, skip the credentials file and pass the key via
139
202
  the environment:
@@ -143,6 +206,22 @@ export DN_API_KEY=... # beats any stored profile
143
206
  dncli services list | jq -r '.[].entity'
144
207
  ```
145
208
 
209
+ ## AI agents
210
+
211
+ dncli ships with a skill that teaches AI coding agents how to use it
212
+ safely: where ids come from, what costs money or deletes data, and to
213
+ ask before changing anything. It works with Claude Code, Codex, Gemini
214
+ CLI, GitHub Copilot, Cursor and OpenCode:
215
+
216
+ ```sh
217
+ dncli skill install # every agent found on this machine
218
+ dncli skill install --agent codex # a specific agent; repeat for more
219
+ dncli skill install --project # into the current project instead
220
+ ```
221
+
222
+ Run it again after upgrading dncli to update the skill; `dncli skill
223
+ show` prints it.
224
+
146
225
  ## Certificates
147
226
 
148
227
  `dncli` issues Let's Encrypt certificates using the DNS-01 challenge:
@@ -15,4 +15,5 @@ tests/test_generate.py
15
15
  tests/test_generated_cli.py
16
16
  tests/test_helpers.py
17
17
  tests/test_hook.py
18
- tests/test_transfer.py
18
+ tests/test_transfer.py
19
+ tests/test_versions.py
@@ -1,5 +1,5 @@
1
- typer>=0.12
1
+ typer>=0.19
2
2
  httpx>=0.27
3
3
  rich>=13
4
4
  cryptography>=42
5
- devnomads[acme]>=0.5.0
5
+ devnomads[acme]>=0.6.0