Skip to main content
Glama

venv-manager

CI Go Reference License: MIT Release Website jacopobonomi/venv-manager MCP server

一个面向开发者以及每一个 AI 编码代理的 Python 环境控制层。

使用 Go 编写。一个静态二进制文件,除了 python3(或 uv,如果可用)之外没有运行时依赖。

demo

上面的 GIF 是真实的:venv-manager watch app.py --venv X 监视一个文件,用一个小型 AST-lite 解析器扫描其导入,并 pip 安装任何缺失的包——每次文件变化时都会执行。将其指向一个 LLM 正在迭代的脚本,虚拟环境就会随着代码的变化而收敛。


为什么

Claude、Codex、Cursor 和其他编码代理已经可以运行 shell 命令、创建 .venv,并在敏感操作前请求批准。它们所不共享的是持久的 Python 环境状态。

沙箱保护机器。venv-manager 保护工作流:它给每个代理相同的环境、元数据、包历史和恢复路径,与正在运行的客户端无关。

两个失败模式催生了这个工具:

  1. 人类蔓延。 虚拟环境在 ~ 下成倍增加,缓存目录占用 GB 级空间,激活语法因 shell 而异,克隆“曾经有效的环境”意味着在终端之间复制粘贴 pip freeze。

  2. 代理蔓延。 AI 代理可能安装到错误的解释器,留下部分更改,并在切换客户端或开始新会话时丢失环境上下文。

venv-manager 用干净的 CLI 解决 (1),用共享的 Model Context Protocol 服务器、持久的注册表、类型化的快照和差异、可逆的包更改、带 OS 级沙箱的临时虚拟环境,以及保持虚拟环境与演进代码同步的文件监视器解决 (2)。

代理沙箱不能解决的问题

代理能力

共享环境控制

批准或阻止 shell 命令

记录哪个环境属于哪个项目

限制文件系统和网络访问

在 Claude、Codex 和其他客户端之间保留状态

在提示时创建虚拟环境

跟踪创建和真实最后使用元数据

运行 pip、Poetry 或 uv

显示快照之间的包级更改

停止不安全操作

将损坏的环境回滚到已知状态

这两层互补:代理权限控制现在可能发生什么;venv-manager 记录存在什么、改变了什么,以及如何恢复。


Related MCP server: Sympathy-MCP

安装

Homebrew(macOS、Linux):

brew install jacopobonomi/tap/venv-manager

一行安装脚本(macOS、Linux):

curl -sSL https://raw.githubusercontent.com/jacopobonomi/venv_manager/main/install.sh | bash

从源码构建:

git clone https://github.com/jacopobonomi/venv_manager && cd venv_manager
make install

需要 Go 1.24+ 来构建,运行时需要 Python 3.x。


AI 集成

MCP 服务器

将虚拟环境操作暴露为原生的 Model Context Protocol 工具。Claude、Codex、Cursor、Zed 和其他 MCP 客户端调用相同的类型化工具,并操作相同的持久环境状态,而不是独立猜测 shell 调用。

在 Claude Desktop 中配置(~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "venv-manager": {
      "command": "venv-manager",
      "args": ["mcp", "--policy", "safe"]
    }
  }
}

暴露的工具(通过 stdio 的 JSON-RPC 2.0):

工具

用途

list_venvs

所有受管虚拟环境的名称。

create_venv

{name, python_version?} → 新建虚拟环境,如果配置了 uv 则使用它。

remove_venv

{name} → 递归删除。

describe_venv

{name} → 完整快照:Python 版本、包、大小、freeze 哈希、每个 shell 的激活命令。

install_packages

`{name, packages[]

requirements_file}` → pip install,返回合并的 stdout+stderr。

run_in_venv

{name, command[]} → 在虚拟环境中执行,设置 VIRTUAL_ENV 并前置 PATH。捕获输出。

exec_ephemeral

{packages[], python_version?, command[]} → 在单次调用中创建-安装-运行-销毁。

snapshot_venv

{name, label?} → 捕获 pip freeze;启用 rollback_venv。

list_snapshots

{name} → 最新的在前。

rollback_venv

