msdev 0.11.0__tar.gz → 0.13.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 (106) hide show
  1. {msdev-0.11.0 → msdev-0.13.0}/PKG-INFO +105 -77
  2. {msdev-0.11.0 → msdev-0.13.0}/README.md +104 -76
  3. {msdev-0.11.0 → msdev-0.13.0}/pyproject.toml +6 -2
  4. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/__init__.py +1 -1
  5. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/cli.py +426 -560
  6. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/compat.py +6 -6
  7. msdev-0.13.0/src/msdev/core/config_bundle.py +338 -0
  8. msdev-0.13.0/src/msdev/core/daemon_deploy.py +49 -0
  9. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/env_transfer.py +30 -29
  10. msdev-0.13.0/src/msdev/core/exec_argv.py +196 -0
  11. msdev-0.13.0/src/msdev/core/init_setup.py +42 -0
  12. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/resources.py +58 -11
  13. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/context.py +1 -1
  14. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/environment.py +18 -0
  15. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/node.py +160 -6
  16. msdev-0.13.0/src/msdev/core/sftp_transfer.py +120 -0
  17. msdev-0.13.0/src/msdev/core/skill_install.py +258 -0
  18. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/ssh_auth.py +72 -82
  19. msdev-0.13.0/src/msdev/core/ssh_config.py +380 -0
  20. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/ssh_tunnel.py +5 -2
  21. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/stream_transport.py +9 -3
  22. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/transport.py +343 -181
  23. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/daemon.py +99 -0
  24. msdev-0.13.0/src/msdev/helpers/msdev-file-helper-linux-amd64 +0 -0
  25. msdev-0.13.0/src/msdev/helpers/msdev-file-helper-linux-amd64.sha256 +1 -0
  26. msdev-0.13.0/src/msdev/helpers/msdev-file-helper-linux-arm64 +0 -0
  27. msdev-0.13.0/src/msdev/helpers/msdev-file-helper-linux-arm64.sha256 +1 -0
  28. msdev-0.13.0/src/msdev/helpers/msdevd-linux-amd64 +0 -0
  29. msdev-0.13.0/src/msdev/helpers/msdevd-linux-amd64.sha256 +1 -0
  30. msdev-0.13.0/src/msdev/helpers/msdevd-linux-arm64 +0 -0
  31. msdev-0.13.0/src/msdev/helpers/msdevd-linux-arm64.sha256 +1 -0
  32. msdev-0.13.0/src/msdev/skills/msdev-cli/SKILL.md +182 -0
  33. {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/PKG-INFO +105 -77
  34. {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/SOURCES.txt +26 -0
  35. {msdev-0.11.0 → msdev-0.13.0}/tests/test_cli.py +62 -104
  36. {msdev-0.11.0 → msdev-0.13.0}/tests/test_cli_only_architecture.py +21 -4
  37. {msdev-0.11.0 → msdev-0.13.0}/tests/test_config.py +1 -1
  38. msdev-0.13.0/tests/test_config_bundle.py +224 -0
  39. msdev-0.13.0/tests/test_connect_env_scenario.py +146 -0
  40. msdev-0.13.0/tests/test_daemon_deploy.py +148 -0
  41. {msdev-0.11.0 → msdev-0.13.0}/tests/test_env_transfer.py +16 -11
  42. msdev-0.13.0/tests/test_exec_argv.py +133 -0
  43. msdev-0.13.0/tests/test_exec_command_scenario.py +152 -0
  44. {msdev-0.11.0 → msdev-0.13.0}/tests/test_exec_default_timeout_scenario.py +2 -8
  45. msdev-0.13.0/tests/test_go_msdevd_scenario.py +209 -0
  46. msdev-0.13.0/tests/test_init_skill.py +241 -0
  47. msdev-0.13.0/tests/test_model_cli.py +19 -0
  48. msdev-0.13.0/tests/test_msdev_cli_skill.py +89 -0
  49. msdev-0.13.0/tests/test_node_connect_provision_scenario.py +104 -0
  50. msdev-0.13.0/tests/test_node_connect_save_password_scenario.py +87 -0
  51. {msdev-0.11.0 → msdev-0.13.0}/tests/test_node_env_config.py +1 -1
  52. {msdev-0.11.0 → msdev-0.13.0}/tests/test_node_env_services.py +17 -8
  53. msdev-0.13.0/tests/test_node_sync_ssh_scenario.py +76 -0
  54. msdev-0.13.0/tests/test_sftp_transfer_scenario.py +109 -0
  55. {msdev-0.11.0 → msdev-0.13.0}/tests/test_ssh_auth.py +75 -58
  56. msdev-0.13.0/tests/test_ssh_config.py +171 -0
  57. {msdev-0.11.0 → msdev-0.13.0}/tests/test_target_exec_services.py +17 -4
  58. {msdev-0.11.0 → msdev-0.13.0}/tests/test_transport.py +99 -41
  59. {msdev-0.11.0 → msdev-0.13.0}/tests/test_windows_local_scenario.py +15 -15
  60. msdev-0.11.0/src/msdev/core/exec_argv.py +0 -82
  61. msdev-0.11.0/tests/test_exec_argv.py +0 -55
  62. msdev-0.11.0/tests/test_model_cli.py +0 -364
  63. msdev-0.11.0/tests/test_msdev_cli_skill.py +0 -107
  64. {msdev-0.11.0 → msdev-0.13.0}/LICENSE +0 -0
  65. {msdev-0.11.0 → msdev-0.13.0}/setup.cfg +0 -0
  66. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/__init__.py +0 -0
  67. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/config.py +0 -0
  68. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/container_helper.py +0 -0
  69. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/guides.py +0 -0
  70. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/helper_deploy.py +0 -0
  71. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/host_files.py +0 -0
  72. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/host_mutations.py +0 -0
  73. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/inventory.py +0 -0
  74. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/limits.py +0 -0
  75. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/local_rpc.py +0 -0
  76. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/multiplex.py +0 -0
  77. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/request_client.py +0 -0
  78. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/__init__.py +0 -0
  79. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/capabilities.py +0 -0
  80. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/execution.py +0 -0
  81. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/model.py +0 -0
  82. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/npu.py +0 -0
  83. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/results.py +0 -0
  84. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/stream_limits.py +0 -0
  85. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/stream_server.py +0 -0
  86. {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/streamproto.py +0 -0
  87. {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/dependency_links.txt +0 -0
  88. {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/entry_points.txt +0 -0
  89. {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/top_level.txt +0 -0
  90. {msdev-0.11.0 → msdev-0.13.0}/tests/test_compat.py +0 -0
  91. {msdev-0.11.0 → msdev-0.13.0}/tests/test_container_helper.py +0 -0
  92. {msdev-0.11.0 → msdev-0.13.0}/tests/test_daemon.py +0 -0
  93. {msdev-0.11.0 → msdev-0.13.0}/tests/test_daemon_container_stream.py +0 -0
  94. {msdev-0.11.0 → msdev-0.13.0}/tests/test_docker_stream_dispatch.py +0 -0
  95. {msdev-0.11.0 → msdev-0.13.0}/tests/test_env_put_get_scenario.py +0 -0
  96. {msdev-0.11.0 → msdev-0.13.0}/tests/test_env_read_write_scenario.py +0 -0
  97. {msdev-0.11.0 → msdev-0.13.0}/tests/test_helper_deploy.py +0 -0
  98. {msdev-0.11.0 → msdev-0.13.0}/tests/test_inventory.py +0 -0
  99. {msdev-0.11.0 → msdev-0.13.0}/tests/test_model_services.py +0 -0
  100. {msdev-0.11.0 → msdev-0.13.0}/tests/test_multiplex.py +0 -0
  101. {msdev-0.11.0 → msdev-0.13.0}/tests/test_request_client.py +0 -0
  102. {msdev-0.11.0 → msdev-0.13.0}/tests/test_ssh_tunnel.py +0 -0
  103. {msdev-0.11.0 → msdev-0.13.0}/tests/test_stream_server.py +0 -0
  104. {msdev-0.11.0 → msdev-0.13.0}/tests/test_stream_transport.py +0 -0
  105. {msdev-0.11.0 → msdev-0.13.0}/tests/test_streamproto.py +0 -0
  106. {msdev-0.11.0 → msdev-0.13.0}/tests/test_target_guides.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: msdev
3
- Version: 0.11.0
3
+ Version: 0.13.0
4
4
  Summary: Portable nodes and execution environments for msModelSlim development
5
5
  Author: msModelSlim Agent Contributors
6
6
  License-Expression: MulanPSL-2.0
@@ -25,16 +25,16 @@ Dynamic: license-file
25
25
 
26
26
  # msdev
27
27
 
28
- `msdev` manages connection Nodes and execution Envs. A Node owns SSH and its
29
- per-user `msdevd`; an Env references a Node and adds a host/Docker runtime plus
30
- optional conda/venv/uv layers.
28
+ `msdev` exposes three capabilities: **`node`** (connect + host agent),
29
+ **`env`** (shared execution context, shell, files), and **`exec`** (commands).
31
30
 
32
- The CLI is intentionally stateless:
31
+ A Node owns SSH reachability and `msdevd` deployment. An Env owns the full
32
+ execution context: host or Docker runtime, conda/venv/uv layers, optional
33
+ `setup` script (root switch, proxy, etc.), command `wrap`, and static env vars.
33
34
 
34
- - Node-scoped NPU/model operations name `--node` or use `--all`;
35
- - execution names `--env`;
36
- - no harness conversation binding or implicit current Env exists;
37
- - MCP is not part of the architecture.
35
+ The CLI is intentionally stateless: execution always names the env as the first
36
+ `exec` argument.
37
+ MCP is not part of the architecture.
38
38
 
39
39
  ## Install
40
40
 
@@ -47,6 +47,20 @@ msdev --help
47
47
 
48
48
  The package installs `msdev` and `msdevd`.
49
49
 
50
+ Install the agent skill for Cursor and Claude Code, and sync SSH config:
51
+
52
+ ```bash
53
+ msdev init
54
+ msdev init --scope project
55
+ msdev init -f
56
+ ```
57
+
58
+ `init` registers Host aliases from `~/.ssh/config`, prints added/removed
59
+ changes, and writes `skills/msdev-cli/SKILL.md` into `~/.cursor/skills/` and
60
+ `~/.claude/skills/` (or into `.cursor/` / `.claude/` under the current
61
+ directory with `--scope project`). Outdated skill files prompt before
62
+ overwrite; use `-f` to force.
63
+
50
64
  ## Windows client
51
65
 
52
66
  The typical setup is a **Windows laptop talking to Linux Nodes** via OpenSSH
@@ -59,13 +73,13 @@ implement ControlMaster multiplexing, so msdev:
59
73
  RPC (same role as ControlMaster). Explicit `msdev node connect NODE` is
60
74
  optional; disable persist with `MSDEV_SSH_LOCAL_FORWARD_PERSIST=0`;
61
75
  - reuses that tunnel for captured RPC and default streaming `msdev exec`;
62
- `env put`/`get` stay on scp/ssh streams (file bytes do not go through JSON RPC);
76
+ `env put`/`get` stay on sftp/ssh streams (file bytes do not go through JSON RPC);
63
77
  - hides SSH console windows (`CREATE_NO_WINDOW`) and kills process trees with
64
78
  `taskkill /T` on timeout or cancel;
65
79
  - SSH is non-interactive: `BatchMode` unless a password is supplied, host keys
66
80
  use `accept-new`, and there is no password/passphrase/yes-no prompt. When a
67
81
  password is known, injects OpenSSH `SSH_ASKPASS` so `node connect` (and later
68
- ssh/scp) can authenticate without a TTY; the local public key is then
82
+ ssh/sftp) can authenticate without a TTY; the local public key is then
69
83
  installed on the Node so later logins are passwordless. The password is
70
84
  never written to the node registry;
71
85
  - serves a TCP loopback endpoint for local `msdevd` when this Python build has
@@ -83,36 +97,48 @@ If `ssh` is not on PATH, msdev looks in `%SystemRoot%\System32\OpenSSH\`.
83
97
 
84
98
  ## Nodes and execution environments
85
99
 
86
- Register a host from `~/.ssh/config`:
100
+ Use **`node connect`** as the single entry point: it writes `~/.ssh/config`
101
+ when needed, registers the node, saves passwords, installs the local public
102
+ key, and deploys `msdevd`:
87
103
 
88
104
  ```bash
89
- msdev node add dev-122 --ssh-host dev-122
105
+ msdev node connect dev-122 --hostname 80.48.33.133 --user root --password PASSWORD
106
+ msdev node connect dev-122
107
+ msdev node sync-ssh
108
+ msdev node list --ssh
90
109
  msdev node list
91
- msdev node status dev-122
92
110
  ```
93
111
 
94
- Adding a Node atomically creates a same-named host Env. Bootstrap or refresh
95
- the remote user daemon:
112
+ Connect writes or updates a dedicated `Host <name>` block in OpenSSH config.
113
+ The msdev registry stores only the Host alias plus msdevd settings
114
+ (`remote_bin`, `auto_bootstrap`). User, port, keys, and proxy remain in SSH
115
+ config. `node sync-ssh` registers Host aliases that were added manually.
116
+
117
+ Connect atomically creates a same-named host Env on first use and uploads a
118
+ **static Go msdevd** binary matching the node architecture
119
+ (`linux-amd64` / `linux-arm64`) when the agent is missing or stale. No Python
120
+ is required on the node.
121
+
122
+ Build the static daemons before release or local testing:
96
123
 
97
124
  ```bash
98
- msdev node bootstrap dev-122
125
+ bash msdevd/build-static.sh
126
+ bash file-helper/build-static.sh
99
127
  ```
100
128
 
129
+ Packaged artifacts live under `src/msdev/helpers/` (gitignored until built).
130
+ The Go source is in `msdev/`.
131
+
101
132
  Persistent OpenSSH masters are optional. All SSH from msdev is
102
133
  non-interactive: host keys use `accept-new`, and password/passphrase prompts
103
- are disabled. Supply a password via environment or file (never a prompt);
104
- connect then installs the local public key (`~/.ssh/id_ed25519`, generated
105
- if missing) so later connections are passwordless:
134
+ are disabled. Supply `--password` on connect; it is saved to ``~/.ssh/config``
135
+ as ``# msdev Password ...`` and used to install the local public key
136
+ (``~/.ssh/id_ed25519``, generated if missing) so later connections can be
137
+ passwordless:
106
138
 
107
139
  ```bash
108
- # Environment (also used by exec / env put after connect if persist is off)
109
- export MSDEV_SSH_PASSWORD='...'
110
- export MSDEV_SSH_PASSWORD_DEV_122='...' # per-node override
111
-
140
+ msdev node connect dev-122 --hostname 80.48.33.133 --user root --password PASSWORD
112
141
  msdev node connect dev-122
113
- msdev node connect dev-122 --password-file FILE
114
- msdev node connect dev-122 --password-env VAR
115
- msdev node connect dev-122 --password PASSWORD # non-interactive; visible in ps
116
142
  msdev node connect dev-122 --identity FILE # choose which key to install
117
143
  msdev node connect dev-122 --no-install-key # password only, do not copy key
118
144
  msdev node disconnect dev-122
@@ -128,32 +154,38 @@ msdev env guide dev-122 --write ./host-env-guide.md
128
154
  ```
129
155
 
130
156
  Guides are stored under `~/.config/msdev/guides/nodes/` and
131
- `~/.config/msdev/guides/environments/`, with private permissions and a 256 KiB
132
- limit. Agents read the applicable guides once before first use in a session.
157
+ `~/.config/msdev/guides/environments/`. **Node guides** document how to
158
+ connect; **Env guides** document how to initialize shared context (`setup`).
133
159
 
134
- Open a human-operated interactive shell in an Env:
160
+ Share a full local configuration (registry + guides) with:
135
161
 
136
162
  ```bash
137
- msdev env shell dev-122
138
- msdev env shell dev-122 --cwd /srv/project
163
+ msdev config export ./msdev-config.tar.gz
164
+ msdev config import ./msdev-config.tar.gz
165
+ msdev config import ./msdev-config.tar.gz --force # overwrite name conflicts
139
166
  ```
140
167
 
141
- The command allocates an OpenSSH PTY and enters the Env's Docker runtime and
142
- conda/venv/uv layers. Exiting returns
143
- to the local shell. Only the shell session start and final status are visible
144
- to msdev; commands typed inside it are not individually logged. Agent
145
- automation should continue using `msdev exec`.
146
-
147
- Create another Env on the same Node for Docker and Python layers:
168
+ Bundles contain `resources.json`, both guide trees, and a `manifest.json`.
169
+ SSH keys and passwords are never exported.
148
170
 
149
171
  ```bash
150
- msdev env add dev-122-vllm \
172
+ msdev env add dev-122-root \
151
173
  --node dev-122 \
152
- --docker-container vllm-ascend \
153
- --layer conda:base \
154
- --layer venv:/srv/project/.venv
174
+ --setup-file ./setup-root.sh \
175
+ --wrap sudo --wrap -n --wrap --
176
+
177
+ msdev env open dev-122-root
155
178
  ```
156
179
 
180
+ Open a human-operated interactive shell in an Env:
181
+
182
+ ```bash
183
+ msdev env shell dev-122
184
+ msdev env shell dev-122 --cwd /srv/project
185
+ ```
186
+
187
+ Agent automation should use `msdev exec`, not `env shell`.
188
+
157
189
  ## File put, get, read, and write
158
190
 
159
191
  Bulk transfer copies a local file into an Env filesystem, or fetches one back:
@@ -165,7 +197,7 @@ msdev env get dev-122 /srv/project/config.yaml > ./config.yaml
165
197
  ```
166
198
 
167
199
  Editing uses content-oriented read/write. Paths inside the Env must be
168
- absolute. Host Envs use direct filesystem copy locally and ``scp``/``ssh``
200
+ absolute. Host Envs use direct filesystem copy locally and ``sftp``/``ssh``
169
201
  streams remotely. Docker Envs stage through the node with ``docker cp``.
170
202
  File bytes never pass through JSON RPC.
171
203
 
@@ -181,29 +213,42 @@ msdev env write dev-122 /srv/project/note.md --file /tmp/note.md \
181
213
  Read before replacing an existing file. `--expected-sha256` is compare-and-swap
182
214
  replacement that refuses to overwrite a changed remote file.
183
215
 
184
- ## NPU inventory
185
-
186
- ```bash
187
- msdev npu list --node dev-122 --json
188
- msdev npu list --all --json
189
- ```
190
-
191
216
  ## Command execution
192
217
 
193
218
  Commands execute synchronously and stream stdout and stderr to the terminal as
194
219
  they are produced. Cursor or Claude Code should use their native background
195
- terminal support for long jobs. Long jobs may also write a persistent progress
196
- log when later inspection is required.
220
+ terminal support for long jobs.
221
+
222
+ Pick **one** form:
223
+
224
+ | Scenario | Form |
225
+ |----------|------|
226
+ | Simple one-liner | `-c '…'` |
227
+ | Quotes, pipes, multi-line | `--file -` + heredoc (see below) |
228
+ | Script on disk | `--file ./script.sh` |
229
+
230
+ **Heredoc** (`<<'EOF'`) is a local-shell mechanism: it writes a multi-line
231
+ string to msdev's **stdin** when you pass `--file -`. Quote the delimiter
232
+ (`<<'EOF'`) so `$` and backticks are not expanded locally. msdev then runs the
233
+ body through a remote shell (`sh -c`), or via shebang if the body starts with
234
+ `#!`.
197
235
 
198
236
  ```bash
199
- msdev exec \
200
- --env dev-122 \
201
- --cwd /srv/project \
202
- --timeout-seconds 1800 \
203
- --env-var MODE=test \
204
- -- python3 run.py
237
+ msdev exec dev-122 --file - <<'EOF'
238
+ python3 -c 'print("no local quoting")'
239
+ grep 'pattern' /var/log/app.log | tail -20
240
+ EOF
241
+
242
+ msdev exec dev-122 -c 'python3 train.py --config "path with spaces" | tee log.txt'
243
+
244
+ msdev exec dev-122 --file ./scripts/run.sh
205
245
  ```
206
246
 
247
+ Positional commands after `--` are not supported. The env name is the first
248
+ argument after `exec`; use `-c` for inline strings or `--file` for script
249
+ content (path or `-` for stdin/heredoc). `-c -` is accepted but identical to
250
+ `--file -`; prefer **`--file -`** only.
251
+
207
252
  Quoted pipelines and `|` tokens are executed through a remote POSIX shell
208
253
  (`sh -c`), so they run on the Node instead of being treated as a single
209
254
  executable name. On a Windows `local` Env they use `cmd.exe /s /c`. Prefer
@@ -221,30 +266,13 @@ serialization.
221
266
  `--result-json` selects captured, non-streaming execution and prints one
222
267
  structured JSON result containing stdout and stderr.
223
268
 
224
- ## Model inventory
225
-
226
- Examples:
227
-
228
- ```bash
229
- msdev model discover --node dev-122 --root /data/models
230
- msdev model list --node dev-122 --json
231
- msdev model list --all --json
232
- msdev model inspect model://qwen/Qwen3-32B@main --node dev-122
233
- msdev model validate model://qwen/Qwen3-32B@main --node dev-122
234
- msdev model audit --node dev-122
235
- ```
236
-
237
- Use `msdev model --help` and the individual subcommand help for register,
238
- update, replicas, refresh, verify, export, import, and rebind.
239
-
240
269
  ## Architecture
241
270
 
242
271
  ```text
243
272
  msdev CLI
244
273
  -> typed core service
245
274
  -> UnixRpcTransport or SshRpcTransport
246
- -> per-user msdevd
247
- -> host/container command, env file transfer, NPU, or inventory
275
+ -> per-user msdevd (env session + job runner + files)
248
276
  ```
249
277
 
250
278
  Remote RPC responses and command output are bounded. Node/Env registries use
@@ -1,15 +1,15 @@
1
1
  # msdev
2
2
 
3
- `msdev` manages connection Nodes and execution Envs. A Node owns SSH and its
4
- per-user `msdevd`; an Env references a Node and adds a host/Docker runtime plus
5
- optional conda/venv/uv layers.
3
+ `msdev` exposes three capabilities: **`node`** (connect + host agent),
4
+ **`env`** (shared execution context, shell, files), and **`exec`** (commands).
6
5
 
7
- The CLI is intentionally stateless:
6
+ A Node owns SSH reachability and `msdevd` deployment. An Env owns the full
7
+ execution context: host or Docker runtime, conda/venv/uv layers, optional
8
+ `setup` script (root switch, proxy, etc.), command `wrap`, and static env vars.
8
9
 
9
- - Node-scoped NPU/model operations name `--node` or use `--all`;
10
- - execution names `--env`;
11
- - no harness conversation binding or implicit current Env exists;
12
- - MCP is not part of the architecture.
10
+ The CLI is intentionally stateless: execution always names the env as the first
11
+ `exec` argument.
12
+ MCP is not part of the architecture.
13
13
 
14
14
  ## Install
15
15
 
@@ -22,6 +22,20 @@ msdev --help
22
22
 
23
23
  The package installs `msdev` and `msdevd`.
24
24
 
25
+ Install the agent skill for Cursor and Claude Code, and sync SSH config:
26
+
27
+ ```bash
28
+ msdev init
29
+ msdev init --scope project
30
+ msdev init -f
31
+ ```
32
+
33
+ `init` registers Host aliases from `~/.ssh/config`, prints added/removed
34
+ changes, and writes `skills/msdev-cli/SKILL.md` into `~/.cursor/skills/` and
35
+ `~/.claude/skills/` (or into `.cursor/` / `.claude/` under the current
36
+ directory with `--scope project`). Outdated skill files prompt before
37
+ overwrite; use `-f` to force.
38
+
25
39
  ## Windows client
26
40
 
27
41
  The typical setup is a **Windows laptop talking to Linux Nodes** via OpenSSH
@@ -34,13 +48,13 @@ implement ControlMaster multiplexing, so msdev:
34
48
  RPC (same role as ControlMaster). Explicit `msdev node connect NODE` is
35
49
  optional; disable persist with `MSDEV_SSH_LOCAL_FORWARD_PERSIST=0`;
36
50
  - reuses that tunnel for captured RPC and default streaming `msdev exec`;
37
- `env put`/`get` stay on scp/ssh streams (file bytes do not go through JSON RPC);
51
+ `env put`/`get` stay on sftp/ssh streams (file bytes do not go through JSON RPC);
38
52
  - hides SSH console windows (`CREATE_NO_WINDOW`) and kills process trees with
39
53
  `taskkill /T` on timeout or cancel;
40
54
  - SSH is non-interactive: `BatchMode` unless a password is supplied, host keys
41
55
  use `accept-new`, and there is no password/passphrase/yes-no prompt. When a
42
56
  password is known, injects OpenSSH `SSH_ASKPASS` so `node connect` (and later
43
- ssh/scp) can authenticate without a TTY; the local public key is then
57
+ ssh/sftp) can authenticate without a TTY; the local public key is then
44
58
  installed on the Node so later logins are passwordless. The password is
45
59
  never written to the node registry;
46
60
  - serves a TCP loopback endpoint for local `msdevd` when this Python build has
@@ -58,36 +72,48 @@ If `ssh` is not on PATH, msdev looks in `%SystemRoot%\System32\OpenSSH\`.
58
72
 
59
73
  ## Nodes and execution environments
60
74
 
61
- Register a host from `~/.ssh/config`:
75
+ Use **`node connect`** as the single entry point: it writes `~/.ssh/config`
76
+ when needed, registers the node, saves passwords, installs the local public
77
+ key, and deploys `msdevd`:
62
78
 
63
79
  ```bash
64
- msdev node add dev-122 --ssh-host dev-122
80
+ msdev node connect dev-122 --hostname 80.48.33.133 --user root --password PASSWORD
81
+ msdev node connect dev-122
82
+ msdev node sync-ssh
83
+ msdev node list --ssh
65
84
  msdev node list
66
- msdev node status dev-122
67
85
  ```
68
86
 
69
- Adding a Node atomically creates a same-named host Env. Bootstrap or refresh
70
- the remote user daemon:
87
+ Connect writes or updates a dedicated `Host <name>` block in OpenSSH config.
88
+ The msdev registry stores only the Host alias plus msdevd settings
89
+ (`remote_bin`, `auto_bootstrap`). User, port, keys, and proxy remain in SSH
90
+ config. `node sync-ssh` registers Host aliases that were added manually.
91
+
92
+ Connect atomically creates a same-named host Env on first use and uploads a
93
+ **static Go msdevd** binary matching the node architecture
94
+ (`linux-amd64` / `linux-arm64`) when the agent is missing or stale. No Python
95
+ is required on the node.
96
+
97
+ Build the static daemons before release or local testing:
71
98
 
72
99
  ```bash
73
- msdev node bootstrap dev-122
100
+ bash msdevd/build-static.sh
101
+ bash file-helper/build-static.sh
74
102
  ```
75
103
 
104
+ Packaged artifacts live under `src/msdev/helpers/` (gitignored until built).
105
+ The Go source is in `msdev/`.
106
+
76
107
  Persistent OpenSSH masters are optional. All SSH from msdev is
77
108
  non-interactive: host keys use `accept-new`, and password/passphrase prompts
78
- are disabled. Supply a password via environment or file (never a prompt);
79
- connect then installs the local public key (`~/.ssh/id_ed25519`, generated
80
- if missing) so later connections are passwordless:
109
+ are disabled. Supply `--password` on connect; it is saved to ``~/.ssh/config``
110
+ as ``# msdev Password ...`` and used to install the local public key
111
+ (``~/.ssh/id_ed25519``, generated if missing) so later connections can be
112
+ passwordless:
81
113
 
82
114
  ```bash
83
- # Environment (also used by exec / env put after connect if persist is off)
84
- export MSDEV_SSH_PASSWORD='...'
85
- export MSDEV_SSH_PASSWORD_DEV_122='...' # per-node override
86
-
115
+ msdev node connect dev-122 --hostname 80.48.33.133 --user root --password PASSWORD
87
116
  msdev node connect dev-122
88
- msdev node connect dev-122 --password-file FILE
89
- msdev node connect dev-122 --password-env VAR
90
- msdev node connect dev-122 --password PASSWORD # non-interactive; visible in ps
91
117
  msdev node connect dev-122 --identity FILE # choose which key to install
92
118
  msdev node connect dev-122 --no-install-key # password only, do not copy key
93
119
  msdev node disconnect dev-122
@@ -103,32 +129,38 @@ msdev env guide dev-122 --write ./host-env-guide.md
103
129
  ```
104
130
 
105
131
  Guides are stored under `~/.config/msdev/guides/nodes/` and
106
- `~/.config/msdev/guides/environments/`, with private permissions and a 256 KiB
107
- limit. Agents read the applicable guides once before first use in a session.
132
+ `~/.config/msdev/guides/environments/`. **Node guides** document how to
133
+ connect; **Env guides** document how to initialize shared context (`setup`).
108
134
 
109
- Open a human-operated interactive shell in an Env:
135
+ Share a full local configuration (registry + guides) with:
110
136
 
111
137
  ```bash
112
- msdev env shell dev-122
113
- msdev env shell dev-122 --cwd /srv/project
138
+ msdev config export ./msdev-config.tar.gz
139
+ msdev config import ./msdev-config.tar.gz
140
+ msdev config import ./msdev-config.tar.gz --force # overwrite name conflicts
114
141
  ```
115
142
 
116
- The command allocates an OpenSSH PTY and enters the Env's Docker runtime and
117
- conda/venv/uv layers. Exiting returns
118
- to the local shell. Only the shell session start and final status are visible
119
- to msdev; commands typed inside it are not individually logged. Agent
120
- automation should continue using `msdev exec`.
121
-
122
- Create another Env on the same Node for Docker and Python layers:
143
+ Bundles contain `resources.json`, both guide trees, and a `manifest.json`.
144
+ SSH keys and passwords are never exported.
123
145
 
124
146
  ```bash
125
- msdev env add dev-122-vllm \
147
+ msdev env add dev-122-root \
126
148
  --node dev-122 \
127
- --docker-container vllm-ascend \
128
- --layer conda:base \
129
- --layer venv:/srv/project/.venv
149
+ --setup-file ./setup-root.sh \
150
+ --wrap sudo --wrap -n --wrap --
151
+
152
+ msdev env open dev-122-root
130
153
  ```
131
154
 
155
+ Open a human-operated interactive shell in an Env:
156
+
157
+ ```bash
158
+ msdev env shell dev-122
159
+ msdev env shell dev-122 --cwd /srv/project
160
+ ```
161
+
162
+ Agent automation should use `msdev exec`, not `env shell`.
163
+
132
164
  ## File put, get, read, and write
133
165
 
134
166
  Bulk transfer copies a local file into an Env filesystem, or fetches one back:
@@ -140,7 +172,7 @@ msdev env get dev-122 /srv/project/config.yaml > ./config.yaml
140
172
  ```
141
173
 
142
174
  Editing uses content-oriented read/write. Paths inside the Env must be
143
- absolute. Host Envs use direct filesystem copy locally and ``scp``/``ssh``
175
+ absolute. Host Envs use direct filesystem copy locally and ``sftp``/``ssh``
144
176
  streams remotely. Docker Envs stage through the node with ``docker cp``.
145
177
  File bytes never pass through JSON RPC.
146
178
 
@@ -156,29 +188,42 @@ msdev env write dev-122 /srv/project/note.md --file /tmp/note.md \
156
188
  Read before replacing an existing file. `--expected-sha256` is compare-and-swap
157
189
  replacement that refuses to overwrite a changed remote file.
158
190
 
159
- ## NPU inventory
160
-
161
- ```bash
162
- msdev npu list --node dev-122 --json
163
- msdev npu list --all --json
164
- ```
165
-
166
191
  ## Command execution
167
192
 
168
193
  Commands execute synchronously and stream stdout and stderr to the terminal as
169
194
  they are produced. Cursor or Claude Code should use their native background
170
- terminal support for long jobs. Long jobs may also write a persistent progress
171
- log when later inspection is required.
195
+ terminal support for long jobs.
196
+
197
+ Pick **one** form:
198
+
199
+ | Scenario | Form |
200
+ |----------|------|
201
+ | Simple one-liner | `-c '…'` |
202
+ | Quotes, pipes, multi-line | `--file -` + heredoc (see below) |
203
+ | Script on disk | `--file ./script.sh` |
204
+
205
+ **Heredoc** (`<<'EOF'`) is a local-shell mechanism: it writes a multi-line
206
+ string to msdev's **stdin** when you pass `--file -`. Quote the delimiter
207
+ (`<<'EOF'`) so `$` and backticks are not expanded locally. msdev then runs the
208
+ body through a remote shell (`sh -c`), or via shebang if the body starts with
209
+ `#!`.
172
210
 
173
211
  ```bash
174
- msdev exec \
175
- --env dev-122 \
176
- --cwd /srv/project \
177
- --timeout-seconds 1800 \
178
- --env-var MODE=test \
179
- -- python3 run.py
212
+ msdev exec dev-122 --file - <<'EOF'
213
+ python3 -c 'print("no local quoting")'
214
+ grep 'pattern' /var/log/app.log | tail -20
215
+ EOF
216
+
217
+ msdev exec dev-122 -c 'python3 train.py --config "path with spaces" | tee log.txt'
218
+
219
+ msdev exec dev-122 --file ./scripts/run.sh
180
220
  ```
181
221
 
222
+ Positional commands after `--` are not supported. The env name is the first
223
+ argument after `exec`; use `-c` for inline strings or `--file` for script
224
+ content (path or `-` for stdin/heredoc). `-c -` is accepted but identical to
225
+ `--file -`; prefer **`--file -`** only.
226
+
182
227
  Quoted pipelines and `|` tokens are executed through a remote POSIX shell
183
228
  (`sh -c`), so they run on the Node instead of being treated as a single
184
229
  executable name. On a Windows `local` Env they use `cmd.exe /s /c`. Prefer
@@ -196,30 +241,13 @@ serialization.
196
241
  `--result-json` selects captured, non-streaming execution and prints one
197
242
  structured JSON result containing stdout and stderr.
198
243
 
199
- ## Model inventory
200
-
201
- Examples:
202
-
203
- ```bash
204
- msdev model discover --node dev-122 --root /data/models
205
- msdev model list --node dev-122 --json
206
- msdev model list --all --json
207
- msdev model inspect model://qwen/Qwen3-32B@main --node dev-122
208
- msdev model validate model://qwen/Qwen3-32B@main --node dev-122
209
- msdev model audit --node dev-122
210
- ```
211
-
212
- Use `msdev model --help` and the individual subcommand help for register,
213
- update, replicas, refresh, verify, export, import, and rebind.
214
-
215
244
  ## Architecture
216
245
 
217
246
  ```text
218
247
  msdev CLI
219
248
  -> typed core service
220
249
  -> UnixRpcTransport or SshRpcTransport
221
- -> per-user msdevd
222
- -> host/container command, env file transfer, NPU, or inventory
250
+ -> per-user msdevd (env session + job runner + files)
223
251
  ```
224
252
 
225
253
  Remote RPC responses and command output are bounded. Node/Env registries use
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "msdev"
7
- version = "0.11.0"
7
+ version = "0.13.0"
8
8
  description = "Portable nodes and execution environments for msModelSlim development"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -44,7 +44,11 @@ package-dir = { "" = "src" }
44
44
  where = ["src"]
45
45
 
46
46
  [tool.setuptools.package-data]
47
- msdev = ["helpers/msdev-file-helper-*"]
47
+ msdev = [
48
+ "helpers/msdev-file-helper-*",
49
+ "helpers/msdevd-linux-*",
50
+ "skills/msdev-cli/SKILL.md",
51
+ ]
48
52
 
49
53
  [tool.pytest.ini_options]
50
54
  testpaths = ["tests"]
@@ -1,3 +1,3 @@
1
1
  """Portable node and execution-environment tooling for msModelSlim."""
2
2
 
3
- __version__ = "0.11.0"
3
+ __version__ = "0.13.0"