bsm-cli 1.6.0b4__tar.gz → 1.7.0b2__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 (59) hide show
  1. bsm_cli-1.7.0b2/PKG-INFO +254 -0
  2. bsm_cli-1.7.0b2/README.md +221 -0
  3. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/pyproject.toml +13 -8
  4. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/__main__.py +25 -5
  5. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/account.py +10 -8
  6. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/addon.py +40 -32
  7. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/allowlist.py +41 -25
  8. bsm_cli-1.7.0b2/src/bsm_cli/api.py +400 -0
  9. bsm_cli-1.7.0b2/src/bsm_cli/appearance.py +51 -0
  10. bsm_cli-1.7.0b2/src/bsm_cli/auth.py +141 -0
  11. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/backup.py +65 -48
  12. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/bans.py +15 -17
  13. bsm_cli-1.7.0b2/src/bsm_cli/completion.py +110 -0
  14. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/config.py +34 -7
  15. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/content.py +5 -3
  16. bsm_cli-1.7.0b2/src/bsm_cli/decorators.py +206 -0
  17. bsm_cli-1.7.0b2/src/bsm_cli/interaction.py +26 -0
  18. bsm_cli-1.7.0b2/src/bsm_cli/live.py +109 -0
  19. bsm_cli-1.7.0b2/src/bsm_cli/main_menus.py +275 -0
  20. bsm_cli-1.7.0b2/src/bsm_cli/manager.py +307 -0
  21. bsm_cli-1.7.0b2/src/bsm_cli/menu_registry.py +259 -0
  22. bsm_cli-1.7.0b2/src/bsm_cli/output.py +179 -0
  23. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/permissions.py +32 -20
  24. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/player.py +8 -12
  25. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/plugins.py +102 -46
  26. bsm_cli-1.7.0b2/src/bsm_cli/presentation.py +52 -0
  27. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/properties.py +30 -21
  28. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/server.py +119 -158
  29. bsm_cli-1.7.0b2/src/bsm_cli/settings_editor.py +234 -0
  30. bsm_cli-1.7.0b2/src/bsm_cli/system.py +113 -0
  31. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/users.py +28 -25
  32. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/world.py +36 -33
  33. bsm_cli-1.7.0b2/src/bsm_cli.egg-info/PKG-INFO +254 -0
  34. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli.egg-info/SOURCES.txt +19 -1
  35. bsm_cli-1.7.0b2/src/bsm_cli.egg-info/requires.txt +15 -0
  36. bsm_cli-1.7.0b2/src/bsm_cli.egg-info/scm_file_list.json +45 -0
  37. bsm_cli-1.7.0b2/tests/test_cli_auth.py +124 -0
  38. bsm_cli-1.7.0b2/tests/test_cli_commands.py +436 -0
  39. bsm_cli-1.7.0b2/tests/test_cli_menus.py +349 -0
  40. bsm_cli-1.7.0b2/tests/test_cli_openapi.py +460 -0
  41. bsm_cli-1.7.0b2/tests/test_cli_websocket.py +253 -0
  42. bsm_cli-1.7.0b2/tests/test_interaction.py +37 -0
  43. bsm_cli-1.7.0b2/tests/test_live.py +109 -0
  44. bsm_cli-1.7.0b2/tests/test_settings_editor.py +103 -0
  45. bsm_cli-1.6.0b4/PKG-INFO +0 -77
  46. bsm_cli-1.6.0b4/README.md +0 -46
  47. bsm_cli-1.6.0b4/src/bsm_cli/auth.py +0 -106
  48. bsm_cli-1.6.0b4/src/bsm_cli/decorators.py +0 -138
  49. bsm_cli-1.6.0b4/src/bsm_cli/main_menus.py +0 -293
  50. bsm_cli-1.6.0b4/src/bsm_cli/system.py +0 -142
  51. bsm_cli-1.6.0b4/src/bsm_cli.egg-info/PKG-INFO +0 -77
  52. bsm_cli-1.6.0b4/src/bsm_cli.egg-info/requires.txt +0 -14
  53. bsm_cli-1.6.0b4/tests/test_cli_websocket.py +0 -147
  54. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/LICENSE +0 -0
  55. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/setup.cfg +0 -0
  56. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli/__init__.py +0 -0
  57. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli.egg-info/dependency_links.txt +0 -0
  58. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli.egg-info/entry_points.txt +0 -0
  59. {bsm_cli-1.6.0b4 → bsm_cli-1.7.0b2}/src/bsm_cli.egg-info/top_level.txt +0 -0
