Skip to main content
Glama
jacopobonomi

venv-manager

by jacopobonomi

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 包别名(cv2opencv-pythonsklearnscikit-learnPILPillowbs4beautifulsoup4yamlPyYAML、...)

  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 后端

如果 uvPATH 中且 use_uv: truecreate 将运行 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 vetgo 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

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jacopobonomi/venv_manager'

If you have feedback or need assistance with the MCP directory API, please join our Discord server