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.
- {msdev-0.11.0 → msdev-0.13.0}/PKG-INFO +105 -77
- {msdev-0.11.0 → msdev-0.13.0}/README.md +104 -76
- {msdev-0.11.0 → msdev-0.13.0}/pyproject.toml +6 -2
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/__init__.py +1 -1
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/cli.py +426 -560
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/compat.py +6 -6
- msdev-0.13.0/src/msdev/core/config_bundle.py +338 -0
- msdev-0.13.0/src/msdev/core/daemon_deploy.py +49 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/env_transfer.py +30 -29
- msdev-0.13.0/src/msdev/core/exec_argv.py +196 -0
- msdev-0.13.0/src/msdev/core/init_setup.py +42 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/resources.py +58 -11
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/context.py +1 -1
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/environment.py +18 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/node.py +160 -6
- msdev-0.13.0/src/msdev/core/sftp_transfer.py +120 -0
- msdev-0.13.0/src/msdev/core/skill_install.py +258 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/ssh_auth.py +72 -82
- msdev-0.13.0/src/msdev/core/ssh_config.py +380 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/ssh_tunnel.py +5 -2
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/stream_transport.py +9 -3
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/transport.py +343 -181
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/daemon.py +99 -0
- msdev-0.13.0/src/msdev/helpers/msdev-file-helper-linux-amd64 +0 -0
- msdev-0.13.0/src/msdev/helpers/msdev-file-helper-linux-amd64.sha256 +1 -0
- msdev-0.13.0/src/msdev/helpers/msdev-file-helper-linux-arm64 +0 -0
- msdev-0.13.0/src/msdev/helpers/msdev-file-helper-linux-arm64.sha256 +1 -0
- msdev-0.13.0/src/msdev/helpers/msdevd-linux-amd64 +0 -0
- msdev-0.13.0/src/msdev/helpers/msdevd-linux-amd64.sha256 +1 -0
- msdev-0.13.0/src/msdev/helpers/msdevd-linux-arm64 +0 -0
- msdev-0.13.0/src/msdev/helpers/msdevd-linux-arm64.sha256 +1 -0
- msdev-0.13.0/src/msdev/skills/msdev-cli/SKILL.md +182 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/PKG-INFO +105 -77
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/SOURCES.txt +26 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_cli.py +62 -104
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_cli_only_architecture.py +21 -4
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_config.py +1 -1
- msdev-0.13.0/tests/test_config_bundle.py +224 -0
- msdev-0.13.0/tests/test_connect_env_scenario.py +146 -0
- msdev-0.13.0/tests/test_daemon_deploy.py +148 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_env_transfer.py +16 -11
- msdev-0.13.0/tests/test_exec_argv.py +133 -0
- msdev-0.13.0/tests/test_exec_command_scenario.py +152 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_exec_default_timeout_scenario.py +2 -8
- msdev-0.13.0/tests/test_go_msdevd_scenario.py +209 -0
- msdev-0.13.0/tests/test_init_skill.py +241 -0
- msdev-0.13.0/tests/test_model_cli.py +19 -0
- msdev-0.13.0/tests/test_msdev_cli_skill.py +89 -0
- msdev-0.13.0/tests/test_node_connect_provision_scenario.py +104 -0
- msdev-0.13.0/tests/test_node_connect_save_password_scenario.py +87 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_node_env_config.py +1 -1
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_node_env_services.py +17 -8
- msdev-0.13.0/tests/test_node_sync_ssh_scenario.py +76 -0
- msdev-0.13.0/tests/test_sftp_transfer_scenario.py +109 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_ssh_auth.py +75 -58
- msdev-0.13.0/tests/test_ssh_config.py +171 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_target_exec_services.py +17 -4
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_transport.py +99 -41
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_windows_local_scenario.py +15 -15
- msdev-0.11.0/src/msdev/core/exec_argv.py +0 -82
- msdev-0.11.0/tests/test_exec_argv.py +0 -55
- msdev-0.11.0/tests/test_model_cli.py +0 -364
- msdev-0.11.0/tests/test_msdev_cli_skill.py +0 -107
- {msdev-0.11.0 → msdev-0.13.0}/LICENSE +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/setup.cfg +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/__init__.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/config.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/container_helper.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/guides.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/helper_deploy.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/host_files.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/host_mutations.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/inventory.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/limits.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/local_rpc.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/multiplex.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/request_client.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/__init__.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/capabilities.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/execution.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/model.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/npu.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/services/results.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/stream_limits.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/stream_server.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev/core/streamproto.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/dependency_links.txt +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/entry_points.txt +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/src/msdev.egg-info/top_level.txt +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_compat.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_container_helper.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_daemon.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_daemon_container_stream.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_docker_stream_dispatch.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_env_put_get_scenario.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_env_read_write_scenario.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_helper_deploy.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_inventory.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_model_services.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_multiplex.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_request_client.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_ssh_tunnel.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_stream_server.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_stream_transport.py +0 -0
- {msdev-0.11.0 → msdev-0.13.0}/tests/test_streamproto.py +0 -0
- {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.
|
|
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`
|
|
29
|
-
|
|
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
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
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/
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
95
|
-
the
|
|
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
|
-
|
|
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
|
|
104
|
-
|
|
105
|
-
if missing) so later connections
|
|
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
|
-
|
|
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
|
|
132
|
-
|
|
157
|
+
`~/.config/msdev/guides/environments/`. **Node guides** document how to
|
|
158
|
+
connect; **Env guides** document how to initialize shared context (`setup`).
|
|
133
159
|
|
|
134
|
-
|
|
160
|
+
Share a full local configuration (registry + guides) with:
|
|
135
161
|
|
|
136
162
|
```bash
|
|
137
|
-
msdev
|
|
138
|
-
msdev
|
|
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
|
-
|
|
142
|
-
|
|
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-
|
|
172
|
+
msdev env add dev-122-root \
|
|
151
173
|
--node dev-122 \
|
|
152
|
-
--
|
|
153
|
-
--
|
|
154
|
-
|
|
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 ``
|
|
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.
|
|
196
|
-
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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`
|
|
4
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
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/
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
70
|
-
the
|
|
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
|
-
|
|
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
|
|
79
|
-
|
|
80
|
-
if missing) so later connections
|
|
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
|
-
|
|
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
|
|
107
|
-
|
|
132
|
+
`~/.config/msdev/guides/environments/`. **Node guides** document how to
|
|
133
|
+
connect; **Env guides** document how to initialize shared context (`setup`).
|
|
108
134
|
|
|
109
|
-
|
|
135
|
+
Share a full local configuration (registry + guides) with:
|
|
110
136
|
|
|
111
137
|
```bash
|
|
112
|
-
msdev
|
|
113
|
-
msdev
|
|
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
|
-
|
|
117
|
-
|
|
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-
|
|
147
|
+
msdev env add dev-122-root \
|
|
126
148
|
--node dev-122 \
|
|
127
|
-
--
|
|
128
|
-
--
|
|
129
|
-
|
|
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 ``
|
|
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.
|
|
171
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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.
|
|
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 = [
|
|
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"]
|