Metadata-Version: 2.4
Name: msdev
Version: 0.10.1
Summary: Portable nodes and execution environments for msModelSlim development
Author: msModelSlim Agent Contributors
License-Expression: MulanPSL-2.0
Project-URL: Homepage, https://gitcode.com/rookie_hongchuan/msdev
Project-URL: Repository, https://gitcode.com/rookie_hongchuan/msdev
Keywords: ssh,docker,conda,venv,remote,npu,mlops,devops
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# msdev

`msdev` manages connection Nodes and execution Envs. A Node owns SSH and its
per-user `msdevd`; an Env references a Node and adds a host/Docker runtime plus
optional conda/venv/uv layers.

The CLI is intentionally stateless:

- Node-scoped NPU/model operations name `--node` or use `--all`;
- execution names `--env`;
- no harness conversation binding or implicit current Env exists;
- MCP is not part of the architecture.

## Install

```bash
git clone https://gitcode.com/rookie_hongchuan/msdev.git
cd msdev
python3 -m pip install -e .
msdev --help
```

The package installs `msdev` and `msdevd`.

## Windows client

The typical setup is a **Windows laptop talking to Linux Nodes** via OpenSSH
(`C:\Windows\System32\OpenSSH\ssh.exe`). Native Windows OpenSSH does not
implement ControlMaster multiplexing, so msdev:

- omits `ControlMaster`/`ControlPath` on Windows (override with
  `MSDEV_SSH_CONTROL_MASTER=1` only if your SSH client actually supports mux);
- starts a persistent `ssh -L` LocalForward tunnel automatically on the first
  RPC (same role as ControlMaster). Explicit `msdev node connect NODE` is
  optional; disable persist with `MSDEV_SSH_LOCAL_FORWARD_PERSIST=0`;
- reuses that tunnel for captured RPC and default streaming `msdev exec`;
  `env put`/`get` stay on scp/ssh streams (file bytes do not go through JSON RPC);
- hides SSH console windows (`CREATE_NO_WINDOW`) and kills process trees with
  `taskkill /T` on timeout or cancel;
- serves a TCP loopback endpoint for local `msdevd` when this Python build has
  no `AF_UNIX` sockets.

Install with `python -m pip install -e .`. `install-user.py` writes
`msdev.cmd` / `msdevd.cmd` under `%USERPROFILE%\.local\bin`.

Remote paths inside a Linux Env remain POSIX (`/srv/...`). Local `env put`/`get`
on Windows accept Windows absolute paths (`C:\...`).

Local `exec` on Windows wraps Conda with `conda run` and venvs with
`Scripts\activate.bat` (remote Linux Nodes still use POSIX `sh`/`bash` wrappers).
If `ssh` is not on PATH, msdev looks in `%SystemRoot%\System32\OpenSSH\`.

## Nodes and execution environments

Register a host from `~/.ssh/config`:

```bash
msdev node add dev-122 --ssh-host dev-122
msdev node list
msdev node status dev-122
```

Adding a Node atomically creates a same-named host Env. Bootstrap or refresh
the remote user daemon:

```bash
msdev node bootstrap dev-122
```

Persistent OpenSSH masters are optional:

```bash
msdev node connect dev-122
msdev node disconnect dev-122
```

Nodes and Envs have separate private Markdown guides:

```bash
msdev node guide dev-122
msdev node guide dev-122 --write ./dev-122-guide.md
msdev env guide dev-122
msdev env guide dev-122 --write ./host-env-guide.md
```

Guides are stored under `~/.config/msdev/guides/nodes/` and
`~/.config/msdev/guides/environments/`, with private permissions and a 256 KiB
limit. Agents read the applicable guides once before first use in a session.

Open a human-operated interactive shell in an Env:

```bash
msdev env shell dev-122
msdev env shell dev-122 --cwd /srv/project
```

The command allocates an OpenSSH PTY and enters the Env's Docker runtime and
conda/venv/uv layers. Exiting returns
to the local shell. Only the shell session start and final status are visible
to msdev; commands typed inside it are not individually logged. Agent
automation should continue using `msdev exec`.

Create another Env on the same Node for Docker and Python layers:

```bash
msdev env add dev-122-vllm \
  --node dev-122 \
  --docker-container vllm-ascend \
  --layer conda:base \
  --layer venv:/srv/project/.venv
```

## File put, get, read, and write

Bulk transfer copies a local file into an Env filesystem, or fetches one back:

```bash
msdev env put dev-122 ./config.yaml /srv/project/config.yaml
msdev env get dev-122 /srv/project/config.yaml --output ./config.yaml
msdev env get dev-122 /srv/project/config.yaml > ./config.yaml
```

Editing uses content-oriented read/write. Paths inside the Env must be
absolute. Host Envs use direct filesystem copy locally and ``scp``/``ssh``
streams remotely. Docker Envs stage through the node with ``docker cp``.
File bytes never pass through JSON RPC.

```bash
msdev env read dev-122 /srv/project/config.yaml
msdev env read dev-122 /srv/project/config.yaml --json
msdev env write dev-122 /srv/project/note.md --file /tmp/note.md
msdev env write dev-122 /srv/project/note.md < /tmp/note.md
msdev env write dev-122 /srv/project/note.md --file /tmp/note.md \
  --expected-sha256 <digest>
```

Read before replacing an existing file. `--expected-sha256` is compare-and-swap
replacement that refuses to overwrite a changed remote file.

## NPU inventory

```bash
msdev npu list --node dev-122 --json
msdev npu list --all --json
```

## Command execution

Commands execute synchronously and stream stdout and stderr to the terminal as
they are produced. Cursor or Claude Code should use their native background
terminal support for long jobs. Long jobs may also write a persistent progress
log when later inspection is required.

```bash
msdev exec \
  --env dev-122 \
  --cwd /srv/project \
  --timeout-seconds 1800 \
  --env-var MODE=test \
  -- python3 run.py
```

`--timeout-seconds` defaults to `-1` (no deadline). Any positive finite duration
is also accepted. A positive timeout kills the complete command
process group and returns exit code 124. Cancelling the local CLI closes the RPC
connection, causing `msdevd` to kill and reap the remote process group. Finite
SSH/Unix RPC deadlines include a short completion grace for output drain and
serialization.

`--result-json` selects captured, non-streaming execution and prints one
structured JSON result containing stdout and stderr.

## Model inventory

Examples:

```bash
msdev model discover --node dev-122 --root /data/models
msdev model list --node dev-122 --json
msdev model list --all --json
msdev model inspect model://qwen/Qwen3-32B@main --node dev-122
msdev model validate model://qwen/Qwen3-32B@main --node dev-122
msdev model audit --node dev-122
```

Use `msdev model --help` and the individual subcommand help for register,
update, replicas, refresh, verify, export, import, and rebind.

## Architecture

```text
msdev CLI
  -> typed core service
  -> UnixRpcTransport or SshRpcTransport
  -> per-user msdevd
  -> host/container command, env file transfer, NPU, or inventory
```

Remote RPC responses and command output are bounded. Node/Env registries use
locked atomic updates.

## Testing

```bash
python3 -m unittest discover -s tests -v
```

Feature work must include at least one actual scenario test on the real
control path (`msdev` CLI → service → transport → `msdevd` → effect). Unit
tests alone are not sufficient.
