1. 环境资产盘点为什么总在出事后才想起
你有没有过这种时刻:新项目要复现一个半年前跑通的脚本,pip install报了一堆版本冲突,你盯着pip list里 90 多个包,完全想不起来当初是哪个版本配哪个库。或者同事问你「你本地 Claude Code 那个 Skill 装哪了」,你翻遍~/.claude、项目根目录、甚至回收站,最后发现它藏在某个早就忘了的.claude/skills子目录里。
这类问题的本质不是「你不会管理环境」,而是环境状态从来没有被记录过。pip 有pip list,npm 有npm ls -g,但它们各说各话,互不认识;AI Agent 工具(Claude Code、OpenClaw、Codex、Cursor)的 Skills 和 Rules 目录更是散落在用户主目录和各个项目文件夹里,没有任何统一入口。你装了什么、装在哪、是全局还是项目级、什么时候装的——全靠记忆。
我试过用pip freeze > requirements.txt来记账,但那只覆盖 Python 包,npm 全局包和 AI Agent 配置完全漏掉。也试过手动维护一个 Markdown 清单,坚持了不到两周就放弃了,因为每次装新东西都要手动更新,太反人性。
env-recorder 就是冲着这个场景写的:一个 Python 脚本,跑一次,把 pip 包、npm 全局包、四大 AI Agent 的 Skills/Rules 全部扫出来,存成带时间戳的快照,还能用--diff对比两次快照的差异。它不解决依赖冲突,也不做自动化安装,只回答一个问题:这台电脑上到底装了什么。适合谁用?经常折腾 AI 编程工具、同时维护多个 Python/Node 项目、或者需要在新机器上快速重建环境的开发者。下面我把安装、配置、扫描范围、diff 对比和常见报错全部拆开讲,你可以直接跟着操作。
2. 前置准备:Python 环境与 env-recorder 获取
env-recorder 本身是一个 Python 脚本,所以第一步是确认你的机器上有可用的 Python 解释器。它不依赖任何第三方库,标准库就能跑,这一点对「环境已经乱到不敢乱装包」的人来说很友好——你不需要先pip install一堆东西才能用它。
先检查 Python 版本。打开终端(Windows 用 PowerShell 或 CMD,macOS/Linux 用默认终端),执行:
python --version如果输出Python 3.8及以上即可。如果提示command not found,试试python3 --version。Windows 上如果两个都没有,需要先去 python.org 下载安装包,安装时勾选「Add Python to PATH」。这一步是基础,不展开。
确认 Python 可用后,获取 env-recorder。它托管在 GitHub 上,直接 clone:
git clone https://github.com/mixuecoding/env-recorder.git cd env-recorder如果你没有 git,也可以直接在 GitHub 页面点「Code」→「Download ZIP」,解压后进入目录。目录结构很简单,核心就是record_env.py一个文件,加上一个用于网页查看器的静态资源文件夹。
这里有个前置认知需要说清楚:env-recorder 扫描的是当前用户的环境,包括全局 pip 包、全局 npm 包、以及用户主目录下的 AI Agent 配置目录。它不会去扫描系统级安装的包(比如/usr/lib/python3下的系统包),也不会修改任何东西,纯读取。所以你可以放心跑,不会把环境搞坏。
另外,如果你同时用多个 Python 虚拟环境,env-recorder 默认扫描的是当前激活的 Python 解释器对应的 pip 包。也就是说,你先source venv/bin/activate再跑脚本,它记录的就是这个 venv 里的包;不激活就直接跑,记录的是全局 Python 的包。这个行为在后面的扫描范围配置里会再展开。
npm 部分需要你的机器上装了 Node.js 和 npm。检查:
npm --version有版本号输出即可。如果 npm 没装,env-recorder 会跳过 npm 扫描并在输出里提示,不会报错中断。AI Agent 部分则是纯文件系统扫描,不依赖对应工具是否安装,只要目录存在就能识别。
3. 可复制配置:扫描范围与运行参数
env-recorder 的设计是「零配置也能跑,但你可以用参数精细控制扫描范围」。先看最基础的运行方式:
python record_env.py这条命令会做四件事:扫描 pip 包、扫描 npm 全局包、扫描 AI Agent 的 Skills/Rules 目录、把结果存成一份带时间戳的快照。输出大概长这样:
AI Agents: 24 个 Claude Code 全局 (2): agent-reach, anysearch OpenClaw 全局 (2): agent-reach, khazix-skills-main Codex 全局 (1): .system Codex Rules 全局 (1): default.rules Claude Code [AiTools] (17): animejs, gsap, hyperframes... Claude Code [Test] (1): wechat-writing 🐍 Pip: 89 个 (89 全局 + 0 项目) 📦 npm: 10 个 (10 全局 + 0 项目)如果你想把扫描范围固定下来,避免每次手动传参,可以在项目目录下建一个配置文件。env-recorder 支持读取同目录下的env_recorder.toml,格式如下:
[scan] # 是否扫描 pip 包 pip = true # 是否扫描 npm 全局包 npm = true # 是否扫描 AI Agent 配置 agents = true [agents] # 要扫描的 Agent 类型,可多选 targets = ["claude", "openclaw", "codex", "cursor"] # 额外要扫描的项目目录(会递归查找 .claude/skills 等) project_dirs = ["/Users/yourname/projects", "/Users/yourname/work"] [snapshot] # 保留最近多少条快照 keep = 50 # 快照存储目录 dir = "./snapshots"这个 TOML 文件里几个关键点:project_dirs是你希望 env-recorder 去递归查找项目级 Skills 的根目录。比如你把所有项目放在~/projects下,就填这个路径,它会自动找到~/projects/foo/.claude/skills这类目录。keep = 50表示只保留最近 50 条快照,超出的自动清理,避免快照目录无限膨胀。
如果你不想用 TOML,也可以用命令行参数临时覆盖:
python record_env.py --no-npm --agents claude,codex --project-dirs ~/projects常用参数对照如下:
| 参数 | 作用 | 示例 |
|---|---|---|
--no-pip | 跳过 pip 扫描 | python record_env.py --no-pip |
--no-npm | 跳过 npm 扫描 | python record_env.py --no-npm |
--agents | 指定扫描的 Agent | --agents claude,openclaw |
--project-dirs | 指定项目根目录 | --project-dirs ~/work,~/side |
--diff | 对比最近两次快照 | python record_env.py --diff |
--web | 启动网页查看器 | python record_env.py --web |
--keep | 保留快照数量 | --keep 100 |
这里要提醒一个容易踩的点:--project-dirs传多个路径时,用逗号分隔,不要用空格。空格会被 shell 拆成多个参数,导致解析错误。另外路径里如果有空格(比如 Windows 的C:\Users\My Name\projects),需要用引号包起来。
配置好之后,建议把「跑一次 env-recorder」加进你的日常习惯:每次pip install完新包、或者在 Claude Code 里加了新 Skill,就跑一下python record_env.py。这样快照序列本身就是一部环境变更史。
4. 验证请求:跑一次扫描并 diff 两台机器
配置就绪后,先跑一次完整扫描,确认输出符合预期:
python record_env.py如果一切正常,你会看到类似第 3 节里的分类输出,并且在./snapshots目录下生成一个 JSON 文件,文件名带时间戳,比如snapshot_20250612_143022.json。打开这个 JSON,结构大致是:
{ "timestamp": "2025-06-12T14:30:22", "pip": { "global": [{"name": "requests", "version": "2.31.0"}, ...], "project": [] }, "npm": { "global": [{"name": "claude-code", "version": "1.2.3"}, ...] }, "agents": { "claude": {"global": ["agent-reach", "anysearch"], "projects": {...}}, "openclaw": {"global": ["agent-reach", "khazix-skills-main"]}, "codex": {"global": [".system"], "rules": ["default.rules"]} } }这个 JSON 就是「环境快照」的原始数据。你可以把它提交到 git 仓库,或者同步到网盘,作为环境备份。
接下来验证 diff 功能。先手动装一个包制造变化:
pip install cowsay然后再跑一次扫描:
python record_env.py现在快照目录里有两份 JSON 了。执行 diff:
python record_env.py --diff输出会明确告诉你两次快照之间多了什么、少了什么、什么升级了:
对比: snapshot_20250612_143022.json -> snapshot_20250612_144510.json 🐍 Pip 新增: cowsay==6.1 📦 npm 无变化 Agents 无变化这个 diff 能力在「两台机器环境对比」场景下特别有用。假设你有一台旧笔记本和一台新台式机,想把旧机器的环境复刻到新机器上,操作流程是:在旧机器上跑python record_env.py,把生成的 JSON 拷到新机器,在新机器上也跑一次,然后用 diff 对比两份快照。差异部分就是你需要在新机器上补装的东西。
如果你想把 diff 结果导出成文件方便分享,可以重定向输出:
python record_env.py --diff > env_diff.txt网页查看器也值得一试。执行:
python record_env.py --web它会在本地起一个 HTTP 服务(默认端口 8080),浏览器打开http://localhost:8080就能看到图形化界面,支持搜索包名、按类型筛选、可视化对比两次快照。89 个 pip 包在终端里滚屏很痛苦,网页里搜索框一敲就定位到了。这个查看器是纯本地运行的,数据不出机器。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
env-recorder 本身不涉及网络请求和鉴权,所以它不会报 401 或 OAuth 错误。但你在用它盘点环境时,很可能会顺带排查其他工具的问题。下面这几类报错是实际使用中高频出现的,我按「报错原文 → 原因 → 解决」的结构列出来。
报错一:npm: command not found或FileNotFoundError: [WinError 2]
这是 Windows 上最典型的坑。npm 在 Windows 上实际是npm.cmd文件,Python 的subprocess直接调npm会找不到可执行文件。env-recorder 内部已经做了处理:它会先探测 Node.js 安装路径,然后优先调用npm.cmd。如果你仍然遇到这个报错,说明 Node.js 没装或者没在 PATH 里。解决方式是重新安装 Node.js 并确保勾选「Add to PATH」,或者手动在 TOML 里指定 npm 路径:
[npm] binary = "C:/Program Files/nodejs/npm.cmd"报错二:local proxy failed或connection refused
这个报错通常出现在你跑其他 AI 工具(比如 Claude Code、Codex)时,而不是 env-recorder 本身。原因是这些工具需要访问模型 API,而你的网络配置或代理设置有问题。排查顺序:先确认curl https://taotoken.net/api能否通(注意这是 API 地址,不带 UTM),如果不通,检查你的网络环境。如果通但工具仍报错,检查工具自己的配置文件里 Base URL 是否写对。以 Claude Code 为例,它的配置在~/.claude/settings.json,需要确保ANTHROPIC_BASE_URL指向正确的地址。这里不展开代理配置细节,只提醒一点:env-recorder 扫描的是文件系统,不碰网络,所以它跑不通和 API 连不上是两码事,别混在一起排查。
报错三:reading choices或invalid response format
这类报错一般出现在调用模型 API 时,返回的 JSON 结构不符合预期。常见原因是 Base URL 配错了,请求打到了错误的端点。比如你把https://taotoken.net/api写成了https://taotoken.net/api/v1/chat之类的错误路径。正确的做法是只填 Base URL,让 SDK 自己拼接路径。以 OpenAI 兼容的 SDK 为例:
from openai import OpenAI client = OpenAI( base_url="https://taotoken.net/api", api_key="你的Key" )注意base_url结尾不要多加/v1,除非文档明确要求。很多「reading choices」报错都是因为路径重复拼接导致的。
报错四:OAuth token expired或authentication failed
如果你在用 Codex 或 Claude Code 的 OAuth 登录方式,token 过期后会报这个。解决方式是重新登录,或者改用 API Key 方式。以 Codex 为例,它的鉴权信息存在~/.codex/auth.json,结构大致是:
{ "OPENAI_API_KEY": "sk-...", "base_url": "https://taotoken.net/api" }如果你要切换到 API Key 方式,把auth.json里的OPENAI_API_KEY换成你的 Key,base_url指向https://taotoken.net/api即可。改完后跑一次python record_env.py,快照里会记录这个配置文件的状态,方便你回溯「什么时候改的鉴权方式」。
报错五:CORS policy blocked网页查看器打不开数据
这是 env-recorder 网页查看器在file://协议下的经典问题。浏览器出于安全策略,禁止file://页面用fetch读取本地 JSON。env-recorder 的解决方式是起一个本地 HTTP 服务器,所以你必须用python record_env.py --web来打开查看器,而不是直接双击 HTML 文件。如果你看到控制台报 CORS 错误,检查是不是直接打开了index.html。
排查完这些,回到 env-recorder 本身:它的报错信息都很直白,基本是「某个目录不存在」或「某个命令找不到」,按提示补上即可。它不会静默失败,每个扫描模块失败都会在输出里标注。
6. 把环境快照变成日常习惯:CTA 与长期用法
env-recorder 的价值不在于跑一次,而在于持续跑。我的用法是把它和几个日常动作绑定:每次pip install完、每次在 Claude Code 里加完 Skill、每次换机器,都跑一次python record_env.py。快照序列积累下来,你就有了一个可以回溯的环境变更日志。
如果你同时用多个 AI 编程工具,建议把它们的配置也纳入盘点范围。Claude Code 的 Skills 在~/.claude/skills,OpenClaw 在~/.openclaw/skills,Codex 在~/.codex/skills和~/.codex/rules,Cursor 在~/.cursor/rules。env-recorder 默认会扫这些目录,你只需要在 TOML 里确认targets包含了你用的工具。
对于需要长期维护多个项目环境的开发者,可以考虑把快照 JSON 提交到 git,配合 CI 定期跑 diff,这样环境漂移会第一时间暴露。如果你在团队里做环境标准化,可以把一份「基准快照」放进仓库,新成员入职时跑一次 diff,就知道自己缺什么。
如果你在配置模型接入时需要查 Key 和管理额度,可以走 API Keys 页面;需要对照接入参数和示例代码,看接入文档;想先验证模型连通性,用模型对话页面直接试;如果是长期编码或 Agent 场景,Coding Plan 更合适。这几个入口按你的实际需求选,不用全走一遍。
最后回到那个问题:你的电脑上到底装了什么?跑一次 env-recorder,答案就在那份 JSON 里。它不宏大,不智能,但当你需要回答这个问题的时候,它是你手边最快的那把尺子。