@@ -0,0 +1,254 @@
1
+ Metadata-Version: 2.4
2
+ Name: bsm-cli
3
+ Version: 1.7.0b2
4
+ Summary: A CLI for managing Bedrock servers via BSM API
5
+ Author-email: DMedina559 <dmedina559-github@outlook.com>
6
+ Project-URL: Homepage, https://github.com/DMedina559/bsm-api-client
7
+ Keywords: minecraft,bedrock,server,manager,cli
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Intended Audience :: Developers
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: click<8.6,>=8.2.0
19
+ Requires-Dist: questionary<2.2,>=2.1.0
20
+ Requires-Dist: rich<16,>=13.9
21
+ Requires-Dist: bsm-api-client<1.8,>=1.7.0b1
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest<9.2,>=8.4.0; extra == "dev"
24
+ Requires-Dist: pytest-mock<3.17,>=3.14.0; extra == "dev"
25
+ Requires-Dist: pytest-asyncio<1.5,>=1.1.0; extra == "dev"
26
+ Requires-Dist: black<26.11,>=25.1.0; extra == "dev"
27
+ Requires-Dist: flake8<7.5,>=7.3.0; extra == "dev"
28
+ Requires-Dist: isort<9.1,>=5.13.0; extra == "dev"
29
+ Requires-Dist: mypy<2.4,>=1.10.0; extra == "dev"
30
+ Requires-Dist: bedrock-server-manager<4.1,>=4.0.0b5; extra == "dev"
31
+ Requires-Dist: pre-commit<4.7,>=4.6.0; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ <div style="text-align: center;">
35
+ <img src="https://raw.githubusercontent.com/DMedina559/bsm-frontend/main/frontend/public/image/icon/favicon.svg" alt="BSM Logo" width="150">
36
+ </div>
37
+
38
+ # bsm-cli
39
+
40
+ <p align="center">
41
+ <a href="https://github.com/DMedina559/bsm-api-client/releases">
42
+ <img alt="Stable" src="https://img.shields.io/github/v/release/DMedina559/bsm-api-client?label=Stable&color=blue">
43
+ </a>
44
+ <a href="https://github.com/DMedina559/bsm-api-client/releases">
45
+ <img alt="Pre-Release" src="https://img.shields.io/github/v/release/DMedina559/bsm-api-client?include_prereleases&label=Pre-Release&color=red">
46
+ </a>
47
+ <a href="https://github.com/DMedina559/bsm-api-client/actions">
48
+ <img alt="Tests" src="https://img.shields.io/github/actions/workflow/status/DMedina559/bsm-api-client/build-test.yml?label=Tests&event=push">
49
+ </a>
50
+ </p>
51
+
52
+ ## Introduction
53
+
54
+ `bsm-cli` is a command-line interface tool for managing Minecraft Bedrock Dedicated Servers via the Bedrock Server Manager API.
55
+
56
+ ## Features
57
+
58
+ * Full CLI interface using `click` and `questionary`.
59
+ * Interactive menus for server management.
60
+ * Realtime server state updates via WebSocket.
61
+ * Seamlessly manages configuration for server and backups.
62
+
63
+ ## Installation
64
+
65
+ Install the library using pip:
66
+
67
+ ```bash
68
+ pip install bsm-cli
69
+ ```
70
+
71
+ ## Quick Start
72
+
73
+ You can invoke the CLI using:
74
+
75
+ ```bash
76
+ bsm-cli
77
+ ```
78
+
79
+ Which will trigger the interactive menu allowing you to manage and configure your Bedrock Dedicated Servers.
80
+
81
+ ## OpenAPI commands
82
+
83
+ The CLI targets BSM's typed-contract branch and stable operation IDs. Curated commands remain available;
84
+ new server/plugin HTTP endpoints can be inspected and called immediately:
85
+
86
+ ```bash
87
+ bsm-cli api info
88
+ bsm-cli api schema
89
+ bsm-cli api operations --tag 'Server Management'
90
+ bsm-cli api operation start_server
91
+ bsm-cli api call start_server --param server_name=survival
92
+ bsm-cli api diff --against-generated
93
+ bsm-cli api diff --against saved-openapi.json
94
+ bsm-cli api refresh
95
+ bsm-cli api export saved-openapi.json
96
+ bsm-cli plugin operations discord
97
+ bsm-cli plugin call discord discord_status
98
+ ```
99
+
100
+ `--param NAME=VALUE` uses declared path/query/header parameter types. Boolean values
101
+ use `true`/`false`; arrays and objects use JSON. Missing, duplicate, and unknown
102
+ parameters fail before invoking an endpoint. Cookie parameters are not currently supported by the generic CLI. Query arrays and objects honor form `explode`, deepObject, spaceDelimited and pipeDelimited serialization.
103
+
104
+ Request-body options:
105
+
106
+ ```bash
107
+ bsm-cli api call send_command --param server_name=survival --json '{"command":"list"}'
108
+ bsm-cli api call login --form username=admin --form password=example
109
+ bsm-cli api call plugin_upload --file file=./addon.mcaddon
110
+ ```
111
+
112
+ The global `--json` flag precedes the command; the call-specific `--json` option
113
+ is a request body and follows the operation:
114
+
115
+ ```bash
116
+ bsm-cli --json api call send_command --param server_name=survival --json '{"command":"list"}'
117
+ bsm-cli --json server list
118
+ ```
119
+
120
+ JSON output contains structured API responses, without human progress/table text.
121
+ Commands making multiple calls return an ordered array of responses unless they
122
+ provide their own result. Errors are JSON objects on stderr. Resource monitoring
123
+ returns one snapshot in JSON mode; `server list --loop` requires human output.
124
+ Interactive commands may still prompt; supply their options for scripting.
125
+
126
+ | Exit status | Meaning |
127
+ | --- | --- |
128
+ | 0 | Success |
129
+ | 1 | API/server or unexpected failure |
130
+ | 2 | Usage or input validation |
131
+ | 3 | Authentication/authorization |
132
+ | 4 | Connection failure |
133
+ | 5 | Missing resource/operation |
134
+
135
+ Human discovery output uses tables. Interactive menus browse Click's registered
136
+ command groups and add a Plugin API menu only when the live schema has plugin
137
+ operations. `api refresh` caches operation/plugin/parameter completion; on servers
138
+ advertising `list_servers`, it also caches server-name completion. Completion does
139
+ not make network requests and ignores caches belonging to another configured URL.
140
+
141
+ Enable Click shell completion, for example in Bash:
142
+
143
+ ```bash
144
+ eval "$(_BSM_CLI_COMPLETE=bash_source bsm-cli)"
145
+ ```
146
+
147
+ For Python client examples and OpenAPI discovery, see the
148
+ [API usage guide](../../docs/API_DOCS.md).
149
+
150
+
151
+ ## Content and task behavior
152
+
153
+ `world install --file`, `addon install --file`, and `backup restore --file` select
154
+ files already present on the backend. They do not upload a local file. Examples:
155
+
156
+ ```bash
157
+ bsm-cli world install --server survival --file MyWorld.mcworld --yes
158
+ bsm-cli addon install --server survival --file Example.mcaddon
159
+ bsm-cli backup restore --server survival --file MyWorld_backup_20261007_120000.mcworld
160
+ bsm-cli backup restore --server survival --file custom-backup.zip --type world
161
+ ```
162
+
163
+ `content upload LOCAL_FILE` works only when the server advertises an
164
+ `upload_content` operation. The current backend does not advertise one.
165
+ Place content files in the backend's content directories, then select them by name.
166
+
167
+ Background commands subscribe to the task's WebSocket topic and check its REST
168
+ snapshot after subscribing, covering tasks that finish before monitoring starts.
169
+ A silent or disconnected WebSocket falls back to REST polling. Failed and
170
+ cancelled tasks exit with a nonzero status.
171
+
172
+ Registry menus accept a single value or a JSON array for repeated options and
173
+ variadic arguments, preserving spaces in player names and paths. Password inputs
174
+ are hidden and password confirmations are checked.
175
+
176
+ ## Contract review and streaming downloads
177
+
178
+ ```bash
179
+ bsm-cli api operations --method GET --plugin example
180
+ bsm-cli --json api diff --against saved-openapi.json --details
181
+ bsm-cli api download example_download ./archive.zip --param name=example
182
+ ```
183
+
184
+ `api download` streams a discovered GET operation and replaces the destination
185
+ only after a complete download. JSON mode returns the output path and byte count.
186
+ `api diff --details` includes conservative compatibility classifications alongside
187
+ the usual added/removed/changed lists. Invalid saved schemas produce input errors.
188
+
189
+ Completion validates cached contracts and fingerprints and rejects metadata for a
190
+ different backend URL or recorded user. Malformed caches yield no suggestions.
191
+ Boolean and enum parameter values have completion suggestions. Interactive command
192
+ menus can select live operation IDs and return to the menu after each action.
193
+
194
+
195
+ ## Manager dashboard and settings
196
+
197
+ The home menu opens Overview, Monitor, and Operations directly. Select a server
198
+ to see its lifecycle, configuration, backup, and world actions on one screen.
199
+ Menus with a list display it automatically before offering actions. Operations
200
+ can be selected directly to inspect their outcomes.
201
+
202
+ These views are also available without entering the menu:
203
+
204
+ ```bash
205
+ bsm-cli auth setup --base-url http://localhost:11325
206
+ bsm-cli overview
207
+ bsm-cli health
208
+ bsm-cli monitor
209
+ bsm-cli monitor --once --unit GB
210
+ bsm-cli operations list
211
+ bsm-cli operations show TASK_ID
212
+ bsm-cli audit
213
+ bsm-cli logs --topic app_logs
214
+ ```
215
+
216
+ Application commands use their direct paths (`overview`, `monitor`, `settings`,
217
+ `health`, `logs`, `audit`, and `operations`). Server monitoring and settings live
218
+ under `server`; the duplicate `manager` and `system` groups have been removed.
219
+ Use `bsm-cli server monitor --server survival` for a single server.
220
+
221
+ Overview, monitoring, and operation lists use structured terminal tables. In an
222
+ interactive menu, Ctrl+C stops the active live view and returns to its menu;
223
+ standalone live commands still exit normally on Ctrl+C.
224
+
225
+ Live views reconnect automatically and reconcile WebSocket updates with HTTP
226
+ snapshots. Revision checks prevent older snapshots from replacing newer state.
227
+ Application monitoring separates app and system metrics and shows recent CPU
228
+ history. Log history returns a cursor for requesting older pages.
229
+
230
+ ```bash
231
+ bsm-cli settings
232
+ bsm-cli server settings --server survival
233
+ bsm-cli plugin settings edit backup_on_start
234
+ bsm-cli plugin settings show backup_on_start
235
+ bsm-cli plugin settings set backup_on_start settings.json
236
+ bsm-cli appearance set --memory-unit GB --density compact
237
+ ```
238
+
239
+ The shared settings editor reviews changes before saving. Plugin schemas provide
240
+ field descriptions, bounds, enums, and server checklists; plugins without settings
241
+ have no Settings action. Credential fields are masked. Application and server
242
+ settings infer field types from their current values because those endpoints do
243
+ not advertise an editable settings schema. Backend validation remains authoritative.
244
+
245
+ An editor refuses to save if its settings changed in another session. Global and
246
+ server settings are saved one key at a time; the CLI prints each successfully saved
247
+ key so partial updates remain visible if a later request fails. Plugins use one
248
+ request to replace their settings. `--json` continues to return structured API data
249
+ for noninteractive commands; use `plugin settings set` for scripted updates.
250
+
251
+ Use `bsm-cli auth login --remember-me` to request the backend-configured longer
252
+ token lifetime. Interactive login also offers this choice, defaulting to off.
253
+ The CLI saves the issued token without storing your password; the flag cannot
254
+ extend the lifetime of an existing token supplied with `--token`.
@@ -0,0 +1,221 @@
1
+ <div style="text-align: center;">
2
+ <img src="https://raw.githubusercontent.com/DMedina559/bsm-frontend/main/frontend/public/image/icon/favicon.svg" alt="BSM Logo" width="150">
3
+ </div>
4
+
5
+ # bsm-cli
6
+
7
+ <p align="center">
8
+ <a href="https://github.com/DMedina559/bsm-api-client/releases">
9
+ <img alt="Stable" src="https://img.shields.io/github/v/release/DMedina559/bsm-api-client?label=Stable&color=blue">
10
+ </a>
11
+ <a href="https://github.com/DMedina559/bsm-api-client/releases">
12
+ <img alt="Pre-Release" src="https://img.shields.io/github/v/release/DMedina559/bsm-api-client?include_prereleases&label=Pre-Release&color=red">
13
+ </a>
14
+ <a href="https://github.com/DMedina559/bsm-api-client/actions">
15
+ <img alt="Tests" src="https://img.shields.io/github/actions/workflow/status/DMedina559/bsm-api-client/build-test.yml?label=Tests&event=push">
16
+ </a>
17
+ </p>
18
+
19
+ ## Introduction
20
+
21
+ `bsm-cli` is a command-line interface tool for managing Minecraft Bedrock Dedicated Servers via the Bedrock Server Manager API.
22
+
23
+ ## Features
24
+
25
+ * Full CLI interface using `click` and `questionary`.
26
+ * Interactive menus for server management.
27
+ * Realtime server state updates via WebSocket.
28
+ * Seamlessly manages configuration for server and backups.
29
+
30
+ ## Installation
31
+
32
+ Install the library using pip:
33
+
34
+ ```bash
35
+ pip install bsm-cli
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ You can invoke the CLI using:
41
+
42
+ ```bash
43
+ bsm-cli
44
+ ```
45
+
46
+ Which will trigger the interactive menu allowing you to manage and configure your Bedrock Dedicated Servers.
47
+
48
+ ## OpenAPI commands
49
+
50
+ The CLI targets BSM's typed-contract branch and stable operation IDs. Curated commands remain available;
51
+ new server/plugin HTTP endpoints can be inspected and called immediately:
52
+
53
+ ```bash
54
+ bsm-cli api info
55
+ bsm-cli api schema
56
+ bsm-cli api operations --tag 'Server Management'
57
+ bsm-cli api operation start_server
58
+ bsm-cli api call start_server --param server_name=survival
59
+ bsm-cli api diff --against-generated
60
+ bsm-cli api diff --against saved-openapi.json
61
+ bsm-cli api refresh
62
+ bsm-cli api export saved-openapi.json
63
+ bsm-cli plugin operations discord
64
+ bsm-cli plugin call discord discord_status
65
+ ```
66
+
67
+ `--param NAME=VALUE` uses declared path/query/header parameter types. Boolean values
68
+ use `true`/`false`; arrays and objects use JSON. Missing, duplicate, and unknown
69
+ parameters fail before invoking an endpoint. Cookie parameters are not currently supported by the generic CLI. Query arrays and objects honor form `explode`, deepObject, spaceDelimited and pipeDelimited serialization.
70
+
71
+ Request-body options:
72
+
73
+ ```bash
74
+ bsm-cli api call send_command --param server_name=survival --json '{"command":"list"}'
75
+ bsm-cli api call login --form username=admin --form password=example
76
+ bsm-cli api call plugin_upload --file file=./addon.mcaddon
77
+ ```
78
+
79
+ The global `--json` flag precedes the command; the call-specific `--json` option
80
+ is a request body and follows the operation:
81
+
82
+ ```bash
83
+ bsm-cli --json api call send_command --param server_name=survival --json '{"command":"list"}'
84
+ bsm-cli --json server list
85
+ ```
86
+
87
+ JSON output contains structured API responses, without human progress/table text.
88
+ Commands making multiple calls return an ordered array of responses unless they
89
+ provide their own result. Errors are JSON objects on stderr. Resource monitoring
90
+ returns one snapshot in JSON mode; `server list --loop` requires human output.
91
+ Interactive commands may still prompt; supply their options for scripting.
92
+
93
+ | Exit status | Meaning |
94
+ | --- | --- |
95
+ | 0 | Success |
96
+ | 1 | API/server or unexpected failure |
97
+ | 2 | Usage or input validation |
98
+ | 3 | Authentication/authorization |
99
+ | 4 | Connection failure |
100
+ | 5 | Missing resource/operation |
101
+
102
+ Human discovery output uses tables. Interactive menus browse Click's registered
103
+ command groups and add a Plugin API menu only when the live schema has plugin
104
+ operations. `api refresh` caches operation/plugin/parameter completion; on servers
105
+ advertising `list_servers`, it also caches server-name completion. Completion does
106
+ not make network requests and ignores caches belonging to another configured URL.
107
+
108
+ Enable Click shell completion, for example in Bash:
109
+
110
+ ```bash
111
+ eval "$(_BSM_CLI_COMPLETE=bash_source bsm-cli)"
112
+ ```
113
+
114
+ For Python client examples and OpenAPI discovery, see the
115
+ [API usage guide](../../docs/API_DOCS.md).
116
+
117
+
118
+ ## Content and task behavior
119
+
120
+ `world install --file`, `addon install --file`, and `backup restore --file` select
121
+ files already present on the backend. They do not upload a local file. Examples:
122
+
123
+ ```bash
124
+ bsm-cli world install --server survival --file MyWorld.mcworld --yes
125
+ bsm-cli addon install --server survival --file Example.mcaddon
126
+ bsm-cli backup restore --server survival --file MyWorld_backup_20261007_120000.mcworld
127
+ bsm-cli backup restore --server survival --file custom-backup.zip --type world
128
+ ```
129
+
130
+ `content upload LOCAL_FILE` works only when the server advertises an
131
+ `upload_content` operation. The current backend does not advertise one.
132
+ Place content files in the backend's content directories, then select them by name.
133
+
134
+ Background commands subscribe to the task's WebSocket topic and check its REST
135
+ snapshot after subscribing, covering tasks that finish before monitoring starts.
136
+ A silent or disconnected WebSocket falls back to REST polling. Failed and
137
+ cancelled tasks exit with a nonzero status.
138
+
139
+ Registry menus accept a single value or a JSON array for repeated options and
140
+ variadic arguments, preserving spaces in player names and paths. Password inputs
141
+ are hidden and password confirmations are checked.
142
+
143
+ ## Contract review and streaming downloads
144
+
145
+ ```bash
146
+ bsm-cli api operations --method GET --plugin example
147
+ bsm-cli --json api diff --against saved-openapi.json --details
148
+ bsm-cli api download example_download ./archive.zip --param name=example
149
+ ```
150
+
151
+ `api download` streams a discovered GET operation and replaces the destination
152
+ only after a complete download. JSON mode returns the output path and byte count.
153
+ `api diff --details` includes conservative compatibility classifications alongside
154
+ the usual added/removed/changed lists. Invalid saved schemas produce input errors.
155
+
156
+ Completion validates cached contracts and fingerprints and rejects metadata for a
157
+ different backend URL or recorded user. Malformed caches yield no suggestions.
158
+ Boolean and enum parameter values have completion suggestions. Interactive command
159
+ menus can select live operation IDs and return to the menu after each action.
160
+
161
+
162
+ ## Manager dashboard and settings
163
+
164
+ The home menu opens Overview, Monitor, and Operations directly. Select a server
165
+ to see its lifecycle, configuration, backup, and world actions on one screen.
166
+ Menus with a list display it automatically before offering actions. Operations
167
+ can be selected directly to inspect their outcomes.
168
+
169
+ These views are also available without entering the menu:
170
+
171
+ ```bash
172
+ bsm-cli auth setup --base-url http://localhost:11325
173
+ bsm-cli overview
174
+ bsm-cli health
175
+ bsm-cli monitor
176
+ bsm-cli monitor --once --unit GB
177
+ bsm-cli operations list
178
+ bsm-cli operations show TASK_ID
179
+ bsm-cli audit
180
+ bsm-cli logs --topic app_logs
181
+ ```
182
+
183
+ Application commands use their direct paths (`overview`, `monitor`, `settings`,
184
+ `health`, `logs`, `audit`, and `operations`). Server monitoring and settings live
185
+ under `server`; the duplicate `manager` and `system` groups have been removed.
186
+ Use `bsm-cli server monitor --server survival` for a single server.
187
+
188
+ Overview, monitoring, and operation lists use structured terminal tables. In an
189
+ interactive menu, Ctrl+C stops the active live view and returns to its menu;
190
+ standalone live commands still exit normally on Ctrl+C.
191
+
192
+ Live views reconnect automatically and reconcile WebSocket updates with HTTP
193
+ snapshots. Revision checks prevent older snapshots from replacing newer state.
194
+ Application monitoring separates app and system metrics and shows recent CPU
195
+ history. Log history returns a cursor for requesting older pages.
196
+
197
+ ```bash
198
+ bsm-cli settings
199
+ bsm-cli server settings --server survival
200
+ bsm-cli plugin settings edit backup_on_start
201
+ bsm-cli plugin settings show backup_on_start
202
+ bsm-cli plugin settings set backup_on_start settings.json
203
+ bsm-cli appearance set --memory-unit GB --density compact
204
+ ```
205
+
206
+ The shared settings editor reviews changes before saving. Plugin schemas provide
207
+ field descriptions, bounds, enums, and server checklists; plugins without settings
208
+ have no Settings action. Credential fields are masked. Application and server
209
+ settings infer field types from their current values because those endpoints do
210
+ not advertise an editable settings schema. Backend validation remains authoritative.
211
+
212
+ An editor refuses to save if its settings changed in another session. Global and
213
+ server settings are saved one key at a time; the CLI prints each successfully saved
214
+ key so partial updates remain visible if a later request fails. Plugins use one
215
+ request to replace their settings. `--json` continues to return structured API data
216
+ for noninteractive commands; use `plugin settings set` for scripted updates.
217
+
218
+ Use `bsm-cli auth login --remember-me` to request the backend-configured longer
219
+ token lifetime. Interactive login also offers this choice, defaulting to off.
220
+ The CLI saves the issued token without storing your password; the flag cannot
221
+ extend the lifetime of an existing token supplied with `--token`.
@@ -17,26 +17,28 @@ classifiers = [
17
17
  "Programming Language :: Python :: 3.11",
18
18
  "Programming Language :: Python :: 3.12",
19
19
  "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
20
21
  "Operating System :: OS Independent",
21
22
  "Intended Audience :: Developers",
22
23
  ]
23
24
  dependencies = [
24
- "click >=8.2.0,<8.5",
25
+ "click >=8.2.0,<8.6",
25
26
  "questionary >=2.1.0,<2.2",
26
- "bsm-api-client >=1.6.0b3,<1.7",
27
+ "rich >=13.9,<16",
28
+ "bsm-api-client >=1.7.0b1,<1.8",
27
29
  ]
28
30
  keywords = ["minecraft", "bedrock", "server", "manager", "cli"]
29
31
 
30
32
  [project.optional-dependencies]
31
33
  dev = [
32
34
  "pytest >=8.4.0,<9.2",
33
- "pytest-mock >=3.14.0,<3.16",
35
+ "pytest-mock >=3.14.0,<3.17",
34
36
  "pytest-asyncio >= 1.1.0,< 1.5",
35
- "black >=25.1.0,<26.6",
36
- "flake8 >=7.3.0,<7.4",
37
- "isort >=5.13.0,<8.1",
38
- "mypy >=1.10.0,<2.2",
39
- "bedrock-server-manager >=3.10.0b3,<3.11.0",
37
+ "black >=25.1.0,<26.11",
38
+ "flake8 >=7.3.0,<7.5",
39
+ "isort >=5.13.0,<9.1",
40
+ "mypy >=1.10.0,<2.4",
41
+ "bedrock-server-manager >=4.0.0b5,<4.1",
40
42
  "pre-commit >=4.6.0,<4.7",
41
43
  ]
42
44
 
@@ -53,11 +55,14 @@ include = ["bsm_cli*"]
53
55
  [tool.setuptools_scm]
54
56
  root = "../.."
55
57
  local_scheme = "no-local-version"
58
+ fallback_version = "1.6.1.dev0"
56
59
 
57
60
  [tool.black]
61
+ target-version = ["py311"]
58
62
 
59
63
  [tool.isort]
60
64
  profile = "black"
65
+ known_first_party = ["bsm_api_client", "bsm_cli"]
61
66
  line_length = 88
62
67
 
63
68
  [tool.mypy]
@@ -10,9 +10,12 @@ except ImportError:
10
10
 
11
11
  from contextlib import asynccontextmanager
12
12
 
13
+ from bsm_api_client import BedrockServerManagerApi
13
14
  from bsm_cli.account import account
14
15
  from bsm_cli.addon import addon
15
16
  from bsm_cli.allowlist import allowlist
17
+ from bsm_cli.api import api, register_plugin_commands
18
+ from bsm_cli.appearance import appearance
16
19
  from bsm_cli.auth import auth
17
20
  from bsm_cli.backup import backup
18
21
  from bsm_cli.bans import bans
@@ -20,6 +23,7 @@ from bsm_cli.config import Config
20
23
  from bsm_cli.content import content
21
24
  from bsm_cli.decorators import AsyncGroup
22
25
  from bsm_cli.main_menus import main_menu
26
+ from bsm_cli.manager import manager
23
27
  from bsm_cli.permissions import permissions
24
28
  from bsm_cli.player import player
25
29
  from bsm_cli.plugins import plugin
@@ -29,21 +33,26 @@ from bsm_cli.system import system
29
33
  from bsm_cli.users import users
30
34
  from bsm_cli.world import world
31
35
 
32
- from bsm_api_client import BedrockServerManagerApi
33
-
34
36
 
35
37
  @click.group(cls=AsyncGroup, invoke_without_command=True)
38
+ @click.option(
39
+ "--json", "json_output", is_flag=True, help="Print deterministic JSON responses."
40
+ )
36
41
  @click.pass_context
37
- def cli(ctx):
42
+ def cli(ctx, json_output):
38
43
  """A CLI for managing Bedrock servers."""
39
44
  ctx.obj["cli"] = cli
45
+ ctx.obj["json_output"] = json_output
40
46
  if ctx.invoked_subcommand is None:
47
+ if json_output:
48
+ raise click.UsageError("Choose a command with --json.")
41
49
  return main_menu(ctx)
42
50
 
43
51
 
44
52
  @cli.context
45
53
  @asynccontextmanager
46
54
  async def cli_context(ctx):
55
+ ctx.obj["json_output"] = ctx.params.get("json_output", False)
47
56
  config = Config()
48
57
  ctx.obj["config"] = config
49
58
 
@@ -51,11 +60,13 @@ async def cli_context(ctx):
51
60
  client = BedrockServerManagerApi(
52
61
  base_url=config.base_url,
53
62
  jwt_token=config.jwt_token,
63
+ username=config.username,
64
+ password=config.password,
54
65
  verify_ssl=config.verify_ssl,
55
66
  )
56
67
  except ValueError as e:
57
68
  # Ignore AuthError when logging out or auth group is called
58
- if ctx.invoked_subcommand == auth or ctx.invoked_subcommand is None:
69
+ if not config.jwt_token and not (config.username and config.password):
59
70
  client = None
60
71
  else:
61
72
  raise e
@@ -68,6 +79,9 @@ async def cli_context(ctx):
68
79
  await ctx.obj["client"].close()
69
80
 
70
81
 
82
+ cli.add_command(appearance)
83
+ cli.add_command(api)
84
+ register_plugin_commands(plugin)
71
85
  cli.add_command(auth)
72
86
  cli.add_command(server)
73
87
  cli.add_command(addon)
@@ -78,11 +92,17 @@ cli.add_command(allowlist)
78
92
  cli.add_command(bans)
79
93
  cli.add_command(permissions)
80
94
  cli.add_command(properties)
81
- cli.add_command(system)
82
95
  cli.add_command(world)
83
96
  cli.add_command(account)
84
97
  cli.add_command(content)
85
98
  cli.add_command(users)
86
99
 
100
+ # Register each workflow at its canonical command path.
101
+ for name in ("overview", "monitor", "settings", "health", "audit", "logs"):
102
+ cli.add_command(manager.commands[name], name=name)
103
+ cli.add_command(manager.commands["tasks"], name="operations")
104
+ server.add_command(system.commands["monitor"], name="monitor")
105
+ server.add_command(system.commands["settings"], name="settings")
106
+
87
107
  if __name__ == "__main__":
88
108
  cli()
@@ -2,7 +2,9 @@
2
2
  """CLI commands for account management."""
3
3
 
4
4
  import click
5
+
5
6
  from bsm_cli.decorators import pass_async_context
7
+ from bsm_cli.output import get_client
6
8
 
7
9
 
8
10
  @click.group()
@@ -15,8 +17,8 @@ def account():
15
17
  @pass_async_context
16
18
  async def details(ctx):
17
19
  """Get your account details."""
18
- client = ctx.obj["client"]
19
- details = await client.async_get_account_details()
20
+ client = get_client(ctx)
21
+ details = await client.account.async_get_account_details()
20
22
  click.echo(details.model_dump_json(indent=2))
21
23
 
22
24
 
@@ -27,9 +29,9 @@ async def update_theme(ctx, theme):
27
29
  """Update your theme."""
28
30
  from bsm_api_client.models import ThemeUpdatePayload
29
31
 
30
- client = ctx.obj["client"]
32
+ client = get_client(ctx)
31
33
  payload = ThemeUpdatePayload(theme=theme)
32
- response = await client.async_update_theme(payload)
34
+ response = await client.account.async_update_theme(payload)
33
35
  click.echo(response.model_dump_json(indent=2))
34
36
 
35
37
 
@@ -41,9 +43,9 @@ async def update_profile(ctx, full_name, email):
41
43
  """Update your profile."""
42
44
  from bsm_api_client.models import ProfileUpdatePayload
43
45
 
44
- client = ctx.obj["client"]
46
+ client = get_client(ctx)
45
47
  payload = ProfileUpdatePayload(full_name=full_name, email=email)
46
- response = await client.async_update_profile(payload)
48
+ response = await client.account.async_update_profile(payload)
47
49
  click.echo(response.model_dump_json(indent=2))
48
50
 
49
51
 
@@ -67,9 +69,9 @@ async def change_password(ctx, current_password, new_password):
67
69
  """Change your password."""
68
70
  from bsm_api_client.models import ChangePasswordPayload
69
71
 
70
- client = ctx.obj["client"]
72
+ client = get_client(ctx)
71
73
  payload = ChangePasswordPayload(
72
74
  current_password=current_password, new_password=new_password
73
75
  )
74
- response = await client.async_change_password(payload)
76
+ response = await client.account.async_change_password(payload)
75
77
  click.echo(response.model_dump_json(indent=2))