hetzner-cli 2.0.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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +907 -0
  3. package/dist/auction/client.d.ts +4 -0
  4. package/dist/auction/client.js +103 -0
  5. package/dist/auction/commands.d.ts +2 -0
  6. package/dist/auction/commands.js +138 -0
  7. package/dist/auction/formatter.d.ts +3 -0
  8. package/dist/auction/formatter.js +87 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +39 -0
  11. package/dist/client.d.ts +2 -0
  12. package/dist/client.js +4 -0
  13. package/dist/cloud/client.d.ts +511 -0
  14. package/dist/cloud/client.js +706 -0
  15. package/dist/cloud/commands/certificate.d.ts +2 -0
  16. package/dist/cloud/commands/certificate.js +77 -0
  17. package/dist/cloud/commands/context.d.ts +2 -0
  18. package/dist/cloud/commands/context.js +78 -0
  19. package/dist/cloud/commands/datacenter.d.ts +2 -0
  20. package/dist/cloud/commands/datacenter.js +20 -0
  21. package/dist/cloud/commands/firewall.d.ts +2 -0
  22. package/dist/cloud/commands/firewall.js +77 -0
  23. package/dist/cloud/commands/floating-ip.d.ts +2 -0
  24. package/dist/cloud/commands/floating-ip.js +83 -0
  25. package/dist/cloud/commands/image.d.ts +2 -0
  26. package/dist/cloud/commands/image.js +60 -0
  27. package/dist/cloud/commands/index.d.ts +2 -0
  28. package/dist/cloud/commands/index.js +41 -0
  29. package/dist/cloud/commands/iso.d.ts +2 -0
  30. package/dist/cloud/commands/iso.js +22 -0
  31. package/dist/cloud/commands/load-balancer-type.d.ts +2 -0
  32. package/dist/cloud/commands/load-balancer-type.js +20 -0
  33. package/dist/cloud/commands/load-balancer.d.ts +2 -0
  34. package/dist/cloud/commands/load-balancer.js +177 -0
  35. package/dist/cloud/commands/location.d.ts +2 -0
  36. package/dist/cloud/commands/location.js +20 -0
  37. package/dist/cloud/commands/network.d.ts +2 -0
  38. package/dist/cloud/commands/network.js +96 -0
  39. package/dist/cloud/commands/placement-group.d.ts +2 -0
  40. package/dist/cloud/commands/placement-group.js +53 -0
  41. package/dist/cloud/commands/primary-ip.d.ts +2 -0
  42. package/dist/cloud/commands/primary-ip.js +83 -0
  43. package/dist/cloud/commands/server-type.d.ts +2 -0
  44. package/dist/cloud/commands/server-type.js +20 -0
  45. package/dist/cloud/commands/server.d.ts +2 -0
  46. package/dist/cloud/commands/server.js +260 -0
  47. package/dist/cloud/commands/ssh-key.d.ts +2 -0
  48. package/dist/cloud/commands/ssh-key.js +63 -0
  49. package/dist/cloud/commands/volume.d.ts +2 -0
  50. package/dist/cloud/commands/volume.js +92 -0
  51. package/dist/cloud/context.d.ts +28 -0
  52. package/dist/cloud/context.js +172 -0
  53. package/dist/cloud/formatter.d.ts +37 -0
  54. package/dist/cloud/formatter.js +413 -0
  55. package/dist/cloud/helpers.d.ts +18 -0
  56. package/dist/cloud/helpers.js +48 -0
  57. package/dist/cloud/types.d.ts +398 -0
  58. package/dist/cloud/types.js +5 -0
  59. package/dist/config.d.ts +1 -0
  60. package/dist/config.js +2 -0
  61. package/dist/formatter.d.ts +3 -0
  62. package/dist/formatter.js +6 -0
  63. package/dist/index.d.ts +10 -0
  64. package/dist/index.js +17 -0
  65. package/dist/robot/client.d.ts +256 -0
  66. package/dist/robot/client.js +656 -0
  67. package/dist/robot/commands/auth.d.ts +2 -0
  68. package/dist/robot/commands/auth.js +54 -0
  69. package/dist/robot/commands/boot.d.ts +2 -0
  70. package/dist/robot/commands/boot.js +72 -0
  71. package/dist/robot/commands/cancel.d.ts +2 -0
  72. package/dist/robot/commands/cancel.js +36 -0
  73. package/dist/robot/commands/failover.d.ts +2 -0
  74. package/dist/robot/commands/failover.js +42 -0
  75. package/dist/robot/commands/firewall.d.ts +2 -0
  76. package/dist/robot/commands/firewall.js +66 -0
  77. package/dist/robot/commands/index.d.ts +2 -0
  78. package/dist/robot/commands/index.js +36 -0
  79. package/dist/robot/commands/interactive.d.ts +2 -0
  80. package/dist/robot/commands/interactive.js +134 -0
  81. package/dist/robot/commands/ip.d.ts +2 -0
  82. package/dist/robot/commands/ip.js +52 -0
  83. package/dist/robot/commands/key.d.ts +2 -0
  84. package/dist/robot/commands/key.js +64 -0
  85. package/dist/robot/commands/order.d.ts +2 -0
  86. package/dist/robot/commands/order.js +33 -0
  87. package/dist/robot/commands/rdns.d.ts +2 -0
  88. package/dist/robot/commands/rdns.js +41 -0
  89. package/dist/robot/commands/reset.d.ts +2 -0
  90. package/dist/robot/commands/reset.js +77 -0
  91. package/dist/robot/commands/server.d.ts +2 -0
  92. package/dist/robot/commands/server.js +29 -0
  93. package/dist/robot/commands/storagebox.d.ts +2 -0
  94. package/dist/robot/commands/storagebox.js +116 -0
  95. package/dist/robot/commands/subnet.d.ts +2 -0
  96. package/dist/robot/commands/subnet.js +21 -0
  97. package/dist/robot/commands/traffic.d.ts +2 -0
  98. package/dist/robot/commands/traffic.js +20 -0
  99. package/dist/robot/commands/vswitch.d.ts +2 -0
  100. package/dist/robot/commands/vswitch.js +64 -0
  101. package/dist/robot/commands/wol.d.ts +2 -0
  102. package/dist/robot/commands/wol.js +20 -0
  103. package/dist/robot/formatter.d.ts +58 -0
  104. package/dist/robot/formatter.js +500 -0
  105. package/dist/robot/types.d.ts +352 -0
  106. package/dist/robot/types.js +5 -0
  107. package/dist/shared/config.d.ts +86 -0
  108. package/dist/shared/config.js +273 -0
  109. package/dist/shared/formatter.d.ts +29 -0
  110. package/dist/shared/formatter.js +118 -0
  111. package/dist/shared/helpers.d.ts +17 -0
  112. package/dist/shared/helpers.js +72 -0
  113. package/dist/shared/reference.d.ts +2 -0
  114. package/dist/shared/reference.js +626 -0
  115. package/dist/types.d.ts +75 -0
  116. package/dist/types.js +1 -0
  117. package/package.json +112 -0
