AeroPy
AeroPy is a browser-native Python execution extension for VS Code Web. It runs a pinned Pyodide runtime in a dedicated Web Worker and exposes six capabilities through public VS Code language-model tools plus one focused Agent Skill.
It has no Node.js extension entry point, native binary, server-side Python fallback, AeroCode dependency, workspace mount, or credential bridge.
Capabilities
| Public capability |
VS Code tool name |
Effect |
python/run_code |
aeropy_python_run_code |
Approved execution |
python/run_file |
aeropy_python_run_file |
Approved execution and explicit workspace read |
python/environment |
aeropy_python_environment |
Read |
python/install_packages |
aeropy_python_install_packages |
Separately approved execution and browser network |
python/save_artifacts |
aeropy_python_save_artifacts |
Explicitly approved workspace writes |
python/reset |
aeropy_python_reset |
Approved Worker destruction; no workspace mutation |
Other extensions discover these tools through vscode.lm.tools and invoke them with vscode.lm.invokeTool. The contributed python-analysis skill is declared with contributes.chatSkills. AeroPy also returns a versioned public API from activate() for independently approved direct workflows.
When a Python file is active, AeroPy shows a ▶ Run button in the editor title bar. It invokes AeroPy: Run Active Python File, requests execution approval, and streams output to the AeroPy output channel.
Python output contract
from browser_python import emit, artifact
print("streamed to the AeroPy output channel")
emit({"answer": 42}, name="summary")
open("/tmp/result.csv", "w", encoding="utf-8").write("value\n42\n")
artifact("/tmp/result.csv", "text/csv", "result.csv")
Staged files are copied below /inputs for one run. python/run_file accepts either an absolute workspace URI or a workspace-relative path; multi-root paths start with the workspace folder name. Artifacts stay in host memory until reset, cancellation, deactivation, or an explicit save through python/save_artifacts, AeroPy: Save Artifact to Workspace…, or AeroPy: Save All Artifacts to Workspace….
Artifact writes are performed by the Web extension host through vscode.workspace.fs, not by Python. The agent supplies each returned artifact ID and a workspace-relative destination, VS Code previews the paths for approval, and existing files are protected unless overwrite=true is explicitly requested.
Architecture
The web extension host owns VS Code APIs, workspace access, approvals, and in-memory artifact handles. A dedicated Worker owns Pyodide and its ephemeral filesystem. Only structured-cloneable protocol messages cross the boundary.
Protocol v1 messages include a run ID, operation, code or staged byte arrays, stream events, structured values, artifact descriptors, package changes, environment data, and terminal completion/error results. Timeout and cancellation terminate the Worker. The next operation creates a clean generation.
No VS Code API, authentication session, GitHub token, extension secret, or workspace credential enters the Worker. Standard input is noninteractive. Python can still use Pyodide's JavaScript bridge and browser fetch, so the Worker is a lifecycle/isolation boundary—not a secure sandbox for hostile code.
Enforced first-slice limits
| Limit |
Value |
| Default / maximum execution timeout |
30 s / 120 s |
| Python source |
1 MiB |
| stdout / stderr |
512 KiB each |
| Staged files |
16 |
| Individual / total staged input |
8 MiB / 16 MiB |
| Artifacts |
16 |
| Individual / total returned artifacts |
8 MiB / 32 MiB |
| Packages per install |
5 |
| Package downloads per install |
25 MiB |
Package requests must use exact name==version pins. AeroPy accepts packages built for Pyodide 0.29.4 and PyPI pure-Python *-none-any.whl files. Implicit dependencies are disabled so every download is explicit and bounded. Native CPython wheels, source builds, arbitrary wheel URLs, and install scripts are rejected.
Browser networking and CORS rules apply. Subprocesses and raw sockets are unavailable. The filesystem and installed packages do not persist across browser sessions or environment resets.
Public direct API
const extension = vscode.extensions.getExtension('bpcarson.aeropy');
const python = await extension.activate();
const result = await python.runCode(
{ code: 'print(sum(range(10)))' },
{
approve: async ({ operation, effect, input, limits }) => {
// Present and record approval in the consuming extension's normal flow.
return true;
},
onEvent: (event) => console.log(event),
cancellationToken,
},
);
await python.saveArtifacts(
{
artifacts: result.artifacts.map(({ id, name }) => ({ artifactId: id, workspacePath: `generated/${name}` })),
overwrite: false,
},
{ approve: async ({ effect }) => effect.workspaceWrite === true },
);
Effectful direct calls default to denied when no approval callback is supplied. Language-model tool invocations use VS Code's standard prepareInvocation confirmation contract. Artifact writes require a trusted workspace and remain outside the Worker.
npm ci
npm run check
npm run package:vsix
npm run test:web
test/shared/conformance.js is the unchanged deterministic fixture used by headless contract tests and the real VS Code Web Chromium gate. It verifies discovery, clean environment inspection, stdout/structured/artifact output, hard cancellation and recovery, approved pinned installation, native-package rejection, reset, and pre-Worker denial. The web gate additionally invokes python/environment through the public vscode.lm.invokeTool surface.
npm run test:aerocode installs the marketplace bpcarson.configurable-chat Web extension into a Playwright-controlled VS Code Web host, discovers AeroPy's public skill and tools through AeroCode, and runs that same fixture through AeroCode's approval and tool UI. Approval, result, and completed-conformance screenshots are retained in the Playwright report.
Non-goals for 0.1
No notebook controller, debugger, terminal, interactive REPL, language server, persistent environment, arbitrary native wheels, subprocesses, sockets, unrestricted networking, hostile-code sandbox guarantee, server-side Python fallback, or AeroCode-private API.