pyro-mcp/README.md
Thales Maciel 663241d5d2 Add daily-loop prepare and readiness checks
Make the local chat-host loop explicit and cheap so users can warm the machine once instead of rediscovering environment and guest setup on every session.

Add cache-backed daily-loop manifests plus the new `pyro prepare` flow, extend `pyro doctor --environment` with warm/cold/stale readiness reporting, and add `make smoke-daily-loop` to prove the warmed repro-fix reset path end to end.

Also fix `python -m pyro_mcp.cli` to invoke `main()` so the new smoke and `dist-check` actually exercise the CLI module, and update the docs/roadmap to present `doctor -> prepare -> connect host -> reset` as the recommended daily path.

Validation: `uv lock`, `UV_OFFLINE=1 UV_CACHE_DIR=.uv-cache make check`, `UV_OFFLINE=1 UV_CACHE_DIR=.uv-cache make dist-check`, and `UV_OFFLINE=1 UV_CACHE_DIR=.uv-cache make smoke-daily-loop`.
2026-03-13 21:17:59 -03:00

299 lines
9.8 KiB
Markdown

# pyro-mcp
`pyro-mcp` is a disposable MCP workspace for chat-based coding agents such as
Claude Code, Codex, and OpenCode.
It is built for Linux `x86_64` hosts with working KVM. The product path is:
1. prove the host works
2. connect a chat host over MCP
3. let the agent work inside a disposable workspace
4. validate the workflow with the recipe-backed smoke pack
`pyro-mcp` currently has no users. Expect breaking changes while this chat-host
path is still being shaped.
This repo is not trying to be a generic VM toolkit, a CI runner, or an
SDK-first platform.
[![PyPI version](https://img.shields.io/pypi/v/pyro-mcp.svg)](https://pypi.org/project/pyro-mcp/)
## Start Here
- Install and zero-to-hero path: [docs/install.md](docs/install.md)
- First run transcript: [docs/first-run.md](docs/first-run.md)
- Chat host integrations: [docs/integrations.md](docs/integrations.md)
- Use-case recipes: [docs/use-cases/README.md](docs/use-cases/README.md)
- Vision: [docs/vision.md](docs/vision.md)
- Public contract: [docs/public-contract.md](docs/public-contract.md)
- Host requirements: [docs/host-requirements.md](docs/host-requirements.md)
- Troubleshooting: [docs/troubleshooting.md](docs/troubleshooting.md)
- Stable workspace walkthrough GIF: [docs/assets/workspace-first-run.gif](docs/assets/workspace-first-run.gif)
- Terminal walkthrough GIF: [docs/assets/first-run.gif](docs/assets/first-run.gif)
- What's new in 4.5.0: [CHANGELOG.md#450](CHANGELOG.md#450)
- PyPI package: [pypi.org/project/pyro-mcp](https://pypi.org/project/pyro-mcp/)
## Who It's For
- Claude Code users who want disposable workspaces instead of running directly
on the host
- Codex users who want an MCP-backed sandbox for repo setup, bug fixing, and
evaluation loops
- OpenCode users who want the same disposable workspace model
- people evaluating repo setup, test, and app-start workflows from a chat
interface on a clean machine
If you want a general VM platform, a queueing system, or a broad SDK product,
this repo is intentionally biased away from that story.
## Quickstart
Use either of these equivalent quickstart paths:
```bash
# Package without install
python -m pip install uv
uvx --from pyro-mcp pyro doctor
uvx --from pyro-mcp pyro prepare debian:12
uvx --from pyro-mcp pyro run debian:12 -- git --version
```
![Quickstart walkthrough](docs/assets/first-run.gif)
```bash
# Already installed
pyro doctor
pyro prepare debian:12
pyro run debian:12 -- git --version
```
From a repo checkout, replace `pyro` with `uv run pyro`.
What success looks like:
```bash
Platform: linux-x86_64
Runtime: PASS
Catalog version: 4.4.0
...
[pull] phase=install environment=debian:12
[pull] phase=ready environment=debian:12
Pulled: debian:12
...
[run] phase=create environment=debian:12
[run] phase=start vm_id=...
[run] phase=execute vm_id=...
[run] environment=debian:12 execution_mode=guest_vsock exit_code=0 duration_ms=...
git version ...
```
The first pull downloads an OCI environment from public Docker Hub, requires
outbound HTTPS access to `registry-1.docker.io`, and needs local cache space
for the guest image. `pyro prepare debian:12` performs that install step
automatically, then proves create, exec, reset, and delete on one throwaway
workspace so the daily loop is warm before the chat host connects.
## Chat Host Quickstart
After the quickstart works, make the daily loop explicit before you connect the
chat host:
```bash
uvx --from pyro-mcp pyro doctor --environment debian:12
uvx --from pyro-mcp pyro prepare debian:12
```
Then connect a chat host in one named mode. Use the helper flow first:
```bash
uvx --from pyro-mcp pyro host connect codex --mode repro-fix
uvx --from pyro-mcp pyro host connect codex --mode inspect
uvx --from pyro-mcp pyro host connect claude-code --mode cold-start
uvx --from pyro-mcp pyro host connect claude-code --mode review-eval
uvx --from pyro-mcp pyro host print-config opencode --mode repro-fix
```
If setup drifts or you want to inspect it first:
```bash
uvx --from pyro-mcp pyro host doctor
uvx --from pyro-mcp pyro host repair claude-code
uvx --from pyro-mcp pyro host repair codex
uvx --from pyro-mcp pyro host repair opencode
```
Those helpers wrap the same `pyro mcp serve` entrypoint. Use a named mode when
one workflow already matches the job. Fall back to the generic no-mode path
when the mode feels too narrow.
Mode examples:
```bash
uvx --from pyro-mcp pyro mcp serve --mode repro-fix
uvx --from pyro-mcp pyro mcp serve --mode inspect
uvx --from pyro-mcp pyro mcp serve --mode cold-start
uvx --from pyro-mcp pyro mcp serve --mode review-eval
```
Generic escape hatch:
```bash
uvx --from pyro-mcp pyro mcp serve
```
From a repo root, the generic path auto-detects the current Git checkout and
lets the first `workspace_create` omit `seed_path`. If the host does not
preserve the server working directory, use:
```bash
uvx --from pyro-mcp pyro host connect codex --project-path /abs/path/to/repo
uvx --from pyro-mcp pyro mcp serve --project-path /abs/path/to/repo
```
If you are starting outside a local checkout, use a clean clone source:
```bash
uvx --from pyro-mcp pyro host connect codex --repo-url https://github.com/example/project.git
uvx --from pyro-mcp pyro mcp serve --repo-url https://github.com/example/project.git
```
Copy-paste host-specific starts:
- Claude Code: [examples/claude_code_mcp.md](examples/claude_code_mcp.md)
- Codex: [examples/codex_mcp.md](examples/codex_mcp.md)
- OpenCode: [examples/opencode_mcp_config.json](examples/opencode_mcp_config.json)
- Generic MCP config: [examples/mcp_client_config.md](examples/mcp_client_config.md)
Claude Code cold-start or review-eval:
```bash
claude mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --mode cold-start
```
Codex repro-fix or inspect:
```bash
codex mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --mode repro-fix
```
OpenCode `opencode.json` snippet:
```json
{
"mcp": {
"pyro": {
"type": "local",
"enabled": true,
"command": ["uvx", "--from", "pyro-mcp", "pyro", "mcp", "serve", "--mode", "repro-fix"]
}
}
}
```
If OpenCode launches the server from an unexpected cwd, use
`pyro host print-config opencode --project-path /abs/path/to/repo` or add
`"--project-path", "/abs/path/to/repo"` after `"serve"` in the same command
array.
If `pyro-mcp` is already installed, replace `uvx --from pyro-mcp pyro` with
`pyro` in the same command or config shape.
Use the generic no-mode path when the named mode feels too narrow. Move to
`--profile workspace-full` only when the chat truly needs shells, services,
snapshots, secrets, network policy, or disk tools.
## Zero To Hero
1. Validate the host with `pyro doctor`.
2. Warm the machine-level daily loop with `pyro prepare debian:12`.
3. Prove guest execution with `pyro run debian:12 -- git --version`.
4. Connect Claude Code, Codex, or OpenCode with one named mode such as
`pyro host connect codex --mode repro-fix`, then fall back to raw
`pyro mcp serve --mode ...` or the generic no-mode path when needed.
5. Start with one recipe from [docs/use-cases/README.md](docs/use-cases/README.md).
`repro-fix` is the shortest chat-first mode and story.
6. Use `workspace reset` as the normal retry step inside that warmed loop.
7. Use `make smoke-use-cases` as the trustworthy guest-backed verification path
for the advertised workflows.
That is the intended user journey. The terminal commands exist to validate and
debug that chat-host path, not to replace it as the main product story.
## Manual Terminal Workspace Flow
If you want to understand what the agent gets inside the sandbox, or debug a
recipe outside the chat host, use the terminal companion flow below:
```bash
uv tool install pyro-mcp
WORKSPACE_ID="$(pyro workspace create debian:12 --seed-path ./repo --name repro-fix --label issue=123 --id-only)"
pyro workspace list
pyro workspace sync push "$WORKSPACE_ID" ./changes
pyro workspace file read "$WORKSPACE_ID" note.txt --content-only
pyro workspace patch apply "$WORKSPACE_ID" --patch-file fix.patch
pyro workspace exec "$WORKSPACE_ID" -- cat note.txt
pyro workspace summary "$WORKSPACE_ID"
pyro workspace snapshot create "$WORKSPACE_ID" checkpoint
pyro workspace reset "$WORKSPACE_ID" --snapshot checkpoint
pyro workspace export "$WORKSPACE_ID" note.txt --output ./note.txt
pyro workspace delete "$WORKSPACE_ID"
```
Add `workspace-full` only when the chat or your manual debugging loop really
needs:
- persistent PTY shells
- long-running services and readiness probes
- guest networking and published ports
- secrets
- stopped-workspace disk inspection
The five recipe docs show when those capabilities are justified:
[docs/use-cases/README.md](docs/use-cases/README.md)
## Official Environments
Current official environments in the shipped catalog:
- `debian:12`
- `debian:12-base`
- `debian:12-build`
The embedded Firecracker runtime ships with the package. Official environments
are pulled as OCI artifacts from public Docker Hub into a local cache on first
use or through `pyro env pull`. End users do not need registry credentials to
pull or run the official environments.
## Contributor Workflow
For work inside this repository:
```bash
make help
make setup
make check
make dist-check
```
Contributor runtime sources live under `runtime_sources/`. The packaged runtime
bundle under `src/pyro_mcp/runtime_bundle/` contains the embedded boot/runtime
assets plus manifest metadata. End-user environment installs pull
OCI-published environments by default. Use
`PYRO_RUNTIME_BUNDLE_DIR=build/runtime_bundle` only when you are explicitly
validating a locally built contributor runtime bundle.
Official environment publication is performed locally against Docker Hub:
```bash
export DOCKERHUB_USERNAME='your-dockerhub-username'
export DOCKERHUB_TOKEN='your-dockerhub-token'
make runtime-materialize
make runtime-publish-official-environments-oci
```
For a local PyPI publish:
```bash
export TWINE_PASSWORD='pypi-...'
make pypi-publish
```