{name, snapshot_id?} → 安装快照状态,然后移除其中不存在的包。

diff_snapshots

{name, from_snapshot_id, to_snapshot_id?} → 包级差异;省略 to_snapshot_id 表示当前状态。

scan_imports

{path, venv?} → 找到的第三方导入;当传入 venv 时,报告哪些缺失。

list_registry

持久的项目、标签、创建和最后使用元数据。

set_registry_metadata

{name, project?, tags[]?, confirm?} → 更新注册表元数据。

doctor

PATH 上的 Python 版本、uv 可用性、损坏的虚拟环境。

服务器默认采用 safe 策略。安装、回滚、移除和任意执行需要 confirm: true。使用 --policy read-only 用于仅检查的客户端,--policy full 用于无限制兼容,重复 --allow-tool NAME 仅暴露显式子集。这些策略是纵深防御:即使不同客户端具有不同的批准设置,它们也保持一致。

实现使用零第三方 MCP 依赖。在 stdin/stdout 上使用换行分隔的 JSON-RPC 2.0。

临时执行(uvx 风格,沙箱化)

# create → install → run → destroy, all in one call
venv-manager exec --with requests -- python -c "import requests; print(requests.__version__)"

# with an OS sandbox: no network, no writes outside /tmp + the ephemeral venv
venv-manager exec --sandbox --with pandas -- python untrusted.py

--sandbox 在 macOS 上使用 sandbox-exec,在 Linux 上使用 bwrap。默认拒绝配置文件,并显式允许虚拟环境路径、/tmp 和进程管理。网络不共享。

文件监视器

venv-manager watch app.py --venv myenv

在父目录上使用 fsnotify(能承受编辑器原子重命名写入),500 毫秒防抖,然后:

  1. 对 .py 文件进行 AST-lite 正则扫描(跳过文档字符串、相对导入、本地模块/包,以及 .venv、.git、__pycache__、node_modules 等 vendored 目录)

  2. 根据标准库模块集过滤

  3. 解析导入名 → pip 包别名(cv2 → opencv-python、sklearn → scikit-learn、PIL → Pillow、bs4 → beautifulsoup4、yaml → PyYAML、...)

  4. 与已安装的包进行差异比较

  5. pip install 差异部分

虚拟环境始终是当前文件需求的超集。这就是上面演示 GIF 所展示的循环。

持久注册表

每个环境都在 ~/.venvs/.venv-manager/registry.json 中跟踪,包含创建和最后使用时间戳、可选的项目路径和标签。写入是原子的,注册表会与实时虚拟环境目录自动协调。

venv-manager registry
venv-manager registry set research --project ~/work/paper --tag data,ai
venv-manager registry research

prune 在元数据可用时使用注册表的 last_used_at 而不是目录修改时间。

JSON 快照作为单次调用的上下文入门

venv-manager describe myenv
{
  "name": "myenv",
  "path": "/Users/me/.venvs/myenv",
  "python_version": "3.12.6",
  "python_path": "/Users/me/.venvs/myenv/bin/python",
  "pip_path": "/Users/me/.venvs/myenv/bin/pip",
  "packages": ["requests==2.34.2", "rich==15.0.0", ...],
  "package_count": 12,
  "size_bytes": 45123456,
  "size_human": "43.03 MB",
  "modified_at": "2026-07-20T15:41:35Z",
  "freeze_hash": "sha256:2c58d830...",
  "activation": {
    "bash": "source '/Users/me/.venvs/myenv/bin/activate'",
    "zsh":  "source '/Users/me/.venvs/myenv/bin/activate'",
    "fish": "source '/Users/me/.venvs/myenv/bin/activate.fish'"
  }
}

一次工具调用,代理推理环境所需的一切。freeze_hash 让代理以 O(1) 检测两次 describe 调用之间的漂移,而不是比较包列表。


命令

Command

Description

create <name> [--python VER]

创建虚拟环境。当配置中 use_uv: true 时使用 uv。

list [--json]

列出虚拟环境。

remove <name>

删除虚拟环境。

rename <old> <new>

重命名并通过 python -m venv --upgrade 重新生成激活脚本。

