Make the docs and help text unapologetically teach as the product path for Claude Code, Codex, and OpenCode on Linux KVM.
Rewrite the README, install/first-run/integration guides, public contract, vision, and use-case docs around the zero-to-hero chat flow, and explicitly note that there are no users yet so breaking changes are acceptable while the interface is still being shaped.
Update package metadata, CLI help, and the docs/help expectation tests to match the new positioning. Validate the reframe with usage: pyro [-h] [--version] COMMAND ...
Validate the host and serve disposable MCP workspaces for chat-based coding agents on supported Linux x86_64 KVM hosts.
positional arguments:
COMMAND
env Inspect and manage curated environments.
mcp Run the MCP server.
run Run one command inside an ephemeral VM.
workspace Manage persistent workspaces.
doctor Inspect runtime and host diagnostics.
demo Run built-in demos.
options:
-h, --help show this help message and exit
--version show program's version number and exit
Suggested zero-to-hero path:
pyro doctor
pyro env list
pyro env pull debian:12
pyro run debian:12 -- git --version
pyro mcp serve
Connect a chat host after that:
claude mcp add pyro -- uvx --from pyro-mcp pyro mcp serve
codex mcp add pyro -- uvx --from pyro-mcp pyro mcp serve
If you want terminal-level visibility into the workspace model:
pyro workspace create debian:12 --seed-path ./repo --id-only
pyro workspace sync push WORKSPACE_ID ./changes
pyro workspace exec WORKSPACE_ID -- cat note.txt
pyro workspace diff WORKSPACE_ID
pyro workspace snapshot create WORKSPACE_ID checkpoint
pyro workspace reset WORKSPACE_ID --snapshot checkpoint
pyro workspace shell open WORKSPACE_ID --id-only
pyro workspace service start WORKSPACE_ID app --ready-file .ready -- sh -lc 'touch .ready && while true; do sleep 60; done'
pyro workspace export WORKSPACE_ID note.txt --output ./note.txt, usage: pyro mcp serve [-h] [--profile {vm-run,workspace-core,workspace-full}]
Expose pyro tools over stdio for an MCP client. Bare `pyro mcp serve` now starts `workspace-core`, the recommended first profile for most chat hosts.
options:
-h, --help show this help message and exit
--profile {vm-run,workspace-core,workspace-full}
Expose only one model-facing tool profile. `workspace-
core` is the default and recommended first profile for
most chat hosts; `workspace-full` is the larger opt-in
profile. (default: workspace-core)
Default and recommended first start:
pyro mcp serve
Profiles:
workspace-core: default for normal persistent chat editing
vm-run: smallest one-shot-only surface
workspace-full: larger opt-in surface for shells, services,
snapshots, secrets, network policy, and disk tools
Use --profile workspace-full only when the host truly needs those
extra workspace capabilities., and uv run ruff check .
All checks passed!
uv run mypy
Success: no issues found in 61 source files
uv run pytest -n auto
============================= test session starts ==============================
platform linux -- Python 3.12.10, pytest-9.0.2, pluggy-1.6.0
rootdir: /home/thales/projects/personal/pyro
configfile: pyproject.toml
testpaths: tests
plugins: anyio-4.12.1, xdist-3.8.0, cov-7.0.0
created: 32/32 workers
32 workers [393 items]
........................................................................ [ 18%]
........................................................................ [ 36%]
........................................................................ [ 54%]
........................................................................ [ 73%]
........................................................................ [ 91%]
................................. [100%]
=============================== warnings summary ===============================
../../../.local/share/uv/python/cpython-3.12.10-linux-x86_64-gnu/lib/python3.12/importlib/metadata/__init__.py:467: 32 warnings
/home/thales/.local/share/uv/python/cpython-3.12.10-linux-x86_64-gnu/lib/python3.12/importlib/metadata/__init__.py:467: DeprecationWarning: Implicit None on return values is deprecated and will raise KeyErrors.
return self.metadata['Version']
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.12.10-final-0 _______________
Name Stmts Miss Cover Missing
-------------------------------------------------------------------------
src/pyro_mcp/__init__.py 25 0 100%
src/pyro_mcp/api.py 307 7 98% 37-38, 63, 69, 72, 75, 548
src/pyro_mcp/cli.py 1132 141 88% 288-289, 332-333, 336, 344, 367-368, 394-395, 398, 406, 450, 460-461, 464, 477, 483-484, 498-499, 502, 566-575, 592-593, 596, 635, 2180, 2182, 2226, 2236, 2280, 2284-2285, 2295, 2302, 2344-2351, 2392, 2409-2414, 2459-2461, 2470-2472, 2483-2485, 2494-2496, 2503-2505, 2510-2512, 2523-2528, 2530, 2541-2546, 2567-2572, 2574, 2589-2594, 2596, 2608, 2623, 2637, 2655-2660, 2669-2674, 2676, 2683-2688, 2690, 2701-2706, 2708, 2719-2724, 2726, 2737-2742, 2764, 2787, 2806, 2824, 2841, 2899, 3017
src/pyro_mcp/contract.py 52 0 100%
src/pyro_mcp/demo.py 16 0 100%
src/pyro_mcp/doctor.py 12 0 100%
src/pyro_mcp/ollama_demo.py 245 6 98% 289, 294, 299, 318, 439, 550
src/pyro_mcp/runtime.py 142 14 90% 80, 84, 88, 92, 120, 130, 144, 173, 182, 194, 230-232, 262
src/pyro_mcp/runtime_boot_check.py 33 0 100%
src/pyro_mcp/runtime_build.py 546 47 91% 92, 127, 181, 189, 238-240, 263-265, 300, 325, 331, 340-341, 343, 392, 396, 413, 416, 492-494, 497-499, 522, 525, 578, 615, 620, 646-647, 649, 686, 688, 694, 697, 725, 765, 779, 791, 805, 808, 1002, 1009, 1198
src/pyro_mcp/runtime_bundle/__init__.py 0 0 100%
src/pyro_mcp/runtime_network_check.py 15 0 100%
src/pyro_mcp/server.py 8 0 100%
src/pyro_mcp/vm_environments.py 386 55 86% 128, 131, 267, 274, 281, 304-306, 329-331, 352-353, 355, 380, 382, 392-394, 415, 418, 421, 429, 431, 436-437, 446-448, 488, 495-496, 502, 515, 526, 539, 546, 549, 570, 596, 599, 608-609, 613, 617, 626, 629, 636, 644, 647, 659, 667, 676, 682, 685
src/pyro_mcp/vm_firecracker.py 47 0 100%
src/pyro_mcp/vm_guest.py 206 22 89% 139, 142, 173, 176, 202, 205, 208, 211, 217, 239, 262-279, 291, 313, 633-634, 643
src/pyro_mcp/vm_manager.py 2846 355 88% 625, 642, 650-657, 677, 684, 688, 712-715, 795-796, 818, 828, 830, 845, 853-855, 858, 870, 872, 881, 889, 892, 901-902, 910, 913, 919, 926, 929, 933, 951-955, 1010-1011, 1050, 1096, 1102, 1114, 1150, 1156, 1159, 1168, 1170, 1173-1177, 1230, 1236, 1239, 1248, 1250, 1253-1257, 1268, 1277, 1280, 1284-1290, 1319, 1322-1324, 1326, 1333, 1335, 1345, 1347, 1349, 1352-1353, 1361, 1377, 1379, 1381, 1391, 1403-1404, 1408, 1424, 1440-1441, 1443, 1447, 1450-1451, 1469, 1476, 1488, 1505, 1508-1509, 1511, 1582-1583, 1586-1588, 1599, 1602, 1605, 1617, 1638, 1649-1650, 1657-1658, 1669-1671, 1781, 1792-1798, 1808, 1860, 1870, 1891, 1894-1895, 1901-1904, 1910, 1922-1962, 1991-1993, 2034, 2046-2047, 2077, 2146, 2175, 2524-2528, 2598-2602, 2614, 2720, 3563, 3577, 3580, 3583, 3648-3653, 3720, 3802, 3842-3843, 3846-3847, 3862-3863, 3914, 4194, 4229, 4232, 4237, 4250, 4254, 4263, 4277, 4316, 4349, 4444, 4472-4473, 4477-4478, 4504, 4530-4531, 4576, 4578, 4600-4601, 4629, 4631, 4661-4662, 4681-4682, 4734, 4738, 4741-4743, 4745, 4747, 4776-4777, 4809-4845, 4863-4864, 4903, 4905, 4934, 4954-4955, 4977, 4988-4990, 5036, 5049-5050, 5059-5061, 5104-5105, 5171-5178, 5189-5192, 5203, 5208, 5216-5230, 5240, 5473-5476, 5485-5490, 5498-5503, 5513, 5557, 5577, 5601-5602, 5678-5680, 5706-5725, 5784, 5789, 5804, 5832, 5836, 5848, 5884-5886, 5946, 5950, 6079, 6111, 6155, 6170, 6189, 6201, 6242, 6251, 6256, 6269, 6274, 6296, 6394, 6422-6423
src/pyro_mcp/vm_network.py 134 22 84% 65-66, 139, 201, 203, 205, 226, 317-331, 350-351, 360, 362, 372-384
src/pyro_mcp/workspace_disk.py 164 0 100%
src/pyro_mcp/workspace_files.py 293 0 100%
src/pyro_mcp/workspace_ports.py 79 1 99% 116
src/pyro_mcp/workspace_shell_output.py 88 2 98% 16, 61
src/pyro_mcp/workspace_shells.py 235 26 89% 105-118, 193-194, 226-227, 230-235, 251, 257-259, 263, 270-271, 299, 301, 303, 306-307
src/pyro_mcp/workspace_use_case_smokes.py 216 8 96% 131, 134-135, 423-426, 490
-------------------------------------------------------------------------
TOTAL 7227 706 90%
Required test coverage of 90% reached. Total coverage: 90.23%
======================= 393 passed, 32 warnings in 5.60s =======================.
199 lines
5.1 KiB
Markdown
199 lines
5.1 KiB
Markdown
# Vision
|
|
|
|
`pyro-mcp` should become the disposable MCP workspace for chat-based coding
|
|
agents.
|
|
|
|
That is a different product from a generic VM wrapper, a secure CI runner, or
|
|
an SDK-first platform.
|
|
|
|
`pyro-mcp` currently has no users. That means we can still make breaking
|
|
changes freely while we shape the chat-host path into the right product.
|
|
|
|
## Core Thesis
|
|
|
|
The goal is not just to run one command in a microVM.
|
|
|
|
The goal is to give a chat-hosted coding agent a bounded workspace where it can:
|
|
|
|
- inspect a repo
|
|
- install dependencies
|
|
- edit files
|
|
- run tests
|
|
- start and inspect services
|
|
- reset and retry
|
|
- export patches and artifacts
|
|
- destroy the sandbox when the task is done
|
|
|
|
The sandbox is the execution boundary for agentic software work.
|
|
|
|
## Current Product Focus
|
|
|
|
The product path should be obvious and narrow:
|
|
|
|
- Claude Code
|
|
- Codex
|
|
- OpenCode
|
|
- Linux `x86_64` with KVM
|
|
|
|
The happy path is:
|
|
|
|
1. prove the host with the terminal companion commands
|
|
2. run `pyro mcp serve`
|
|
3. connect a chat host
|
|
4. work through one disposable workspace per task
|
|
|
|
The repo can contain lower-level building blocks, but they should not drive the
|
|
product story.
|
|
|
|
## What This Is Not
|
|
|
|
`pyro-mcp` should not drift into:
|
|
|
|
- a YAML pipeline system
|
|
- a build farm
|
|
- a generic CI job runner
|
|
- a scheduler or queueing platform
|
|
- a broad VM orchestration product
|
|
- an SDK product that happens to have an MCP server on the side
|
|
|
|
Those products optimize for queued work, throughput, retries, matrix builds, or
|
|
library ergonomics.
|
|
|
|
`pyro-mcp` should optimize for agent loops:
|
|
|
|
- explore
|
|
- edit
|
|
- test
|
|
- observe
|
|
- reset
|
|
- export
|
|
|
|
## Why This Can Look Like CI
|
|
|
|
Any sandbox product starts to look like CI if the main abstraction is:
|
|
|
|
- submit a command
|
|
- wait
|
|
- collect logs
|
|
- fetch artifacts
|
|
|
|
That shape is useful, but it is not the center of the vision.
|
|
|
|
To stay aligned, the primary abstraction should be a workspace the agent
|
|
inhabits from a chat host, not a job the agent submits to a runner.
|
|
|
|
## Product Principles
|
|
|
|
### Chat Hosts First
|
|
|
|
The product should be shaped around the MCP path used from chat interfaces.
|
|
Everything else is there to support, debug, or build that path.
|
|
|
|
### Workspace-First
|
|
|
|
The default mental model should be "open a disposable workspace" rather than
|
|
"enqueue a task".
|
|
|
|
### Stateful Interaction
|
|
|
|
The product should support repeated interaction in one sandbox. One-shot command
|
|
execution matters, but it is the entry point, not the destination.
|
|
|
|
### Explicit Host Crossing
|
|
|
|
Anything that crosses the host boundary should be intentional and visible:
|
|
|
|
- seeding a workspace
|
|
- syncing changes in
|
|
- exporting artifacts out
|
|
- granting secrets or network access
|
|
|
|
### Reset Over Repair
|
|
|
|
Agents should be able to checkpoint, reset, and retry cheaply. Disposable state
|
|
is a feature, not a limitation.
|
|
|
|
### Agent-Native Observability
|
|
|
|
The sandbox should expose the things an agent actually needs to reason about:
|
|
|
|
- command output
|
|
- file diffs
|
|
- service status
|
|
- logs
|
|
- readiness
|
|
- exported results
|
|
|
|
## The Shape Of The Product
|
|
|
|
The strongest direction is a small chat-facing contract built around:
|
|
|
|
- one MCP server
|
|
- one disposable workspace model
|
|
- structured file inspection and edits
|
|
- repeated commands in the same sandbox
|
|
- service lifecycle when the workflow needs it
|
|
- reset as a first-class workflow primitive
|
|
|
|
Representative primitives:
|
|
|
|
- `workspace.create`
|
|
- `workspace.status`
|
|
- `workspace.delete`
|
|
- `workspace.sync_push`
|
|
- `workspace.export`
|
|
- `workspace.diff`
|
|
- `workspace.reset`
|
|
- `workspace.exec`
|
|
- `shell.open`
|
|
- `shell.read`
|
|
- `shell.write`
|
|
- `service.start`
|
|
- `service.status`
|
|
- `service.logs`
|
|
|
|
These names are illustrative, not a promise that every lower-level repo surface
|
|
should be treated as equally stable or equally important.
|
|
|
|
## Interactive Shells And Disk Operations
|
|
|
|
Interactive shells are aligned with the vision because they make the agent feel
|
|
present inside the sandbox rather than reduced to one-shot job submission.
|
|
|
|
They should remain subordinate to the workspace model, not replace it with a
|
|
raw SSH story.
|
|
|
|
Disk-level operations are useful for:
|
|
|
|
- fast workspace seeding
|
|
- snapshotting
|
|
- offline inspection
|
|
- export/import without a full boot
|
|
|
|
They should remain supporting tools rather than the product identity.
|
|
|
|
## What To Build Next
|
|
|
|
Features should keep reinforcing the chat-host path in this order:
|
|
|
|
1. make the first chat-host setup painfully obvious
|
|
2. make the recipe-backed workflows feel trivial from chat
|
|
3. keep the smoke pack trustworthy enough to gate the advertised stories
|
|
4. keep the terminal companion path good enough to debug what the chat sees
|
|
5. let lower-level repo surfaces move freely when the chat-host product needs it
|
|
|
|
The completed workspace GA roadmap lives in
|
|
[roadmap/task-workspace-ga.md](roadmap/task-workspace-ga.md).
|
|
|
|
The follow-on milestones that make the chat-host path clearer live in
|
|
[roadmap/llm-chat-ergonomics.md](roadmap/llm-chat-ergonomics.md).
|
|
|
|
## Litmus Test
|
|
|
|
When evaluating a new feature, ask:
|
|
|
|
"Does this make Claude Code, Codex, or OpenCode feel more natural and powerful
|
|
when they work inside a disposable sandbox?"
|
|
|
|
If the better description is "it helps build a broader VM toolkit or SDK", it
|
|
is probably pushing the product in the wrong direction.
|