
说来有点讽刺我最近几个月的代码产量比过去两年加起来都高但心里发虚的时刻也比过去两年加起来都多。原因大家都猜到了我几乎天天在 vibe coding。自然语言喂给大模型让它把想法变成代码我再负责跑起来、改报错、继续往下怼——这套流程确实爽但爽完之后问题也攒了一堆项目里的依赖被 AI 顺手加了一大批有的没的环境动不动就崩提交的代码自己都不确定是不是漏了什么低级错误几周前跟 AI 讨论过的一个关键方案再也翻不到聊天记录。我管这种状态叫 vibe coding 焦虑。它不是写不出代码的焦虑而是代码写得太多太快之后掌控感没跟上带来的失控焦虑。后来我花了一段时间把跟开发相关的工具链全部换成开源方案。这 9 个开源 App 不是那种装完就吃灰的玩具它们是实实在在治好了我上面说的那些焦虑环境快速清澈、依赖不再冗余、漏洞提前暴露、测试自动盯着、跟 AI 的每一句话都有日志可查。这篇文章把我的完整做法整理出来包括每个工具解决什么问题、几个关键参数怎么配以及我踩过的坑。适合所有用 AI 辅助写代码、但总觉得心里没底的开发者参考。1. 先别急着装工具vibe coding 的焦虑到底从哪来1.1 vibe coding 是种享受但失控感也真实存在vibe coding 这个词最近在开发者圈子里几乎成了默认工作方式。它的大概意思是你不再逐行敲代码而是用自然语言描述需求让大模型把功能“长”出来你负责确认方向、修报错、查结果。听起来很爽尤其是对我这种一个人要撑起好几个小项目的开发者以前写个爬虫加接口要折腾一下午现在半小时就能跑通。但问题是这种模式下你对代码的掌控和以前完全不一样了。以前写代码每一行都是自己敲的项目结构在心里有完整地图。vibe coding 时代代码是一段一段“空降”到项目里的AI 帮你建的目录、起的变量名、引的依赖很多你其实没细看。我最早那种焦虑就是从这来的依赖一大包我根本不知道哪些是 AI 顺手加上却从来没用的代码几百行我不敢保证它没有隐藏的低级错误尤其是对话一多之前在哪个网页、哪个上下文里跟 AI 确认过的方案回头找起来像大海捞针。更扎心的是这种失控是叠加的。环境越乱AI 给的建议就越难落地依赖越冗余项目体积和安全风险就越大你越没有测试兜底每次改动就越不敢动。久而久之写代码变成了一件“能跑但不敢碰”的事。所以我觉得vibe coding 本身没有错错的是少了配套的工程纪律。1.2 我整理出的 9 个焦虑源和对应解药带着这个问题我把近几年社区里口碑最好的开源工具重新翻了一遍选了 9 个来构建我自己的 vibe coding 安全网。核心思路很简单环境问题交给环境工具依赖问题交给依赖工具质量问题交给质量工具记忆问题交给记忆工具隐私问题交给本地工具不要指望 AI 或人工同时搞定所有事。这里先给一张对照表后面每个我都会展开讲焦虑源具体表现对应工具环境失控venv / pip 把 Python 环境搞得混乱换机后很难复现uv依赖失控AI 顺手装了没用的库pyproject 越来越臃肿deptry项目规模失控看不出项目到底多少行、哪些语言膨胀tokei代码质量失控未使用变量、低级逻辑错误、风格不统一Ruff依赖安全失控用了带已知漏洞的版本上线后才后悔osv-scanner提交失控提交前忘了检查把坏代码合进去pre-commit行为回归失控AI 改一个功能悄悄改坏了原有行为watchexec对话记忆失控和 AI 的历史讨论散落无法检索llm CLI隐私掌控失控业务代码片段不想上传云端又想用 AI 帮忙Ollama这套工具链的特点是没有一个“大而全”的平台全是小而专的组合件。这样好处是每个环节都可替换、可升级坏处是第一次配置稍微有点繁琐。下面我按“底座治理→质量闸门→测试与记忆→本地掌控”四个顺序来讲你先装最前面几个焦虑通常已经能缓解一半。2. 底座治理依赖、环境与项目体检2.1 uv几秒钟造好一个干净环境先说我之前的环境焦虑。vibe coding 经常是同时开着三四个实验项目每个项目需要的 Python 版本、依赖完全不同。以前一个项目建一个 venv再手动 pip install慢就不说了最怕的是 AI 建议“升级到最新版本”然后整个环境被某个新包的不兼容搞崩。折腾半天才发现是依赖互相打架这种时间浪费真的很难受。uv 是 Rust 写的 Python 包管理器兼容 pip、pip-tools、venv、pyenv 的大部分用法但速度完全不是一个量级。我实测同一个项目 50 多个依赖pip 冷启动要十几秒uv 一秒多就装完。更关键的是它用 pyproject.toml uv.lock 管理依赖lock 文件把每个包的精确版本锁死AI 再怎么“顺手加依赖”也都有迹可循。换机器、重装环境只要一个uv sync全部还原。我平时用得最多的几条命令是这些# 初始化一个带 Python 3.12 的新项目 uv init vibe-demo uv python pin 3.12 # 添加依赖自动更新 lock 文件 uv add requests rich httpx # 跑脚本前自动激活环境 uv run python main.py # 完全同步环境删掉多余依赖 uv sync你可能会问这跟 vibe coding 有什么关系关系太大了。AI 在对话里说“你需要装一下 xxx 包”的时候我现在的习惯是直接uv add xxx不让 AI 帮我执行安装。这样即使 AI 推荐的包有问题我只要看 lock 文件就能回溯不至于让环境变成一个黑盒。还有一个细节是uv tool install可以装全局 Python 工具比如后面要说的 pre-commit、llm我都用这一个入口搞定不用再单独维护一堆 pipx 虚拟环境。2.2 deptry揪出“装着没用”的冗余依赖依赖装上之后下一步是处理“装了一堆却没用到”的问题。我早期 vibe coding 时有个很典型的坑AI 给我写一个数据清洗脚本代码里明明只用了 pandas但对话里它同时推荐了 numpy、openpyxl、xlrd、beautifulsoup4我为了保险全pip install了。最后这些依赖全躺在项目里既占空间又扩大攻击面别人接手时还不敢删怕哪个地方隐式用了。deptry 就是专门干这个的。它扫描你的源码里实际 import 了什么再跟 pyproject.toml 里声明了什么做对比输出“声明了但没用”“用了但没声明”这几类问题。用法简单到有点不像现代工具# 在项目根目录执行 uvx deptry .输出大概是这种风格Scanned 12 files, found 15 dependencies pyproject.toml: ❌ openpyxl declared but unused ❌ numpy declared but unused我自己的经验是跑完 deptry 之后砍掉的依赖经常能占到 pyproject 里三分之一以上。AI 喜欢“多带点保险”这个习惯从代码质量角度看可以理解但从工程卫生角度看就是灾难。当然deptry 不是无脑删有些库是运行时靠动态导入加载的比如 pytest、mkdocs 这类插件机制的包它会误报。这种情况要么把它们挪到 dev 依赖组要么在配置里加 ignore。我踩过一次 scrapy 的坑它靠 entry point 加载中间件源码里没 import 任何 scrapy 相关的包deptry 直接报“declared but unused”。实际上它确实被框架用到了这种就要靠人工判断不能全信。2.3 tokei项目到底写了多少代码心里要有数环境问题解决之后我开始关注一个被很多人忽略的角度项目规模本身的可视化。vibe coding 最大的特点是产出速度极快你可能两周前开了个新项目今天一统计发现已经 4000 多行代码了。问题是代码量越来越大但你心里的“项目地图”还停留在最初那个小脚本的水平。这种规模认知落后是很多失控感的来源。tokei 是一个用 Rust 写的代码统计工具功能很纯粹快速统计各语言的文件数、代码行、注释行、空白行。它对大部分主流语言都有良好的识别能力几毫秒就能扫完一个中型项目比你在 IDE 里挨个文件翻方便太多。# 统计当前目录所有代码 tokei . # 只看 Python tokei -t Python # 按代码量排序 tokei --sort code我实际用了之后才发现那个我以为是“小工具”的项目已经写了 4000 多行 Python其中还有 800 多行是 AI 生成的重复逻辑。这直接逼着我做了一次重构把所有“看起来差不多”的函数收敛成公共模块。有人觉得统计代码行数没意义但在 vibe coding 场景下它其实是一个非常重要的“体检指标”它让你在失控之前意识到“项目已经长大了”。我现在的习惯是每个项目每周跑一次 tokei如果发现单周新增代码超过 1000 行就会主动停下来花半小时整理结构。3. 质量闸门让 AI 产物先过机器这一关3.1 Ruff毫秒级 lint代码风格和隐患一次收走环境、依赖、规模这些问题稳住了接下来是更核心的代码质量焦虑。vibe coding 生成的代码功能上可能能做出来但代码卫生很差未使用的 import、未定义的变量、风格不统一、老旧的语法写法这些问题靠人工 review 根本看不过来尤其当 AI 一次生成几百行时。Ruff 是这两年 Python 社区最流行的 linter用 Rust 写的速度快到离谱。我拿一个 5000 多行的项目试过ruff check .跑完显示耗时 0.08 秒这在以前用的工具里是不可想象的。它能覆盖 pyflakes、pycodestyle、isort、black 的大部分规则所以一把梭就能把风格和历史包袱问题都管住。我最常用的三件套# 检查当前项目 ruff check . # 自动修复能修的问题比如未使用 import、格式问题 ruff check . --fix # 格式化代码 ruff format .实际工作流里我通常是在 AI 把一段新代码塞进项目后马上跑一遍ruff check --fix。能自动修的未使用 import、排序、空格等直接修掉剩下修不了的大部分才是真正需要人工看的逻辑问题。这个区分非常关键它把“低水平重复审查”和“高水平逻辑审查”分开你只需要把精力花在后者上。配置上我建议在 pyproject.toml 里明确一下规则集不要用默认值[tool.ruff] target-version py311 line-length 88 [tool.ruff.lint] select [E, F, I, UP, B]F是 pyflakes 类问题未定义变量、未使用变量E是基础语法风格I是 import 排序UP是语法现代化提醒B是 flake8-bugbear 的一些隐藏 bug 模式。这几个加一起基本能把 AI 代码里最常见的问题都圈住。3.2 osv-scanner开源依赖的漏洞扫描雷达代码本身的问题解决了还有一个更大的隐患AI 推荐的依赖版本可能带着已知安全漏洞。这东西在 vibe coding 时特别容易踩雷因为 AI 的推荐通常基于训练数据它不一定知道某个库的某个版本目前有没有公开漏洞。如果你把项目直接部署上线被别人用已知漏洞打穿那才是真正的“代码焦虑”。osv-scanner 是 Google 开源的一个漏洞扫描工具直接对接 OSV 漏洞数据库。它不需要注册账号不需要上传代码只要在本地扫描你的 lock 文件或目录就能把所有已知漏洞列出来。# 扫描 lock 文件这是最常见的用法 osv-scanner --lockfile uv.lock # 或者直接递归扫描整个项目 osv-scanner -r .输出会列出每个漏洞对应的包名、影响版本、漏洞编号CVE 或 OSV、以及修复版本建议。我的习惯是把它放到提交前的流程里每次准备发一个小版本之前跑一次。如果扫出来高危漏洞并且有修复版本先升级再发布。这个工具和我前面说的 uv lock 文件配合特别好lock 文件锁定了精确版本扫描结果就更准确。有人可能会说“开源依赖这么多扫描出来一堆问题会不会自己吓自己”。确实会但这就是 vibe coding 必须付出的代价你让 AI 替你选了依赖那么你的安全审查看起来就要更勤快一点。osv-scanner 只负责把信息给你不会强制改代码决定权还是在你手上。3.3 pre-commit提交前的自动化防线工具链再完善如果每次提交前都靠脑子记住“我要先跑一遍 ruff再跑一遍 osv-scanner”那基本等于没用。人总是会忘的尤其 vibe coding 状态下注意力全在功能上谁会记得提交前还有一堆检查这就是我为什么把 pre-commit 放在质量闸门的最后一道它把前面所有检查串起来在git commit之前自动执行不过就拦下来。pre-commit 是一个管理 git hooks 的工具配置文件是项目根目录下的.pre-commit-config.yaml。我的配置长这样repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.6.9 hooks: - id: ruff args: [check, --fix] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-merge-conflict - id: detect-secrets第一次用的时候先安装一次环境uv tool install pre-commit pre-commit install之后每次git commitpre-commit 都会先跑一遍。如果有文件被自动修改比如 ruff 修了一行格式commit 会被打断让你先git add那些修改再重新提交。这个“打断”机制非常重要它强迫你亲眼看到提交的变化而不是让 AI 的代码原封不动进仓库。我的最大感受是有了 pre-commit 之后我已经很久没有主动担心“提交的代码规不规范”了。这个担心被转移给了机器而且机器不会偷懒。4. 测试与记忆改完代码不慌翻旧账有底4.1 watchexec文件一保存测试自动续上vibe coding 工作流里最让我胃疼的一环是AI 改完一段代码我总是要手动跑一遍测试才能安心但跑测试这件事频率一高人就容易偷懒。特别是那种“就改了一个变量名应该不用测吧”的想法一冒出来往往就是问题开始的地方。watchexec 是一个通用的文件监听工具它监视文件系统变化然后执行你指定的命令。它不是测试框架但是一个完美的“测试自动触发机”。我的用法是在项目目录开一个终端窗口然后挂上# 监听所有 py 文件变化自动跑 pytest watchexec -e py uv run pytest -q # 只监听 src 和 tests 目录并且加 300ms 防抖 watchexec -w src -w tests -r --debounce 300 uv run pytest -q启动之后我每次保存文件终端就自动开始跑测试一两秒后看到绿了或红了。红了就马上定位是 AI 这次改的问题还是原有逻辑被破坏了整个过程基本不用动手敲命令。这种感觉非常奇妙有点像开车时有个副驾在盯着路面你只需要专注方向盘。一定要强调的是watchexec 只是让你“跑测试”这个动作变得不费力它不能替代你写测试。vibe coding 时我一般会顺手让 AI 给核心函数写几个冒烟测试比如“用 pytest 写一个测试覆盖这个函数的正常输入和边界输入”。测试本身不一定全面但至少把主干功能钉住watchexec 就能在背后替你盯着它们。4.2 llm CLI把 AI 对话存档成可检索的本地资产接下来这个工具我觉得是整套体系里最被低估的一个。vibe coding 一个很容易被忽略的问题你与 AI 之间的讨论过程其实比最终代码更有价值。但你如果一直用网页版聊天这些讨论是散落的、无法检索的。过两周想回看“当时为什么选择了方案 A 而不是方案 B”根本找不到。llm 是 Simon Willison 开发的一个命令行工具它把大模型客户端搬到了终端里并且默认把所有请求和响应记录到本地 SQLite 数据库。这等于给 vibe coding 装了一个“黑匣子”每一次有效对话都自动存档。# 发起一次对话默认模型来自配置 llm 帮我写一个异步爬虫抓取公开 RSS 源 # 用指定模型继续聊 llm -m gpt-4o 再优化一下刚才的代码 # 继续上次会话 llm -c 把超时时间改成 10 秒 # 搜索历史对话 llm logs -p 异步爬虫 # 交互式聊天 llm chat我最常用的其实是llm logs -p这个搜索功能。有一次我在做一个数据采集服务两周前 AI 给过一个关于重试机制的建议我当时觉得有道理就改了代码但没记笔记。后来代码出了奇怪的间歇性超时问题我想起之前好像讨论过类似场景就直接llm logs -p 重试一下就把当时的上下文捞出来了问题立刻清晰。llm 还支持通过插件接本地模型。比如装了llm-ollama插件之后可以直接用llm -m ollama/qwen2.5-coder:14b跑本地模型这样所有对话也能自动存进同一个 SQLite 数据库。所以我现在的习惯是所有重要讨论都在终端里进行而不是开一堆网页标签。原因不只是方便更重要的是这些对话会变成项目的“思考档案”以后不管是自己回顾还是给接手的人看都是非常有价值的一手资料。5. 回归掌控本地推理与完整工作流5.1 Ollama本地大模型vibe 时不依赖云端说完记忆问题再说一个很多人有但不好意思说的担忧vibe coding 时把公司内部代码、个人业务逻辑直接粘给云端对话模型到底安不安全反正我写一些带内部字段名的代码时总是会犹豫几秒。这种时候本地模型就成了完美的缓冲。Ollama 是当前最方便的本地大模型管理器它可以把开源模型下载到本地通过命令行或 API 提供推理服务。和云端 API 相比本地模型没有速率限制、没有按 token 计费最关键的是所有数据都在你自己的机器里不经过网络上传。我用得最多的模型是 Qwen2.5-Coder 系列# 拉取模型 ollama pull qwen2.5-coder:14b # 启动交互式会话 ollama run qwen2.5-coder:14b # 列出本地已有模型 ollama list说实话本地模型在复杂推理上跟顶级云端模型还有差距但用于代码 review、解释陌生代码、写单元测试、总结函数逻辑这些任务完全够用了。比如我写了一个函数想让 AI 帮我看看“有没有边界条件漏了”直接把代码扔给本地模型问一遍心就能定很多。还有像字段名、数据库连接串这种敏感信息我根本不会让它离开本地。我的实际工作流是一种混合模式需要高度创造力的时候比如“这个架构怎么设计”“这个算法怎么优化”用云端最强模型聊方案一旦聊到具体的、带业务细节的代码就切到本地 Ollama 做初步审查和解释。这样既保住了代码质量又不会把所有敏感内容暴露给云端。5.2 把九个工具串成一条 daily loop工具逐个说完了最后串一下完整工作流。很多人问“这么多工具平时能全用上吗”我的答案是真正跑起来之后你其实感觉不到它们的存在因为它们已经嵌进了习惯里。这里拿一个我从零开始写小工具项目的例子展示完整链条# 1. 初始化项目并安装依赖 uv init vibe-demo cd vibe-demo uv python pin 3.12 uv add requests rich httpx # 2. 让 AI 把核心功能写出来粘贴进项目略 # 3. 质量检查Ruff 自动修复 格式化 uvx ruff check . --fix uvx ruff format . # 4. 让 AI 给核心函数写几个冒烟测试手动运行一次 uv run pytest -q # 5. 挂上 watchexec之后保存文件就自动跑测试 watchexec -e py uv run pytest -q # 6. 依赖治理筛查未使用的依赖 uvx deptry . # 7. 安全扫描检查 lock 文件里的已知漏洞 osv-scanner --lockfile uv.lock # 8. 提交前闸门pre-commit 自动跑一遍所有检查 pre-commit install pre-commit run --all-files # 9. 项目体检看看代码规模 tokei .这一套流程跑下来如果有问题的环节会非常早知道环境不对会在第 1 步炸依赖冗余会在第 6 步出现安全问题在第 7 步暴露格式问题在第 8 步被拦截测试挂了在第 5 步就被 watchexec 喊出来。你不需要在写代码时分心去记着这些检查它们自己会来找你。我现在的日常基本就是开一个终端挂着 watchexec然后专心和 AI 对话聊需求。AI 给出代码 → 我粘贴进项目 → 保存 → watchexec 自动跑测试 → 偷偷盯一眼结果 → 没问题就 git add、commit → pre-commit 自动收尾。对话全部在 llm CLI 里做完敏感片段用 Ollama 兜底每周跑一次 deptry、osv-scanner、tokei 做定期体检。整个节奏非常流畅焦虑自然就少了很多。6. 常见问题与排查技巧实录6.1 我踩过的坑和速查表这套工具链我用了两三个月踩坑不算少。其中几个特别有代表性值得单独拿出来说。uv add 之后 pre-commit 报找不到 ruff。这个坑的本质是两套环境隔离pre-commit 在自己隔离的虚拟环境里跑 hook跟你项目里的 uv 环境不互通。解决办法不是去激活项目的 uv 环境而是在.pre-commit-config.yaml里通过 remote repo 从 GitHub 拉取 ruff而不是通过命令写在本地环境里。deptry 误报 scrapy 未使用。我之前做爬虫项目代码里真的没有直接import scrapy它靠框架机制加载。deptry 不明就里报了“declared but unused”。这种场景不能全信输出得把这类库加进 ignore 列表或者移到 dev 依赖组语义上更准确。watchexec 监听整个项目导致 CPU 飙高。早期我直接watchexec -e py uv run pytest结果它把 .git、缓存目录全都监听了每次 commit 都要触发一遍。后来用-w参数只监听 src 和 tests再配合--debounce设防抖这才稳下来。llm logs 数据库越滚越大。llm 默认日志存在 SQLite 里时间久了体积会涨。其实不用担心性能但如果你想备份或迁移可以直接拷贝那个 db 文件。路径一般在~/.local/share/io.datasette.llm/logs.db我每次换电脑都把它一起带走。顺手整理一份速查表方便大家排查症状可能原因处理办法uv add 后脚本跑不起来lock 文件过期或未 sync先执行uv syncruff check 报大量 import 排序问题没有启用 I 规则或没跑 format补--fix再ruff format .deptry 把框架依赖误报为未使用动态导入、插件机制使用 ignore 配置或移入 dev 依赖组pre-commit 自动改完文件导致 commit 中断这是正常现象git add修改后的文件再重新 commitosv-scanner 扫出一堆问题依赖版本确实旧先看高危项优先升级修复版本watchexec 频繁误触发监听范围太广用-w限定目录用--debounce设置防抖6.2 给 vibe coder 的三条保命经验最后分享三条我踩过无数次坑之后总结出来的经验不一定全面但应该能帮你少走不少弯路。第一AI 可以把功能写出来但环境、依赖、安全、格式这些“工程卫生”必须由工具守住。别指望 AI 记住你项目的代码风格和依赖规范它的训练数据里没有你的项目上下文。把规则固化到工具链里让机器替你做纪律检查这是整套方案的核心。第二本地模型不是替代品但它是极好的“第二双眼睛”。尤其是代码 review 的时候云端的强模型可能给出很华丽的优化建议但本地模型反而更专注于眼前这段代码本身的边界问题。我经常让本地模型以“最严格的老程序员”人设来挑刺经常能发现云端版本忽略掉的细节。第三越 vibe 越要留记录。每次重要对话都放进 llm CLI 的日志库不只为回头搜索更为了让 AI 的“思考历史”成为项目文档的一部分。我自己有一次加班到很晚想不起一个关键决策的原因就是用llm logs -p 为什么选 SQLite找回的。那瞬间我真的觉得这一套工具链装得值。最后再补一句如果你觉得 9 个工具太多可以从 uv Ruff watchexec 三个开始它们的学习成本最低见效也最快。等习惯了“工具在背后替你盯”的感觉再把 deptry、osv-scanner、llm 这些加进来。工具是死的但工作流是活的真正治好焦虑的不是某一个工具而是你终于重新掌控了整个过程。