Metadata-Version: 2.5
Name: desktop-monkey
Version: 0.1.1
Summary: Desktop Commander-parity remote MCP plus a device mesh that pools compute, GPU, RAM and disk across your own machines.
Project-URL: Homepage, https://github.com/Arcane-Fly/desktop-monkey
Project-URL: Issues, https://github.com/Arcane-Fly/desktop-monkey/issues
Author: Braden Pty Ltd / Arcane-Fly
License: MIT
License-File: LICENSE
License-File: NOTICE
Keywords: agent-hooks,desktop-commander,distributed,llm,mcp,mesh,remote-mcp
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development
Classifier: Topic :: System :: Distributed Computing
Requires-Python: >=3.12
Requires-Dist: cryptography>=44
Requires-Dist: httpx>=0.28
Requires-Dist: jsonschema>=4.23
Requires-Dist: orjson>=3.10
Requires-Dist: psutil>=6.1
Requires-Dist: pydantic>=2.11
Requires-Dist: pyhpke>=0.6.3
Requires-Dist: qig-coordizer>=0.1.0
Requires-Dist: qig-warp>=0.6.10
Requires-Dist: typer>=0.15
Requires-Dist: websockets>=15
Provides-Extra: all
Requires-Dist: aiosqlite>=0.20; extra == 'all'
Requires-Dist: argon2-cffi>=23.1; extra == 'all'
Requires-Dist: asyncpg>=0.30; extra == 'all'
Requires-Dist: charset-normalizer>=3.4; extra == 'all'
Requires-Dist: dask>=2025.1; extra == 'all'
Requires-Dist: markdown-it-py>=3.0; extra == 'all'
Requires-Dist: numpy>=2.0; extra == 'all'
Requires-Dist: nvidia-ml-py>=12.560; (sys_platform != 'darwin') and extra == 'all'
Requires-Dist: openpyxl>=3.1; extra == 'all'
Requires-Dist: pyjwt[crypto]>=2.10; extra == 'all'
Requires-Dist: pypdf>=5; extra == 'all'
Requires-Dist: pywinpty>=2.0; (sys_platform == 'win32') and extra == 'all'
Requires-Dist: qig-compute>=0.9.10; extra == 'all'
Requires-Dist: ray>=2.40; extra == 'all'
Requires-Dist: reportlab>=4.2; extra == 'all'
Requires-Dist: sqlalchemy[asyncio]>=2.0.36; extra == 'all'
Requires-Dist: starlette>=0.46; extra == 'all'
Requires-Dist: uvicorn[standard]>=0.34; extra == 'all'
Requires-Dist: weightspace>=0.3; extra == 'all'
Requires-Dist: zeroconf>=0.140; extra == 'all'
Provides-Extra: commander
Requires-Dist: charset-normalizer>=3.4; extra == 'commander'
Requires-Dist: markdown-it-py>=3.0; extra == 'commander'
Requires-Dist: openpyxl>=3.1; extra == 'commander'
Requires-Dist: pypdf>=5; extra == 'commander'
Requires-Dist: pywinpty>=2.0; (sys_platform == 'win32') and extra == 'commander'
Requires-Dist: reportlab>=4.2; extra == 'commander'
Provides-Extra: dev
Requires-Dist: anyio>=4.8; extra == 'dev'
Requires-Dist: dask>=2025.1; extra == 'dev'
Requires-Dist: mcp>=1.9; extra == 'dev'
Requires-Dist: mypy>=1.14; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.25; extra == 'dev'
Requires-Dist: pytest-timeout>=2.3; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: qig-compute>=0.9.10; extra == 'dev'
Requires-Dist: ray>=2.40; extra == 'dev'
Requires-Dist: ruff>=0.9; extra == 'dev'
Requires-Dist: weightspace>=0.3; extra == 'dev'
Provides-Extra: fabric
Requires-Dist: dask>=2025.1; extra == 'fabric'
Requires-Dist: ray>=2.40; extra == 'fabric'
Provides-Extra: mesh
Requires-Dist: numpy>=2.0; extra == 'mesh'
Requires-Dist: nvidia-ml-py>=12.560; (sys_platform != 'darwin') and extra == 'mesh'
Requires-Dist: zeroconf>=0.140; extra == 'mesh'
Provides-Extra: qig
Requires-Dist: qig-compute>=0.9.10; extra == 'qig'
Provides-Extra: relay
Requires-Dist: aiosqlite>=0.20; extra == 'relay'
Requires-Dist: argon2-cffi>=23.1; extra == 'relay'
Requires-Dist: asyncpg>=0.30; extra == 'relay'
Requires-Dist: pyjwt[crypto]>=2.10; extra == 'relay'
Requires-Dist: sqlalchemy[asyncio]>=2.0.36; extra == 'relay'
Requires-Dist: starlette>=0.46; extra == 'relay'
Requires-Dist: uvicorn[standard]>=0.34; extra == 'relay'
Provides-Extra: weightspace
Requires-Dist: weightspace>=0.3; extra == 'weightspace'
Description-Content-Type: text/markdown

