Metadata-Version: 2.4
Name: ntoseye
Version: 0.50.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Software Development :: Debuggers
Classifier: Topic :: Security
Summary: The ntoseye Windows kernel debugger for Linux and macOS: Python SDK and CLI
Keywords: debugger,windows,kernel,kvm,qemu,introspection,windbg
Author: dmaivel
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://ntoseye.com/changelog/
Project-URL: Documentation, https://ntoseye.com/scripting/sdk/
Project-URL: Homepage, https://ntoseye.com
Project-URL: Issues, https://github.com/dmaivel/ntoseye/issues
Project-URL: Repository, https://github.com/dmaivel/ntoseye

# ntoseye

This package lets you control the [ntoseye](https://github.com/dmaivel/ntoseye)
Windows kernel debugger from Python and run it from the command line.

For address-space-bound views and run control, see
[`docs/scripting/sdk.md`](../docs/scripting/sdk.md).

The package also installs the `ntoseye` command, which gives you the REPL,
`ntoseye mcp`, `dap`, and `gdbserver`, and runs Python custom commands from
`~/.ntoseye/commands/`. To install the command in its own environment, run
`uv tool install ntoseye` or `pipx install ntoseye`.

## Install

```sh
pip install ntoseye
```

Or build from source into a virtualenv with maturin:

```sh
cd python
python3 -m venv .venv
source .venv/bin/activate
pip install maturin
maturin develop --release
```

Or build a wheel and install it:

```sh
cd python
maturin build --release --out dist
pip install dist/ntoseye-*.whl
```

## Quick start

```python
import ntoseye

with ntoseye.attach() as dbg:  # defaults to the kd backend
    print(dbg.inspect.version())
    for proc in dbg.processes:
        print(proc.pid, proc.name)
```

For read-only inspection of a paused VM, select `backend="memory"`.

`dbg.processes` holds process handles keyed by PID (`dbg.processes[pid]`), and
each process gives its own memory and modules through `proc.memory` and
`proc.modules`.

## Type stubs

PyO3 introspection generates `ntoseye/_ntoseye.pyi` from the extension, taking
the signatures from the Rust types and the docstrings from the doc comments.

CI fails when the stub in the repository differs from a newly generated one, so
after you change the Rust surface, regenerate the stub and commit the result:

```sh
maturin develop --release --generate-stubs
```

## Tests

```sh
pip install pytest mypy
pytest tests                        # target-free surface tests
mypy --strict -p ntoseye            # the stub and package type-check
NTOSEYE_TEST_BACKEND=kd NTOSEYE_TEST_CONNECT=/tmp/ntoseye-kd.sock pytest tests
NTOSEYE_TEST_BACKEND=gdb NTOSEYE_TEST_CONNECT=127.0.0.1:1234 pytest tests
```

The last two commands also run `tests/test_live.py` and
`tests/test_stub_types.py` on a guest, over KD or QEMU's GDB stub. They break
in, step, set breakpoints on hot kernel functions, and resume the guest. The
tests of breakpoints in the Windows hypervisor, the secure kernel, and guest
partitions need the `gdb` backend, and skip on `kd`.

By default (`auto`), the tests read guest memory from the VM process when they
can. Add `NTOSEYE_TEST_MEMORY_SOURCE=kd` to read it over KD instead, which
needs no root for UTM on macOS and is required for a remote target.

## Releasing portable wheels

The workflow `.github/workflows/release.yml` builds the release wheels with `PyO3/maturin-action` on native GitHub runners:

- The Linux x86-64 and ARM64 wheels build on `ubuntu-22.04` and `ubuntu-24.04-arm` inside the `quay.io/pypa/manylinux_2_28_*` images, which makes them `manylinux_2_28` wheels.
- The Apple Silicon wheel builds on the native ARM64 `macos-14` runner.

Before the upload, each wheel must pass `twine check` and the target-free tests (`tests/test_surface.py`) in a clean virtual environment.

To make a Linux release wheel locally, run this from the repository root (Docker is required):

```sh
docker run --rm -e CARGO_TARGET_DIR=/tmp/target -e HOST_IDS="$(id -u):$(id -g)" \
  -v "$PWD":/io -w /io/python quay.io/pypa/manylinux_2_28_$(uname -m) bash -c '
  dnf install -y clang &&
  curl -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal &&
  source ~/.cargo/env &&
  /opt/python/cp312-cp312/bin/pip install maturin &&
  /opt/python/cp312-cp312/bin/maturin build --release --out dist --compatibility manylinux_2_28 &&
  chown -R "$HOST_IDS" dist'
```