package/README.md ADDED
@@ -0,0 +1,907 @@
1
+ <p align="center">
2
+ <img src="logo.svg" alt="hetzner-cli logo" width="128" height="128">
3
+ </p>
4
+
5
+ # hetzner-cli
6
+
7
+ [![npm version](https://badge.fury.io/js/hetzner-cli.svg)](https://www.npmjs.com/package/hetzner-cli)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ Unified CLI and Node.js library for Hetzner's three APIs:
11
+
12
+ - **Robot API** — dedicated server management (servers, IPs, firewall, storage boxes, etc.)
13
+ - **Cloud API** — cloud infrastructure (servers, networks, volumes, load balancers, etc.)
14
+ - **Auction API** — public server auction browser with rich filtering (no auth required)
15
+
16
+ ---
17
+
18
+ ## Table of Contents
19
+
20
+ - [Installation](#installation)
21
+ - [Quick Start](#quick-start)
22
+ - [Authentication](#authentication)
23
+ - [Robot API Credentials](#robot-api-credentials)
24
+ - [Cloud API Token](#cloud-api-token)
25
+ - [Auction API](#auction-api-no-auth)
26
+ - [CLI Reference](#cli-reference)
27
+ - [Global Options](#global-options)
28
+ - [Robot Commands](#robot-commands)
29
+ - [Cloud Commands](#cloud-commands)
30
+ - [Auction Commands](#auction-commands)
31
+ - [Built-in Reference](#built-in-reference)
32
+ - [Library Usage](#library-usage)
33
+ - [Robot Client](#robot-client)
34
+ - [Cloud Client](#cloud-client)
35
+ - [Auction Client](#auction-client)
36
+ - [Type Exports](#type-exports)
37
+ - [API Reference](#api-reference)
38
+ - [Configuration Files](#configuration-files)
39
+ - [Development](#development)
40
+ - [License](#license)
41
+
42
+ ---
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ # Global CLI
48
+ npm install -g hetzner-cli
49
+
50
+ # Or as a project dependency
51
+ npm install hetzner-cli
52
+ ```
53
+
54
+ Requires Node.js >= 18.0.0.
55
+
56
+ ---
57
+
58
+ ## Quick Start
59
+
60
+ ```bash
61
+ # Set up Robot API credentials (interactive)
62
+ hetzner auth login
63
+
64
+ # List your dedicated servers
65
+ hetzner server list
66
+
67
+ # Set up Cloud API context
68
+ hetzner cloud context create production
69
+ hetzner cloud context use production
70
+
71
+ # List your cloud servers
72
+ hetzner cloud server list
73
+
74
+ # Browse the server auction (no login needed)
75
+ hetzner auction list --max-price 60 --ecc --disk-type nvme --sort price
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Authentication
81
+
82
+ ### Robot API Credentials
83
+
84
+ The Robot API uses a **web service username and password** (separate from your main Hetzner login).
85
+
86
+ **To create credentials:**
87
+
88
+ 1. Go to [robot.hetzner.com](https://robot.hetzner.com)
89
+ 2. Navigate to **Settings > Web service settings**
90
+ 3. Create a new web service user
91
+
92
+ **Credential resolution order** (first match wins):
93
+
94
+ | Priority | Method | Details |
95
+ |----------|--------|---------|
96
+ | 1 | CLI flags | `--user <username> --password <password>` |
97
+ | 2 | Environment variables | `HETZNER_ROBOT_USER` and `HETZNER_ROBOT_PASSWORD` |
98
+ | 3 | System keychain | Stored by `hetzner auth login` (uses native keytar) |
99
+ | 4 | Config file | `~/.hetzner-cli/config.json` |
100
+ | 5 | Interactive prompt | Asks for username/password at runtime |
101
+
102
+ **Secure password passing** (keeps password out of shell history):
103
+
104
+ ```bash
105
+ # From stdin
106
+ echo "$PASSWORD" | hetzner server list -u myuser -p -
107
+
108
+ # With 1Password
109
+ op read "op://vault/item/password" | hetzner server list -u $(op read "op://vault/item/user") -p -
110
+
111
+ # From environment
112
+ export HETZNER_ROBOT_USER=myuser
113
+ export HETZNER_ROBOT_PASSWORD=mypassword
114
+ hetzner server list
115
+ ```
116
+
117
+ ### Cloud API Token
118
+
119
+ The Cloud API uses a **bearer token** from the Hetzner Cloud Console.
120
+
121
+ **To create a token:**
122
+
123
+ 1. Go to [console.hetzner.cloud](https://console.hetzner.cloud)
124
+ 2. Select your project
125
+ 3. Navigate to **Security > API Tokens**
126
+ 4. Generate a new token
127
+
128
+ **Token resolution order:**
129
+
130
+ | Priority | Method | Details |
131
+ |----------|--------|---------|
132
+ | 1 | CLI flag | `--token <token>` per command |
133
+ | 2 | Environment variable | `HETZNER_CLOUD_TOKEN` |
134
+ | 3 | Active context | Set via `hetzner cloud context use <name>` |
135
+
136
+ ```bash
137
+ # Set up a named context (saves token)
138
+ hetzner cloud context create production -t hcloud_xxxxxx
139
+
140
+ # Switch contexts
141
+ hetzner cloud context use production
142
+
143
+ # Or use inline
144
+ hetzner cloud server list --token hcloud_xxxxxx
145
+ ```
146
+
147
+ ### Auction API (No Auth)
148
+
149
+ The auction commands use Hetzner's public JSON endpoint. No credentials required.
150
+
151
+ ```bash
152
+ hetzner auction list
153
+ ```
154
+
155
+ ---
156
+
157
+ ## CLI Reference
158
+
159
+ ### Global Options
160
+
161
+ ```
162
+ -u, --user <username> Robot API username
163
+ -p, --password <password> Robot API password (use "-" to read from stdin)
164
+ --json Output raw JSON instead of formatted tables
165
+ -V, --version Show version number
166
+ -h, --help Show help for any command
167
+ ```
168
+
169
+ All commands support `--json` for machine-readable output. Pipe to `jq` for filtering:
170
+
171
+ ```bash
172
+ hetzner server list --json | jq '.[].server.server_ip'
173
+ hetzner auction list --max-price 50 --json | jq '.[].id'
174
+ ```
175
+
176
+ ### Robot Commands
177
+
178
+ Commands for managing Hetzner dedicated servers via the Robot API.
179
+
180
+ #### Authentication
181
+
182
+ ```bash
183
+ hetzner auth login # Interactive credential setup
184
+ hetzner auth logout # Clear saved credentials
185
+ hetzner auth status # Show current auth source
186
+ hetzner auth test # Verify credentials work
187
+ ```
188
+
189
+ #### Servers
190
+
191
+ ```bash
192
+ hetzner server list # List all servers
193
+ hetzner server get <server> # Server details (by ID or IP)
194
+ hetzner server rename <server> <name> # Rename a server
195
+ ```
196
+
197
+ #### Reset
198
+
199
+ ```bash
200
+ hetzner reset options [server] # Show available reset types
201
+ hetzner reset execute <servers...> # Reset servers
202
+ -t, --type <type> # sw|hw|man|power|power_long (default: sw)
203
+ -i, --interactive # Select type interactively
204
+ -y, --yes # Skip confirmation
205
+ ```
206
+
207
+ #### Boot Configuration
208
+
209
+ ```bash
210
+ hetzner boot status <server> # Show all boot config
211
+
212
+ # Rescue system
213
+ hetzner boot rescue activate <server> [-o linux|linuxold|vkvm] [-a 64|32] [-k <fingerprints...>]
214
+ hetzner boot rescue deactivate <server>
215
+ hetzner boot rescue last <server> # Show last rescue (includes password)
216
+
217
+ # Linux installation
218
+ hetzner boot linux options <server> # Show available distributions
219
+ hetzner boot linux activate <server> -d <dist> [-a 64|32] [-l en] [-k <fingerprints...>]
220
+ hetzner boot linux deactivate <server>
221
+ ```
222
+
223
+ #### IP & Networking
224
+
225
+ ```bash
226
+ hetzner ip list # List all IPs
227
+ hetzner ip get <ip> # IP details
228
+ hetzner ip update <ip> [--warnings true|false] [--hourly <mb>] [--daily <mb>] [--monthly <gb>]
229
+ hetzner ip mac get|generate|delete <ip> # Separate MAC management
230
+
231
+ hetzner subnet list # List subnets
232
+ hetzner subnet get <subnet>
233
+
234
+ hetzner failover list # List failover IPs
235
+ hetzner failover get <ip>
236
+ hetzner failover switch <failover-ip> <target-server-ip> [-y]
237
+ hetzner failover delete <ip> [-y]
238
+
239
+ hetzner rdns list # List reverse DNS entries
240
+ hetzner rdns get <ip>
241
+ hetzner rdns set <ip> <ptr> # Create/update
242
+ hetzner rdns delete <ip>
243
+ ```
244
+
245
+ #### SSH Keys
246
+
247
+ ```bash
248
+ hetzner key list # List all keys
249
+ hetzner key get <fingerprint>
250
+ hetzner key add <name> [-f <path>] [-d <data>]
251
+ hetzner key rename <fingerprint> <name>
252
+ hetzner key delete <fingerprint> [-y]
253
+ ```
254
+
255
+ #### Firewall
256
+
257
+ ```bash
258
+ hetzner firewall get <server> # Show config
259
+ hetzner firewall enable|disable <server>
260
+ hetzner firewall delete <server> [-y] # Delete all rules
261
+
262
+ hetzner firewall template list
263
+ hetzner firewall template get|delete <id>
264
+ ```
265
+
266
+ #### vSwitch
267
+
268
+ ```bash
269
+ hetzner vswitch list
270
+ hetzner vswitch get <id>
271
+ hetzner vswitch create <name> <vlan>
272
+ hetzner vswitch update <id> [-n <name>] [-v <vlan>]
273
+ hetzner vswitch delete <id> [-y] [--date <YYYY-MM-DD>]
274
+ hetzner vswitch add-server <vswitch-id> <server>
275
+ hetzner vswitch remove-server <vswitch-id> <server>
276
+ ```
277
+
278
+ #### Storage Box
279
+
280
+ ```bash
281
+ hetzner storagebox list # (alias: storage)
282
+ hetzner storagebox get <id>
283
+ hetzner storagebox update <id> [-n <name>] [--webdav|--samba|--ssh|--external|--zfs true|false]
284
+ hetzner storagebox reset-password <id>
285
+
286
+ # Snapshots
287
+ hetzner storagebox snapshot list|create|delete|revert <box-id> [<name>]
288
+
289
+ # Subaccounts
290
+ hetzner storagebox subaccount list <box-id>
291
+ hetzner storagebox subaccount create <box-id> <home-directory> [--samba|--ssh|--webdav|--external|--readonly true|false]
292
+ hetzner storagebox subaccount delete <box-id> <username> [-y]
293
+ ```
294
+
295
+ #### Traffic, WoL, Cancellation, Ordering
296
+
297
+ ```bash
298
+ hetzner traffic query [-i <ips...>] [-s <subnets...>] [--from <date>] [--to <date>] [-t day|month|year]
299
+ hetzner wol status|send <server>
300
+ hetzner cancel status|request|revoke <server>
301
+ hetzner order products|market|transactions
302
+ hetzner order transaction <id>
303
+ ```
304
+
305
+ #### Interactive Mode
306
+
307
+ ```bash
308
+ hetzner interactive # or: hetzner i
309
+ ```
310
+
311
+ Menu-driven interface for common operations (list servers, reset, rescue, failover, SSH keys).
312
+
313
+ ### Cloud Commands
314
+
315
+ All cloud commands live under `hetzner cloud <resource> <action>`. Add `--token <token>` to any command to override the active context.
316
+
317
+ #### Context Management
318
+
319
+ ```bash
320
+ hetzner cloud context create <name> [-t <token>]
321
+ hetzner cloud context use <name>
322
+ hetzner cloud context delete <name>
323
+ hetzner cloud context list
324
+ hetzner cloud context active
325
+ ```
326
+
327
+ #### Cloud Servers
328
+
329
+ ```bash
330
+ hetzner cloud server list [-l <label-selector>] [-n <name>] [-s <sort>] [--status <status>]
331
+ hetzner cloud server describe <id>
332
+ hetzner cloud server create --name <name> --type <type> --image <image> [--location <loc>] [--ssh-key <keys...>]
333
+ hetzner cloud server delete <id> [-y]
334
+ hetzner cloud server update <id> [--name <name>]
335
+
336
+ # Power management
337
+ hetzner cloud server poweron|poweroff|reboot|reset|shutdown <id>
338
+
339
+ # Maintenance
340
+ hetzner cloud server rebuild <id> --image <image>
341
+ hetzner cloud server change-type <id> --type <type> [--upgrade-disk]
342
+ hetzner cloud server enable-rescue <id> [--type linux64] [--ssh-key <ids...>]
343
+ hetzner cloud server disable-rescue <id>
344
+ hetzner cloud server enable-backup|disable-backup <id>
345
+ hetzner cloud server create-image <id> [--description <desc>]
346
+ hetzner cloud server attach-iso|detach-iso <id> [--iso <iso>]
347
+ hetzner cloud server reset-password <id>
348
+
349
+ # Networking
350
+ hetzner cloud server set-rdns <id> --ip <ip> --dns-ptr <ptr>
351
+ hetzner cloud server attach-to-network <id> --network <id> [--ip <ip>]
352
+ hetzner cloud server detach-from-network <id> --network <id>
353
+
354
+ # Protection & labels
355
+ hetzner cloud server enable-protection|disable-protection <id>
356
+ hetzner cloud server add-label <id> <key=value>
357
+ hetzner cloud server remove-label <id> <key>
358
+ hetzner cloud server request-console <id>
359
+ ```
360
+
361
+ #### Other Cloud Resources
362
+
363
+ Each follows the pattern: `hetzner cloud <resource> list|describe|create|delete`
364
+
365
+ ```bash
366
+ hetzner cloud network list|describe|create|delete
367
+ hetzner cloud firewall list|describe|create|delete
368
+ hetzner cloud floating-ip list|describe|create|delete
369
+ hetzner cloud primary-ip list|describe|create|delete
370
+ hetzner cloud volume list|describe|create|delete
371
+ hetzner cloud load-balancer list|describe|create|delete
372
+ hetzner cloud image list|describe|update|delete
373
+ hetzner cloud ssh-key list|describe|create|delete
374
+ hetzner cloud certificate list|describe|create|delete
375
+ hetzner cloud placement-group list|describe|create|delete
376
+
377
+ # Read-only reference data
378
+ hetzner cloud datacenter list|describe
379
+ hetzner cloud location list|describe
380
+ hetzner cloud server-type list|describe
381
+ hetzner cloud load-balancer-type list|describe
382
+ hetzner cloud iso list|describe
383
+ ```
384
+
385
+ ### Auction Commands
386
+
387
+ Browse Hetzner's server auction — no authentication required. Data is fetched from the public endpoint and filtered/sorted client-side.
388
+
389
+ ```bash
390
+ hetzner auction list [options] # List and filter auction servers
391
+ hetzner auction show <id> # Detailed view of a single server
392
+ ```
393
+
394
+ #### Auction List — Full Option Reference
395
+
396
+ **Price filters:**
397
+
398
+ ```bash
399
+ --min-price <n> # Minimum monthly price
400
+ --max-price <n> # Maximum monthly price
401
+ --max-hourly-price <n> # Maximum hourly price
402
+ --max-setup-price <n> # Maximum setup fee
403
+ --no-setup-fee # Only free setup (shorthand for --max-setup-price 0)
404
+ --fixed-price # Only fixed-price servers
405
+ --auction-only # Only auction servers (price decreases over time)
406
+ ```
407
+
408
+ **Hardware filters:**
409
+
410
+ ```bash
411
+ --cpu <text> # CPU model substring, case-insensitive (e.g. "Ryzen", "EPYC", "i7-6700")
412
+ --min-cpu-count <n> # Minimum CPU/socket count
413
+ --max-cpu-count <n> # Maximum CPU/socket count
414
+ --min-ram <gb> # Minimum RAM in GB
415
+ --max-ram <gb> # Maximum RAM in GB
416
+ --ecc # Only ECC RAM servers
417
+ ```
418
+
419
+ **Disk filters:**
420
+
421
+ ```bash
422
+ --min-disk-size <gb> # Minimum total disk capacity (sum of all drives)
423
+ --max-disk-size <gb> # Maximum total disk capacity
424
+ --min-disk-count <n> # Minimum number of physical drives
425
+ --max-disk-count <n> # Maximum number of physical drives
426
+ --disk-type <type> # Must have this disk type: nvme, sata, hdd
427
+ ```
428
+
429
+ **Network & feature filters:**
430
+
431
+ ```bash
432
+ --datacenter <text> # Datacenter substring, case-insensitive (e.g. "FSN", "HEL1-DC2", "NBG")
433
+ --min-bandwidth <mbit> # Minimum bandwidth in Mbit/s
434
+ --gpu # Only GPU servers
435
+ --inic # Only Intel NIC servers
436
+ --highio # Only high I/O servers
437
+ --specials <text> # Any special feature, substring match (e.g. "GPU", "ECC")
438
+ --search <text> # Free-text search across description
439
+ ```
440
+
441
+ **Sorting:**
442
+
443
+ ```bash
444
+ --sort <field> # Sort field (default: price). Choices:
445
+ # price, hourly, setup, ram, disk, disk_count,
446
+ # cpu, cpu_count, datacenter, bandwidth, next_reduce
447
+ --desc # Sort descending (default: ascending)
448
+ ```
449
+
450
+ **Output:**
451
+
452
+ ```bash
453
+ --currency <EUR|USD> # Price currency (default: EUR)
454
+ --limit <n> # Limit number of results
455
+ --json # Output raw JSON
456
+ ```
457
+
458
+ #### Auction Examples
459
+
460
+ ```bash
461
+ # Browse all servers, cheapest first
462
+ hetzner auction list
463
+
464
+ # Cheap AMD EPYC with NVMe + ECC in Helsinki
465
+ hetzner auction list --cpu epyc --disk-type nvme --ecc --datacenter HEL --sort price
466
+
467
+ # GPU servers under 150 EUR
468
+ hetzner auction list --gpu --max-price 150
469
+
470
+ # High-RAM servers with lots of drives
471
+ hetzner auction list --min-ram 256 --min-disk-count 4 --sort ram --desc
472
+
473
+ # Cheapest 10 fixed-price NVMe servers
474
+ hetzner auction list --fixed-price --disk-type nvme --sort price --limit 10
475
+
476
+ # Auction servers about to drop in price
477
+ hetzner auction list --auction-only --sort next_reduce --limit 20
478
+
479
+ # Export to JSON for scripting
480
+ hetzner auction list --max-price 60 --ecc --json | jq '.[].id'
481
+ ```
482
+
483
+ ### Built-in Reference
484
+
485
+ For a complete, structured reference optimized for LLM context windows:
486
+
487
+ ```bash
488
+ hetzner reference # or: hetzner ref
489
+ ```
490
+
491
+ This prints every command, option, and example in a structured plaintext format designed for easy parsing by language models. Pipe it into your LLM context:
492
+
493
+ ```bash
494
+ hetzner reference | pbcopy # Copy to clipboard (macOS)
495
+ hetzner reference > /tmp/hetzner-ref.txt # Save to file
496
+ ```
497
+
498
+ ---
499
+
500
+ ## Library Usage
501
+
502
+ ### Robot Client
503
+
504
+ ```typescript
505
+ import { HetznerRobotClient } from 'hetzner-cli';
506
+
507
+ const client = new HetznerRobotClient('username', 'password');
508
+
509
+ // List servers
510
+ const servers = await client.listServers();
511
+
512
+ // Get server details
513
+ const { server } = await client.getServer(123456);
514
+ console.log(server.server_name, server.server_ip);
515
+
516
+ // Reset a server
517
+ await client.resetServer(123456, 'sw');
518
+
519
+ // Activate rescue mode
520
+ const rescue = await client.activateRescue(123456, 'linux', 64, ['ssh-fingerprint']);
521
+ console.log('Password:', rescue.rescue.password);
522
+
523
+ // Linux installation
524
+ await client.activateLinux(123456, 'Debian-1210-bookworm-amd64-base', 64, 'en', ['ssh-fingerprint']);
525
+
526
+ // Failover
527
+ await client.switchFailover('1.2.3.4', '5.6.7.8');
528
+
529
+ // SSH keys
530
+ const keys = await client.listSshKeys();
531
+ await client.createSshKey('my-key', 'ssh-rsa AAAA...');
532
+
533
+ // Storage box
534
+ const boxes = await client.listStorageBoxes();
535
+ await client.createStorageBoxSnapshot(123);
536
+
537
+ // Firewall
538
+ const fw = await client.getFirewall(123456);
539
+ await client.updateFirewall(123456, 'active');
540
+ ```
541
+
542
+ ### Cloud Client
543
+
544
+ ```typescript
545
+ import { HetznerCloudClient } from 'hetzner-cli';
546
+
547
+ const client = new HetznerCloudClient('hcloud_xxxxxx');
548
+
549
+ // List servers
550
+ const { servers } = await client.listServers();
551
+
552
+ // Create a server
553
+ const result = await client.createServer({
554
+ name: 'web1',
555
+ server_type: 'cx22',
556
+ image: 'ubuntu-22.04',
557
+ location: 'fsn1',
558
+ });
559
+
560
+ // Networks
561
+ const { networks } = await client.listNetworks();
562
+ await client.createNetwork({ name: 'my-net', ip_range: '10.0.0.0/16' });
563
+
564
+ // Volumes
565
+ const { volumes } = await client.listVolumes();
566
+ await client.createVolume({ name: 'data', size: 50, location: 'fsn1' });
567
+
568
+ // Load Balancers
569
+ const { load_balancers } = await client.listLoadBalancers();
570
+
571
+ // Firewalls, Floating IPs, SSH Keys, Images, etc.
572
+ const { firewalls } = await client.listFirewalls();
573
+ const { floating_ips } = await client.listFloatingIps();
574
+ const { ssh_keys } = await client.listSshKeys();
575
+ ```
576
+
577
+ ### Auction Client
578
+
579
+ ```typescript
580
+ import { fetchAuctionServers, filterAuctionServers, sortAuctionServers } from 'hetzner-cli';
581
+
582
+ // Fetch all servers (EUR pricing)
583
+ const { server: servers } = await fetchAuctionServers('EUR');
584
+
585
+ // Filter: cheap ECC NVMe servers in Helsinki
586
+ const filtered = filterAuctionServers(servers, {
587
+ maxPrice: 60,
588
+ ecc: true,
589
+ diskType: 'nvme',
590
+ datacenter: 'HEL',
591
+ });
592
+
593
+ // Sort by price ascending
594
+ const sorted = sortAuctionServers(filtered, 'price', false);
595
+
596
+ console.log(`Found ${sorted.length} servers`);
597
+ for (const s of sorted) {
598
+ console.log(`${s.id}: ${s.cpu} | ${s.ram_size}GB | €${s.price}/mo | ${s.datacenter}`);
599
+ }
600
+ ```
601
+
602
+ ### Type Exports
603
+
604
+ ```typescript
605
+ import type {
606
+ // Robot types
607
+ Server, ServerDetails, Reset, ResetType,
608
+ RescueConfig, LinuxConfig,
609
+ IP, Subnet, Failover, Rdns,
610
+ SshKey, Firewall, FirewallRule,
611
+ VSwitch, StorageBox,
612
+ Traffic, Wol,
613
+ ServerProduct, ServerMarketProduct,
614
+
615
+ // Cloud types
616
+ CloudServer, CloudAction, CloudFirewall, CloudFirewallRule,
617
+ CloudSshKey, Network, NetworkSubnet, NetworkRoute,
618
+ FloatingIp, PrimaryIp, Volume, Image,
619
+ LoadBalancer, LoadBalancerType, LoadBalancerTarget, LoadBalancerService,
620
+ Certificate, PlacementGroup, Datacenter, Location,
621
+ ServerType, ISO, Labels,
622
+
623
+ // Auction types
624
+ AuctionServer, AuctionDiskData, AuctionIpPrice,
625
+ AuctionFilterOptions, AuctionResponse,
626
+ } from 'hetzner-cli';
627
+ ```
628
+
629
+ ---
630
+
631
+ ## API Reference
632
+
633
+ ### HetznerRobotClient Methods
634
+
635
+ #### Servers
636
+
637
+ | Method | Description |
638
+ |--------|-------------|
639
+ | `listServers()` | List all servers |
640
+ | `getServer(id)` | Get server details |
641
+ | `updateServerName(id, name)` | Rename server |
642
+ | `getCancellation(id)` | Get cancellation status |
643
+ | `cancelServer(id, date?, reasons?)` | Cancel server |
644
+ | `revokeCancellation(id)` | Revoke cancellation |
645
+
646
+ #### Reset
647
+
648
+ | Method | Description |
649
+ |--------|-------------|
650
+ | `listResetOptions()` | List all reset options |
651
+ | `getResetOptions(id)` | Get reset options for server |
652
+ | `resetServer(id, type?)` | Reset server (sw/hw/man/power/power_long) |
653
+
654
+ #### Boot
655
+
656
+ | Method | Description |
657
+ |--------|-------------|
658
+ | `getBootConfig(id)` | Get all boot configs |
659
+ | `activateRescue(id, os, arch?, keys?)` | Activate rescue |
660
+ | `deactivateRescue(id)` | Deactivate rescue |
661
+ | `getLastRescue(id)` | Get last rescue activation |
662
+ | `getLinux(id)` | Get available Linux distributions |
663
+ | `activateLinux(id, dist, arch?, lang?, keys?)` | Activate Linux install |
664
+ | `deactivateLinux(id)` | Deactivate Linux |
665
+ | `activateVnc(id, dist, arch?, lang?)` | Activate VNC install |
666
+ | `activateWindows(id, dist, lang?)` | Activate Windows install |
667
+
668
+ #### IPs & Networking
669
+
670
+ | Method | Description |
671
+ |--------|-------------|
672
+ | `listIps()` | List all IPs |
673
+ | `getIp(ip)` | Get IP details |
674
+ | `updateIp(ip, warnings?, hourly?, daily?, monthly?)` | Update IP settings |
675
+ | `generateIpMac(ip)` | Generate separate MAC |
676
+ | `deleteIpMac(ip)` | Delete MAC |
677
+ | `listSubnets()` | List subnets |
678
+ | `getSubnet(ip)` | Get subnet details |
679
+ | `listFailovers()` | List failover IPs |
680
+ | `getFailover(ip)` | Get failover details |
681
+ | `switchFailover(ip, targetIp)` | Switch routing |
682
+ | `deleteFailoverRouting(ip)` | Delete routing |
683
+ | `listRdns()` | List reverse DNS |
684
+ | `getRdns(ip)` | Get rDNS for IP |
685
+ | `createRdns(ip, ptr)` | Create/update rDNS |
686
+ | `deleteRdns(ip)` | Delete rDNS |
687
+
688
+ #### SSH Keys
689
+
690
+ | Method | Description |
691
+ |--------|-------------|
692
+ | `listSshKeys()` | List SSH keys |
693
+ | `getSshKey(fingerprint)` | Get key details |
694
+ | `createSshKey(name, data)` | Add SSH key |
695
+ | `updateSshKey(fingerprint, name)` | Rename key |
696
+ | `deleteSshKey(fingerprint)` | Delete key |
697
+
698
+ #### Firewall
699
+
700
+ | Method | Description |
701
+ |--------|-------------|
702
+ | `getFirewall(id)` | Get firewall config |
703
+ | `updateFirewall(id, status, rules?)` | Update firewall |
704
+ | `deleteFirewall(id)` | Delete all rules |
705
+ | `listFirewallTemplates()` | List templates |
706
+ | `getFirewallTemplate(id)` | Get template |
707
+ | `deleteFirewallTemplate(id)` | Delete template |
708
+
709
+ #### vSwitch
710
+
711
+ | Method | Description |
712
+ |--------|-------------|
713
+ | `listVSwitches()` | List vSwitches |
714
+ | `getVSwitch(id)` | Get details |
715
+ | `createVSwitch(name, vlan)` | Create |
716
+ | `updateVSwitch(id, name?, vlan?)` | Update |
717
+ | `deleteVSwitch(id, date?)` | Delete |
718
+ | `addServerToVSwitch(vswitchId, serverId)` | Add server |
719
+ | `removeServerFromVSwitch(vswitchId, serverId)` | Remove server |
720
+
721
+ #### Storage Box
722
+
723
+ | Method | Description |
724
+ |--------|-------------|
725
+ | `listStorageBoxes()` | List storage boxes |
726
+ | `getStorageBox(id)` | Get details |
727
+ | `updateStorageBox(id, ...)` | Update settings |
728
+ | `resetStorageBoxPassword(id)` | Reset password |
729
+ | `listStorageBoxSnapshots(id)` | List snapshots |
730
+ | `createStorageBoxSnapshot(id)` | Create snapshot |
731
+ | `deleteStorageBoxSnapshot(id, name)` | Delete snapshot |
732
+ | `revertStorageBoxSnapshot(id, name)` | Revert to snapshot |
733
+ | `listStorageBoxSubaccounts(id)` | List subaccounts |
734
+ | `createStorageBoxSubaccount(id, ...)` | Create subaccount |
735
+ | `deleteStorageBoxSubaccount(id, username)` | Delete subaccount |
736
+
737
+ #### Traffic, WoL, Ordering
738
+
739
+ | Method | Description |
740
+ |--------|-------------|
741
+ | `getTraffic(ips, subnets, from, to, type)` | Query traffic |
742
+ | `getWol(id)` | Get WoL status |
743
+ | `sendWol(id)` | Send Wake-on-LAN |
744
+ | `listServerProducts()` | List products |
745
+ | `listServerMarketProducts()` | List auction servers |
746
+ | `getServerTransaction(id)` | Get transaction |
747
+ | `listServerTransactions()` | List transactions |
748
+
749
+ ### HetznerCloudClient Methods
750
+
751
+ #### Context Management
752
+
753
+ | Function | Description |
754
+ |----------|-------------|
755
+ | `createContext(name, token)` | Create a named context (stores token) |
756
+ | `useContext(name)` | Switch active context |
757
+ | `deleteContext(name)` | Delete a context |
758
+ | `listContexts()` | List all contexts |
759
+ | `getActiveContext()` | Get active context name |
760
+ | `resolveToken(opts)` | Resolve token (flag > env > context) |
761
+
762
+ #### Servers
763
+
764
+ | Method | Description |
765
+ |--------|-------------|
766
+ | `listServers(params?)` | List cloud servers |
767
+ | `getServer(id)` | Get server details |
768
+ | `createServer(data)` | Create a server |
769
+ | `deleteServer(id)` | Delete a server |
770
+ | `updateServer(id, data)` | Update server name/labels |
771
+ | `poweronServer(id)` | Power on |
772
+ | `poweroffServer(id)` | Hard power off |
773
+ | `rebootServer(id)` | Soft reboot |
774
+ | `resetServer(id)` | Hard reset |
775
+ | `shutdownServer(id)` | Graceful shutdown |
776
+ | `rebuildServer(id, image)` | Rebuild with image |
777
+ | `changeServerType(id, type, disk?)` | Resize server |
778
+ | `enableRescue(id, type?, keys?)` | Enable rescue mode |
779
+ | `disableRescue(id)` | Disable rescue mode |
780
+ | `enableBackup(id)` | Enable backups |
781
+ | `disableBackup(id)` | Disable backups |
782
+ | `createImage(id, desc?, type?)` | Create snapshot |
783
+ | `attachIso(id, iso)` | Attach ISO |
784
+ | `detachIso(id)` | Detach ISO |
785
+ | `resetPassword(id)` | Reset root password |
786
+ | `setRdns(id, ip, ptr)` | Set reverse DNS |
787
+ | `changeProtection(id, opts)` | Change protection |
788
+ | `requestConsole(id)` | Get VNC console URL |
789
+ | `attachToNetwork(id, network, ip?)` | Attach to network |
790
+ | `detachFromNetwork(id, network)` | Detach from network |
791
+
792
+ #### Networks
793
+
794
+ | Method | Description |
795
+ |--------|-------------|
796
+ | `listNetworks()` | List networks |
797
+ | `getNetwork(id)` | Get network details |
798
+ | `createNetwork(data)` | Create a network |
799
+ | `deleteNetwork(id)` | Delete a network |
800
+ | `addSubnet(id, subnet)` | Add subnet |
801
+ | `deleteSubnet(id, subnet)` | Delete subnet |
802
+ | `addRoute(id, route)` | Add route |
803
+ | `deleteRoute(id, route)` | Delete route |
804
+ | `changeIpRange(id, range)` | Change IP range |
805
+
806
+ #### Firewalls, IPs, Volumes, Load Balancers
807
+
808
+ | Method | Description |
809
+ |--------|-------------|
810
+ | `listFirewalls()` / `getFirewall(id)` / `createFirewall(data)` / `deleteFirewall(id)` | Firewall CRUD |
811
+ | `listFloatingIps()` / `getFloatingIp(id)` / `createFloatingIp(data)` / `deleteFloatingIp(id)` | Floating IP CRUD |
812
+ | `listPrimaryIps()` / `getPrimaryIp(id)` / `createPrimaryIp(data)` / `deletePrimaryIp(id)` | Primary IP CRUD |
813
+ | `listVolumes()` / `getVolume(id)` / `createVolume(data)` / `deleteVolume(id)` | Volume CRUD |
814
+ | `listLoadBalancers()` / `getLoadBalancer(id)` / `createLoadBalancer(data)` / `deleteLoadBalancer(id)` | Load Balancer CRUD |
815
+ | `listImages()` / `getImage(id)` / `updateImage(id, data)` / `deleteImage(id)` | Image management |
816
+ | `listSshKeys()` / `getSshKey(id)` / `createSshKey(data)` / `deleteSshKey(id)` | SSH key CRUD |
817
+ | `listCertificates()` / `getCertificate(id)` / `createCertificate(data)` / `deleteCertificate(id)` | Certificate CRUD |
818
+ | `listPlacementGroups()` / `getPlacementGroup(id)` / `createPlacementGroup(data)` / `deletePlacementGroup(id)` | Placement group CRUD |
819
+
820
+ #### Reference Data (Read-Only)
821
+
822
+ | Method | Description |
823
+ |--------|-------------|
824
+ | `listDatacenters()` / `getDatacenter(id)` | Datacenter info |
825
+ | `listLocations()` / `getLocation(id)` | Location info |
826
+ | `listServerTypes()` / `getServerType(id)` | Server type info |
827
+ | `listLoadBalancerTypes()` / `getLoadBalancerType(id)` | LB type info |
828
+ | `listIsos(params?)` / `getIso(id)` | ISO image info |
829
+
830
+ ### Auction Functions
831
+
832
+ | Function | Description |
833
+ |----------|-------------|
834
+ | `fetchAuctionServers(currency?)` | Fetch all servers from public API (EUR or USD) |
835
+ | `filterAuctionServers(servers, filters)` | Apply filter criteria to server array |
836
+ | `sortAuctionServers(servers, field, desc)` | Sort servers by field |
837
+
838
+ ---
839
+
840
+ ## Configuration Files
841
+
842
+ | File | Purpose |
843
+ |------|---------|
844
+ | `~/.hetzner-cli/config.json` | Robot API credentials (file-based fallback) |
845
+ | `~/.hetzner-cli/cloud-contexts.json` | Cloud API contexts and tokens |
846
+
847
+ System keychain (via keytar):
848
+
849
+ | Key | Value |
850
+ |-----|-------|
851
+ | Service | `hetzner-cli` |
852
+ | Account | `credentials` |
853
+
854
+ Environment variables:
855
+
856
+ | Variable | Purpose |
857
+ |----------|---------|
858
+ | `HETZNER_ROBOT_USER` | Robot API username |
859
+ | `HETZNER_ROBOT_PASSWORD` | Robot API password |
860
+ | `HETZNER_CLOUD_TOKEN` | Cloud API token (overrides active context) |
861
+
862
+ ---
863
+
864
+ ## Development
865
+
866
+ ```bash
867
+ npm install # Install dependencies
868
+ npm run build # Compile TypeScript
869
+ npm test # Run tests (740 tests across 12 suites)
870
+ npm run test:coverage # Run with coverage report
871
+ npm run test:watch # Watch mode
872
+ ```
873
+
874
+ ### Project Structure
875
+
876
+ ```
877
+ src/
878
+ ├── cli.ts # CLI entry point
879
+ ├── index.ts # Library exports
880
+ ├── shared/
881
+ │ ├── config.ts # Credential management
882
+ │ ├── formatter.ts # Colors, tables, output formatting
883
+ │ ├── helpers.ts # asyncAction, output, confirmAction
884
+ │ └── reference.ts # Built-in reference documentation
885
+ ├── robot/
886
+ │ ├── client.ts # Robot API client (HetznerRobotClient)
887
+ │ ├── types.ts # Robot type definitions
888
+ │ ├── formatter.ts # Robot-specific formatters
889
+ │ └── commands/ # CLI command modules (17 files)
890
+ ├── cloud/
891
+ │ ├── client.ts # Cloud API client
892
+ │ ├── context.ts # Context/token management
893
+ │ ├── types.ts # Cloud type definitions
894
+ │ ├── formatter.ts # Cloud-specific formatters
895
+ │ ├── helpers.ts # Cloud action wrappers
896
+ │ └── commands/ # CLI command modules (17 files)
897
+ └── auction/
898
+ ├── client.ts # Auction fetch/filter/sort
899
+ ├── formatter.ts # Auction formatters
900
+ └── commands.ts # Auction CLI commands
901
+ ```
902
+
903
+ ---
904
+
905
+ ## License
906
+
907
+ MIT