# Desktop Monkey

> Your machines, one troop. A Desktop Commander–parity **remote MCP** plus a **device mesh** that
> pools compute, GPU, RAM and disk across the PCs and laptops you own.

**Status:** under construction — see [`docs/DONE-CONTRACT.json`](docs/DONE-CONTRACT.json) for the
machine-checkable list of what "finished" means and [`docs/STATUS.md`](docs/STATUS.md) for the live
done/asked count.

## What it is

1. **Commander layer** — 100% tool-surface and service parity with
   [Desktop Commander Remote MCP](https://mcp.desktopcommander.app/): every MCP tool, plus the
   hosted pieces (device enrolment, tunnel, per-client OAuth, usage metering, tool-call log,
   revoke/share, settings). Parity is tracked in [`docs/parity/`](docs/parity/).
2. **Troop mesh** — concurrent coordination of several machines: *primary + support*, *several
   supports*, rings and chains. Work is split so that no single machine has to carry the compute,
   GPU memory, RAM or disk. See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
3. **Hooks** — an improved, typed, auditable hook engine (lessons from Claude Code, Codex and
   Cursor hooks) that also fires on mesh events.
4. **Monkey Monitor entry point** — the local GTK app
   ([`monkey-projects/monkey-monitor`](../monkey-projects/monkey-monitor)) is the local front door;
   Desktop Monkey shares its colour tokens and logo.

## Layout

One Python package, `src/desktop_monkey/` (the earlier `packages/` / `services/` / `apps/` split was
never built):

| Path | Purpose |
|---|---|
| `src/desktop_monkey/protocol` | MCP tool schemas + mesh wire messages |
| `src/desktop_monkey/commander` | Desktop Commander–parity MCP server |
| `src/desktop_monkey/agent` | Per-device daemon |
| `src/desktop_monkey/mesh` | Mesh scheduling, placement and pooling |
| `src/desktop_monkey/relay` | Control plane + tunnel (deployed on Railway) |
| `src/desktop_monkey/hooks` | Hook engine and adapters |
| `src/desktop_monkey/learning` | Learning experiments |
| `src/desktop_monkey/monitor` | Monkey Monitor integration |
| `src/desktop_monkey/security` | Security helpers |
| `src/desktop_monkey/theme`, `theme/` | Colour + logo tokens shared with Monkey Monitor |
| `tests/` | Test suite |
| `deploy/` | `targets.json` (pinned IDs) + `guard.py` (deploy isolation check) |
| `scripts/` | Dev and operator scripts (`connect_relay_db.sh`, …) |
| `supabase/migrations/` | Mesh schema on supabase-monkey-one (`public.mesh_*`, RLS on) |
| `docs/` | Vision, architecture, ADRs, parity matrix, research |

## Live hub

The mesh relay is deployed on Railway as the central hub. This section lists its endpoints;
current health is in [`docs/STATUS.md`](docs/STATUS.md).

| | |
|---|---|
| **Public URL** | `https://relay-production-ef48.up.railway.app` |
| **Health** | `GET /health` → `{"status":"ok"}` |
| **MCP endpoint** | `POST /mcp` (OAuth 2.1 bearer token, PKCE S256; 401 without token) |
| **Device mesh tunnel** | `wss://relay-production-ef48.up.railway.app/tunnel` |
| **OAuth discovery** | `/.well-known/oauth-authorization-server` (issuer = public URL) |
| **JWKS** | `/.well-known/jwks.json` (ES256) |
| **Device enrolment** | `/device/start` → `/device/poll` → `/device/verify` (device-code flow) |
| **Device API** | `/api/devices` (pause / resume / revoke) |

Devices and MCP clients connect to the public URL above; `RELAY_PUBLIC_URL` is set
on the Railway `relay` service so the OAuth issuer matches. The image is built from
the repo `Dockerfile` (`pip install '.[relay]'`), which pins the relay extras the
platform builder would otherwise skip.

## Rules of the road

Read [`AGENTS.md`](AGENTS.md) before touching anything — especially the deploy-isolation rules.