clone <src> <dst>

以源环境的 pip freeze 为基础创建全新虚拟环境。

packages <name> [--json]

已安装的包。

install <name> <requirements>

pip install -r。

upgrade [name] [--global]

升级过期的包(按虚拟环境或全部)。

clean [name] [--global]

清除 pip 缓存和 __pycache__ 目录。

size [name] [--global] [--json]

磁盘占用。

activate <name>

打印用于 eval $(...) 的 shell 命令。

deactivate

打印 deactivate。

run <name> -- <cmd>

在不激活的情况下在虚拟环境中执行;继承标准输入输出。

exec [--with pkgs] [-r req] [--python V] [--sandbox] [--keep] -- <cmd>

临时虚拟环境运行。

describe <name>

完整 JSON 快照(见上文)。

scan <path> [--venv N] [--json]

提取第三方导入;与虚拟环境进行核对。

watch <path> --venv N

文件变更时自动安装缺失的导入。

snapshot <name> [-l LABEL]

捕获 pip-freeze 状态。

snapshots <name> [--json]

列出快照(最新的在前)。

rollback <name> [snapshot-id]

先安装快照状态,然后移除快照中不存在的包。

snapshot-diff <name> <from> [to]

比较快照差异,或将某个快照与当前状态进行比较。

export <name>

以 JSON 格式打印可移植清单(名称 + Python 版本 + freeze)。

import <manifest.json>

从清单重新创建虚拟环境。

prune [--days N] [--dry-run] [--yes] [--json]

报告过期的虚拟环境;删除前需要 --yes。

registry [name]

显示持久化的创建、使用、项目和标签元数据。

registry set <name> [--project PATH] [--tag TAGS]

更新项目关联和标签。

doctor [--json]

诊断 Python 版本、uv、损坏的虚拟环境。

`config show

path

init`

显示 / 定位 / 初始化配置。

mcp [--policy MODE] [--allow-tool NAME]

具有只读、安全或完全授权策略的 MCP 服务器。

tui

Bubble Tea TUI 浏览器。

`completion [bash

zsh

fish

powershell]`

Shell 补全脚本。

大多数读取命令也接受 --json 以获得稳定、可机器解析的输出。


配置

~/.config/venv-manager/config.json(遵循 $XDG_CONFIG_HOME 和 $VENV_MANAGER_CONFIG):

{
  "base_dir": "/custom/path/to/venvs",
  "default_python": "3.12",
  "use_uv": true,
  "prune_after_days": 90
}

初始化:venv-manager config init。

uv 后端

如果 uv 在 PATH 中且 use_uv: true,create 将运行 uv venv。在冷缓存情况下通常比 python -m venv 快 10–100 倍。


开发

make build            # go build -o bin/venv-manager
make test             # unit tests
make demo             # regenerate scripts/demo/demo.gif via VHS
go test -tags=integration ./internal/manager/...   # integration tests (real pip, real PyPI)

CI 在 Ubuntu + macOS 上运行 go vet、go test -race,并在 Ubuntu 上使用 Python 3.12 运行集成测试。

架构:

cmd/venv-manager/           cobra CLI
internal/manager/           core operations (create, install, snapshot, scan, watch, exec, describe, ...)
internal/config/            XDG-aware JSON config
internal/mcp/               JSON-RPC 2.0 MCP server (stdio)
internal/tui/               Bubble Tea browser
internal/utils/             platform helpers, size formatting

许可证

MIT。

作者

Jacopo Bonomi

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    An MCP server for managing Incus virtual machines through structured tools for command execution, file management, and snapshot operations. It enables AI agents to puppeteer VMs on a masternode by wrapping the Incus CLI.
    9
    -
  • A
    license
    B
    quality
    D
    maintenance
    Production-grade MCP server that gives AI agents safe access to your local dev environment: filesystem, databases, processes, and OpenAPI specs.
    15
    65 npm
    4
    MIT
  • F
    license
    B
    quality
    D
    maintenance
    An MCP server that manages Python virtual environments using uv, allowing LLMs to reliably resolve dependencies and update virtual environments.
    6
    7
    -