{"id":50590570,"url":"https://github.com/mutms/mpd","last_synced_at":"2026-06-05T10:01:42.218Z","repository":{"id":359439692,"uuid":"1234709205","full_name":"mutms/mpd","owner":"mutms","description":"Moodle™ Plugin Development Environment","archived":false,"fork":false,"pushed_at":"2026-05-21T22:57:15.000Z","size":1125,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-22T07:04:45.954Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mutms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-10T14:41:31.000Z","updated_at":"2026-05-21T22:57:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mutms/mpd","commit_stats":null,"previous_names":["mutms/mpd"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/mutms/mpd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutms%2Fmpd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutms%2Fmpd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutms%2Fmpd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutms%2Fmpd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mutms","download_url":"https://codeload.github.com/mutms/mpd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutms%2Fmpd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33939226,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-05T10:01:41.362Z","updated_at":"2026-06-05T10:01:42.201Z","avatar_url":"https://github.com/mutms.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mpd — Moodle plugin development environment\n\nA development environment for Moodle plugin work, built so that\n**every dev tool — PHP, Composer, Postgres/MariaDB, Node, even your\nAI coding agent — lives inside a per-project runtime container, not\non your laptop**. You edit code in your usual IDE; the language\nserver, Xdebug, phpunit, composer, and the running Moodle all execute\ninside the container. The result, day to day:\n\n- **`https://\u003cproject\u003e.mpd.test/` for every project** — browser-trusted\n  HTTPS via a name-constrained local CA (signs `*.mpd.test` only),\n  available the moment `mpd start \u003cproject\u003e` returns.\n- **Per-project PHP version.** `MPD_PHP_VERSION=8.4` on one project,\n  `8.2` on the next, simultaneously. No system-wide `php-fpm` to\n  juggle.\n- **Per-project database** (Postgres / MariaDB / MySQL, version of\n  your choice via `MPD_DB=postgres:18` — that's `\u003cengine\u003e:\u003cversion\u003e`,\n  not a port). The matching container provisions on demand; no shared\n  DB server with `mdl_proj1_` / `mdl_proj2_` table prefixing.\n- **Reset to clean state in one verb.** `mdl-data-purge` drops the\n  DB, wipes dataroots, removes the generated config — keeps `mpd.env`\n  and the source tree.\n- **Mailpit per project** at `https://mail.\u003cproject\u003e.mpd.test/` with\n  this project's mail pre-filtered.\n- **Behat + Selenium** auto-wired when a project asks for it\n  (`https://behat.\u003cproject\u003e.mpd.test/`).\n- **No host pollution.** No Homebrew PHP, no system Apache, no\n  `brew upgrade` ever broke your Moodle dev environment because of an\n  unrelated OpenSSL bump.\n\nYour IDE (VS Code Remote-SSH, PHPStorm Gateway) connects to the\nruntime container over SSH — the IDE process stays on your host;\nlanguage server, debugger, and integrated terminal execute inside\nthe container. Your AI agent (Claude Code, Codex, Cursor, Aider) is\n**installed inside the runtime** (one-line install via\n`claude-install`) and runs as a process *in* the container. You\nlaunch it from the SSH session you opened into the runtime; the\nagent shares the same files, same tools, same Moodle install the\nIDE is editing. SSH is a clean integration point — no filesystem-\nmount layer papering over the network, no debate about where the\ncode \"really\" lives. (When the work is on **mpd itself** — Swift\nsources, asset scripts — the agent runs in the VM instead, where\nthe source checkout and toolchain live.)\n\n## Coming from…\n\n- **Homebrew-native PHP + MariaDB.** mpd replaces the\n  `brew install php@8.3 mariadb composer node` stack with per-project\n  containers. The laptop stays clean; per-project PHP/DB versions\n  work simultaneously; `brew upgrade` decisions don't touch your dev\n  environment. Tradeoff: a few seconds of container startup vs\n  millisecond-fast native invocation. Worth it once you've juggled\n  two PHP versions on the same Mac for the third time.\n\n- **[moodle-docker](https://github.com/moodlehq/moodle-docker).**\n  mpd is shaped around the same daily-driver pattern but adds:\n  per-project URLs with real HTTPS (no `localhost:8000`), per-project\n  Mailpit filtering, automatic Behat/Selenium wiring, an\n  SSH-into-runtime workflow that AI agents and IDEs both target, and\n  a hard VM boundary on macOS so the AI agent can't touch your host.\n\n- **[DDEV](https://ddev.com/) / [Lando](https://lando.dev/).** mpd is\n  the Moodle-specific cousin: same per-project URL + auto-TLS\n  philosophy, narrowed to Moodle plugin work, hardened with a VM\n  boundary, and shaped around AI agents as a first-class consumer of\n  the SSH-into-runtime endpoint.\n\n## Two modes\n\n|                      | **Sandbox VM**                                                                           | **`mpd VM`**                                                          |\n|----------------------|------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|\n| **Where `mpd` runs** | Inside the VM                                                                            | Inside a VM (headless by default; GNOME on-demand)                    |\n| **Where you sit**    | Inside the VM (full GNOME desktop)                                                       | On your host (browser + SSH-into-VM)                                  |\n| **Host OS**          | Any (UTM, Parallels, Hyper-V, VirtualBox, virt-manager, VMware…)                         | macOS (primary) — Linux/Windows speculative                           |\n| **Bootstrap**        | Install Debian Trixie + GNOME, snapshot, run one script in the VM                        | `mpd-virt setup` (separate orchestrator binary on the host)           |\n| **Network**          | Internal to the VM (host untouched)                                                      | WireGuard tunnel host↔VM                                              |\n| **Best for**         | Experiments, AI-driven workloads (the VM is the wall; snapshot/revert is the safety net) | Daily-driver Moodle work — host browser/IDE see `*.mpd.test` directly |\n\n**Pick Sandbox if you're unsure or just want to try mpd out quickly.**\nIt's the fastest path to \"real Moodle running locally\" — one VM, one\nscript inside it, no host configuration. You'll be able to migrate to\nstandard `mpd VM` (headless, host-integrated) later without losing\nprojects or DBs once you know which workflow you want.\n\n**Both modes ship GNOME.** Sandbox boots into it; mpd VM defaults to\nheadless to save resources, but GNOME is installed and toggleable on\ndemand — `gnome-start` brings the desktop up (and pins it as the\nboot target until you flip back), `gnome-stop` returns to headless.\nUseful when you occasionally want an in-VM Firefox session or a\nGUI-based debugging tool without committing to a full graphical\nboot every day.\n\n## Get started\n\n### 1. Sandbox VM (recommended)\n\n**Pick a hypervisor** — free and native per OS where possible:\n\n- **macOS (Apple Silicon)**: [UTM](https://mac.getutm.app/) — free,\n  uses Apple's Virtualization.framework directly (no third-party kernel\n  extensions). Or Parallels Desktop / VMware Fusion if you already\n  own them.\n- **Windows 11 Pro/Enterprise**: Hyper-V — built in, enable via\n  \"Turn Windows features on or off.\"\n- **Linux**: virt-manager + KVM — built into most distros; `apt\n  install virt-manager` on Debian/Ubuntu.\n- **Anywhere else**: VirtualBox (free, cross-platform).\n\n**Provision the VM** — Debian Trixie (13) with the GNOME desktop, 8 GB\nRAM and 4 CPUs as a comfortable default (4 GB / 2 CPU minimum), 100 GB\ndisk. When the installer asks for a hostname, type **`mpd-sandbox`**.\nTake a hypervisor snapshot after first boot — that's your safety net.\n\n**Inside the VM**, in a terminal, run:\n\n```bash\nbash \u003c(wget -qO- https://raw.githubusercontent.com/mutms/mpd/main/setup/sandbox/take-over-sandbox-vm.sh)\n```\n\n(That syntax fetches the take-over script and runs it in one step.\n`wget` because Debian's base install ships it; `curl` isn't always\npresent.)\n\nOpen Firefox-ESR inside the VM and browse to https://mpd.test/.\n\n### 2. `mpd VM` (host reaches into a Linux VM)\n\nPick this when you want your laptop's own browser/IDE to resolve\n`*.mpd.test` directly. The matched-host bootstrap configures the host\nside (static route + DNS resolver + CA trust + WireGuard) so the\nlaptop sees the VM's container subnet:\n\n| Host                          | Bootstrap                                                                          |\n|-------------------------------|------------------------------------------------------------------------------------|\n| macOS (Parallels / UTM)       | [mpd-virt-macos](https://github.com/mutms/mpd-virt-macos) — Swift CLI orchestrator |\n| Ubuntu (libvirt/KVM)          | [setup/linux/README.md](setup/linux/README.md)                                     |\n| Windows (Hyper-V)             | [setup/windows/README.txt](setup/windows/README.txt)                               |\n\nThe `mpd-virt-macos` repo ships a `mpd-virt` host binary that drives\nParallels Desktop Pro and UTM (via cloud-init), runs the in-VM\nbootstrap pipeline over SSH, and configures the macOS side (route, DNS\nresolver, CA trust, WireGuard) in one shot. Sibling `mpd-virt-linux` /\n`mpd-virt-windows` repos are planned along the same shape.\n\n## What to expect, timing-wise\n\n- **First-time VM bootstrap**: 5–15 minutes depending on hypervisor\n  speed (image download, apt installs, Swift toolchain, build).\n- **First runtime build** after `mpd --setup`: 3–5 minutes (apt\n  installs for PHP/Node/etc. inside the runtime container).\n- **Subsequent project start** (`mpd start \u003cproject\u003e`): a few seconds.\n- **`demo moodle v5.2.0`** (one-command fully-installed Moodle): a\n  few minutes the first time (runtime + DB + Moodle install in\n  sequence); near-instant on re-runs (just starts the existing\n  project).\n- **VM resume from suspend**: seconds.\n\n## Repository layout\n\n- `bin/` — local built binaries (`bin/mpd`)\n- `mpd/` — Swift control-plane sources (`Action/`, `VM/`, `Runtime/`, `Service/`, …)\n- `assets/` — runtime/service/sidecar definitions and shell scripts\n- `bootstrap/` — VM bring-up steps (passwordless sudo, repo clone, networking, apt, build, WireGuard)\n- `setup/` — per-platform host orchestration (sandbox + matched-host platforms)\n- `docs/` — full documentation tree\n- `/var/lib/mpd/` — runtime state at runtime (created by bootstrap, populated by `mpd --setup`)\n\n## Documentation\n\n- [docs/README.md](docs/README.md) — documentation index, audience-shaped\n- [docs/USAGE.md](docs/USAGE.md) — day-to-day handbook (project lifecycle, SSH into runtime, tools)\n- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — under the hood (contributor reference)\n- [docs/ROADMAP.md](docs/ROADMAP.md) — what's queued next\n\n## Why this exists\n\nmpd grew out of a personal security stance plus a working pattern:\n**I'm using AI agents (Claude Code, Codex) to build and maintain\nMoodle plugins, and I want them inside a sandbox.** I'm not willing\nto install Homebrew, MacPorts, Node, PHP, or Apache on my MacBook,\nand I'm not willing to let an AI agent loose on it either. mpd's\npredecessor ([MDC](https://github.com/skodak/mdc)) gave me speed\nand automation around OrbStack, but OrbStack is closed-source — and\nfor a tool that decides what your browser trusts, I wanted the\ntrust-deciding code to be readable. mpd lives entirely in this repo:\nSwift control plane plus shell tooling on top of Podman, with a\nname-constrained local CA that can only sign for `*.mpd.test` (so a\ncompromise can't impersonate anything else). Sandbox VM is the\nrecommended starting point — a whole hypervisor between your dev\nwork and your host, with snapshot/revert as the safety net for\nletting an agent rip without thinking.\n\n## Acknowledgments\n\nThe design draws on 20 years of Moodle development, the OrbStack-era\n[MDC](https://github.com/skodak/mdc) tooling, and the\n[moodle-docker](https://github.com/moodlehq/moodle-docker) workflow as\nthe public reference everyone reaches for first. mpd is also my first\nfully AI-driven project — the Swift binary, asset scripts, and\ndocumentation are mostly written by [Claude Code](https://claude.ai/code)\n(Anthropic) and [Codex](https://openai.com/codex/) (OpenAI) under my\ndirection. Open source so other Moodle developers can adopt the same\nworkflow.\n\n## License\n\nCopyright (C) 2026 Petr Skoda. [GPL-3.0](LICENSE) or later.\n\nMoodle is a registered trademark of [Moodle Pty Ltd](https://moodle.com).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmutms%2Fmpd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmutms%2Fmpd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmutms%2Fmpd/lists"}