Vibe Coding 环境配置¶
前言¶
四个 Vibe Coding Lab 统一使用 OpenCode 作为 AI Agent。本文说明安装、配置、Session 导出和提交要求。
先完成本文再开始 Lab 1
四个 Lab 都要求提交开发 Session。如果配置不正确,做完作业才发现无法导出 Session,会丢掉相应的分数。请先按本文配置好并试走一遍。
OpenCode 是一个运行在终端里的 AI 编程 Agent,它能读写你项目里的文件、运行命令、根据测试结果继续修改。与在网页上问答不同,它直接在你的项目目录里工作。
安装¶
curl -fsSL https://opencode.ai/install | bash
安装完成后验证:
opencode --version
后续升级:
opencode upgrade
命令找不到
如果提示 command not found: opencode,说明安装目录不在 PATH 里。重新打开终端,或者检查安装脚本输出的提示信息。
登录¶
opencode auth login
按提示选择提供方并填入 API Key。课程允许使用的模型清单见作业发布公告。
查看已登录的提供方和可用模型:
opencode auth list
opencode models
不要泄露你的 API Key
登录凭据保存在 ~/.local/share/opencode/auth.json。这个文件包含你的 API Key:
- 不要提交到任何 Git 仓库
- 不要出现在作业截图里
- 不要分享给同学
如果不小心泄露,立即到提供方后台吊销并重新生成。
课程配置¶
课程 AI Platform 提供兼容 OpenAI 格式的代理 API。你可以在平台中为自己创建 API Key,再把它作为自定义 Provider 接入 OpenCode。这样,OpenCode 的请求会经过课程平台转发,不需要在配置文件中填写模型厂商的密钥。
| 项目 | 地址 |
|---|---|
| AI Platform | https://lab.cs.tsinghua.edu.cn/ai-platform/ |
| API Base URL | https://lab.cs.tsinghua.edu.cn/ai-platform/api/v1 |
| 模型列表 | https://lab.cs.tsinghua.edu.cn/ai-platform/api/v1/models |
网页对话和代理 API 是两个入口
网页中的模型选择器用于 AI Platform 自带的对话界面;本节创建的「代理 API 密钥」用于 OpenCode、脚本等外部程序。OpenCode 应使用上表中的 API Base URL,而不是网页地址,也不能使用平台的登录密码代替 API Key。
申请 API Key¶
- 打开 AI Platform 并登录。如果登录后看不到对应功能,请联系课程组确认账号权限。
- 在右侧边栏中打开 代理 API 密钥(Proxy API Keys)。
- 点击右上角的 创建(Create)。
- 填写密钥名称,例如
opencode-lab。过期时间可以留空,但建议设置为课程结束后不久,减少长期泄露的风险。 - 创建后立即复制完整密钥。密钥只会完整显示一次;关闭提示后,平台只保留便于识别的前缀,不能再次查看原值。
如果密钥丢失,可以在同一页面重新生成;如果不再使用,或者怀疑已经泄露,应当立即删除该密钥并创建新的密钥。
不要公开 API Key
不要把 API Key 写入 Git 仓库、opencode.json、AGENTS.md、作业截图或聊天消息。OpenCode 的 Session 也可能保存终端输出和文件内容,导出 Session 时仍须按Session 检查与脱敏的要求进行检查。
添加自定义 Provider¶
新建或编辑 ~/.config/opencode/opencode.json。如果文件已经存在,应把下面的 provider 内容合并进去,不要覆盖原来的 share、其他 Provider 或课程配置。自定义 OpenAI 兼容 Provider 的字段也可以在 OpenCode Providers 文档中查询。
{
"$schema": "https://opencode.ai/config.json",
"share": "disabled",
"model": "thu-ai/glm-5",
"provider": {
"thu-ai": {
"npm": "@ai-sdk/openai-compatible",
"name": "THU Sub2API",
"options": {
"baseURL": "https://lab.cs.tsinghua.edu.cn/ai-platform/api/v1"
},
"models": {
"glm-5": {
"name": "GLM-5"
},
"glm-5.1": {
"name": "GLM-5.1"
},
"glm-5.2": {
"name": "GLM-5.2"
},
"glm-5.3": {
"name": "GLM-5.3"
},
"LongCat-2.0": {
"name": "美团 LongCat 2.0"
}
}
}
}
}
其中:
thu-ai是自定义 Provider ID,后面的认证步骤必须使用完全相同的 ID。@ai-sdk/openai-compatible用于平台提供的/chat/completions接口。options.baseURL必须以/api/v1结尾,不要填写网页地址,也不要再加/chat/completions。models中的键必须是/models接口返回的模型 ID。model的格式是provider-id/model-id。示例默认使用thu-ai/glm-5,也可以从配置中的其他 GLM 或美团模型中选择。share: disabled是课程强制要求。OpenCode 默认值是manual,会保留/share命令把对话公开分享;本课程要求完全禁用,避免作业内容外泄。
课程使用的 THU Sub2API Provider 只配置这里列出的 GLM 系列和美团 LongCat 模型。平台中的其他 Provider 保持独立;模型出现在其他模型列表中,不代表它属于本课程的 Provider。
配置文件支持 JSONC 格式,可以写注释。
项目级配置
除了上面的全局配置,你也可以在项目根目录放一个 opencode.json,只对该项目生效。同名的配置项以项目级为准,其余仍然使用全局配置。
保存 API Key¶
在项目目录中启动 OpenCode:
opencode
在 OpenCode 中输入 /connect,然后:
- 在 Provider 列表底部选择 Other。
- Provider ID 输入
thu-ai,必须与opencode.json中的键一致。 - 粘贴从 AI Platform 创建的完整 API Key。
这会把凭据保存在 OpenCode 的认证存储中,而不是写进项目配置。凭据文件通常位于 ~/.local/share/opencode/auth.json,其中包含明文密钥,不能提交到 Git 或作为作业附件上传。
也可以使用环境变量
在临时环境或自动化脚本中,可以在 options 中增加 "apiKey": "{env:THU_AI_PLATFORM_API_KEY}",并在启动 OpenCode 前设置同名环境变量。日常使用更推荐 /connect,避免把 Key 长期写在 shell 配置文件中。
验证配置¶
退出并重新启动 OpenCode,使配置重新加载。先在普通终端确认凭据和模型:
opencode auth list
opencode models thu-ai
opencode models thu-ai 应当列出类似 thu-ai/glm-5 的完整模型名。可以执行一次最小测试:
opencode run -m thu-ai/glm-5 "只回复 OK"
如果命令已经显示正在使用 glm-5,随后返回明确的上游账号、余额或欠费错误,说明 OpenCode 已成功加载 Provider、读取 Key,并把请求发送到了课程平台。此时重新创建 Key 通常不能解决问题,请按下方说明保留错误信息并联系课程组。
也可以进入交互界面,输入 /models,在 THU Sub2API 下选择模型。
常见问题¶
/models返回 401 或 403:密钥可能复制不完整、已经过期或被删除,当前账号也可能没有代理 API 权限。回到 AI Platform 的「代理 API 密钥」页面检查,必要时删除旧密钥并重新创建。No proxy configuration found for requested model:该模型没有配置到代理 API。以当前 Key 请求/models的结果为准,并检查opencode.json中的模型 ID 是否完全一致。重新创建 API Key 不会增加模型权限。- 返回上游账号、余额或限流错误:如果错误明确提到模型厂商的账号状态、余额、欠费或平台级限流,说明 Key 已经通过身份验证,但课程平台的上游服务暂时不可用。重新创建 Key 通常无效,请保留错误信息并联系课程组。
- OpenCode 中看不到
THU Sub2API:检查opencode.json是否是合法 JSON/JSONC,providerID 是否为thu-ai,npm是否为@ai-sdk/openai-compatible,baseURL是否完整包含/ai-platform/api/v1,以及修改配置后是否重新启动了 OpenCode。 - 能对话,但 Agent 不会调用工具:不同模型的工具调用能力不同。先确认使用的是课程公告推荐的模型,再新建 Session 测试;不要仅凭普通对话成功就认定该模型适合完成 Vibe Coding Lab。
密钥管理¶
- 每个人使用自己的 Key,不要与同学共享。
- 为不同用途创建不同名称的 Key,便于单独吊销。
- 不使用时删除 Key,长期使用时设置合理的过期时间。
- Key 一旦出现在聊天、截图、终端日志、Git 历史或公开 Session 中,应立即吊销,不能只删除明文。
- 提交作业前,继续按照Session 检查与脱敏要求导出和检查记录。
AGENTS.md 介绍¶
AGENTS.md 是一份写给 Agent 的项目工作说明。在项目目录中启动 OpenCode 时,OpenCode 会先读取这个文件;之后即使新开 Session,Agent 也会先看到这些说明,不需要你在每次对话中重新交代相同的背景。
可以把它理解成 Agent 加入项目时会先读的「入组须知」:README.md 主要告诉人这个项目是什么、如何使用;AGENTS.md 主要告诉 Agent 在这个项目里应该怎样工作。两者可以有少量重合,但面向的任务不同。
例如,假设你只对 Agent 说:
修复当前失败的测试。
如果 AGENTS.md 已经写明「不得修改 tests/」「测试必须单线程运行」「改完要跑 Clippy」,Agent 就能在处理这句话时同时遵守这些要求。你不必在每个新 Session 里把三件事再说一遍。
写在文件里不等于一定会执行
AGENTS.md 会影响 Agent 的做法,但不会自动运行其中的命令,也不能从技术上禁止 Agent 修改某个文件。Agent 仍可能理解错或没有完全遵守。因此你仍要运行测试,并用 git diff 查看它改了什么;真正需要限制工具权限时,应使用 OpenCode 的权限配置,不能只写一句「禁止修改」。
适合写什么¶
优先写每个后续 Session 都需要、仅看文件名又不容易知道的信息:
- 构建、测试、格式化和 Clippy 检查命令,以及它们的执行顺序
- 必须遵守的要求,例如「不使用第三方 crate」「不得修改
tests/」 - 代码结构和模块职责,例如解析参数、游戏状态、配置文件分别放在哪里
- 项目特有的坑,例如「测试必须单线程运行」「参数来自标准输入首行」
例如,Lab 3 值得写「评测环境把参数放在标准输入首行,而不是命令行」;Lab 4 值得写「运行测试时必须使用 --test-threads=1」。这些要求很容易在新 Session 中被忘掉,而且一旦忘掉就会做出方向错误的实现。
不必把 Rust 教材、完整题面或大段容易从源码看出的内容全部复制进去。一次会话中 Agent 能记住的内容有限,而每个新会话都会读取 AGENTS.md;文件写得过长,会挤占 Agent 处理当前任务的空间。一次性的当前任务直接在对话里说;密码、API Key 等敏感信息则任何时候都不要写进去。
一个 Rust 项目的例子¶
下面这份可以作为起点。构建、测试和检查命令要按当前作业的要求取舍,不需要保留没有用到的命令:
# 项目说明
## 构建与测试
- 构建:`cargo build`
- 测试:`cargo test`
- 格式检查:`cargo fmt --all --check`
- Clippy 检查:`cargo clippy --all-targets -- -D warnings`
提交前运行当前作业要求的命令。
## 编码要求
- Rust edition 2024
- 不使用 unsafe
- 错误处理用 Result,不要用 unwrap 掩盖错误
## 代码结构
- `src/main.rs`:只负责读取输入和输出结果
- `src/stats.rs`:实现统计逻辑,不直接读写标准输入
项目刚建立、只有一个 main.rs 时,「代码结构」可以先不写。等拆出模块后再补,让以后新开的 Session 能快速找到应该修改的位置。
在 OpenCode 里执行 /init,也可以让它扫描仓库并创建或更新一份 AGENTS.md。自动生成的内容只是初稿:请检查命令是否真的可运行、其中的要求是否与题目一致,再手工删掉空泛或重复的内容。更多规则和文件查找顺序见 OpenCode 官方说明。
要在正确的目录启动 OpenCode
如果文件是 textstat/AGENTS.md,在 textstat/ 或它的子目录中启动 OpenCode 都能找到它;在 textstat/ 的父目录启动则不会向下搜索。最稳妥的做法始终是先 cd 到项目根目录,再运行 opencode。
项目变化后记得更新 AGENTS.md
当构建命令、必须遵守的要求或模块职责发生变化时,同步更新 AGENTS.md。只记录以后每个会话都会用到的信息,不要把「正在修第几个测试」一类很快过期的进度堆进去。Lab 4 会明显感受到这一点。
运行和继续对话¶
在项目目录下启动交互界面:
opencode
这样 Agent 才能读到该项目的文件和 AGENTS.md。
也可以不进界面直接执行一次:
opencode run "把 tests 目录下失败的测试修好"
接着上一次的会话继续:
opencode run --continue "刚才那个测试还是没过"
指定某个会话继续:
opencode run --session <sessionID> "继续"
Session¶
内容和作用¶
Session 是 OpenCode 保存的一次开发记录。它不仅包含你和 Agent 的对话,还会记录 Agent 调用过的工具、读过的文件内容,以及运行过的命令和输出。
四个 Vibe Coding Lab 都要求提交 Session。助教用它确认作业经过了要求的 AI 开发过程,并在提交异常时定位问题;不会根据 Prompt 是否精彩或对话轮数多少评分。
Session 中可能出现你没有直接输入到对话里的内容:
| 情况 | Session 中可能保存的内容 |
|---|---|
| Agent 读取 shell 配置 | 配置文件中的环境变量和密钥 |
运行 env、printenv 或 set |
当前环境变量 |
| 在对话中粘贴 API Key | 明文的 Key |
| Agent 读取项目外的文件 | 文件内容 |
| Agent 访问文件 | 用户名和目录结构等路径信息 |
因此,Session 导出后不能直接提交,必须先检查;发现敏感信息时,还要完成脱敏。
查找会话¶
opencode session list
只看最近几条,或者输出 JSON 便于复制 ID:
opencode session list -n 10
opencode session list --format json
导出会话¶
opencode export ses_... > session-lab1.json
把 ses_... 替换成实际的 Session ID,并按当前 Lab 修改输出文件名。省略 Session ID 会弹出交互式选择列表,但仍要用 > 将结果保存为 JSON 文件。
做完立刻导出
不要堆到提交前才导出。opencode session delete 删除的会话无法恢复,如果作业还没提交就误删了会话,只能重做。
检查与脱敏¶
普通导出会保留完整的开发记录,也可能包含 API Key、Token、私钥等敏感信息。提交前要扫描导出的 JSON;只有发现真实的敏感值时才替换对应内容,不要删除、裁剪或替换正常对话和工具记录。
下面以 session-lab1.json 为例。其他 Lab 请换成实际文件名。
扫描常见的密钥前缀:
grep -nE 'sk-[A-Za-z0-9_-]{8,}|sk-ant-[A-Za-z0-9_-]{8,}|ghp_[A-Za-z0-9_-]{8,}|github_pat_[A-Za-z0-9_-]{8,}|glpat-[A-Za-z0-9_-]{8,}|AKIA[A-Z0-9]{8,}' session-lab1.json
扫描可能包含凭据的关键词:
grep -niE 'api[_-]?key|token|secret|password|passwd|credential' session-lab1.json
扫描私钥:
grep -nE 'BEGIN.*PRIVATE KEY' session-lab1.json
扫描家目录路径:
grep -nE '/(Users|home)/[A-Za-z0-9_.-]+' session-lab1.json
命令有输出不一定表示发生了泄露,例如正常对话中也可能出现 token 这个单词。请查看命中的具体内容,判断其中是否包含真实凭据或不应提交的文件内容。
密钥一旦随 Session 提交,就等于交给了助教;如果 Session 被推到公开仓库,密钥还可能被其他人直接获取。
公开仓库上的密钥会在几分钟内被盗用
GitHub、GitLab 这类平台上有大量自动扫描程序,专门抓取新提交里的 API Key。从你 push 到密钥被人拿去用,通常只需要几分钟,比你发现并吊销要快得多。
后果由你承担:Key 被用来跑大量请求,账单记在你头上;如果是学校或课程提供的 Key,还会影响其他同学使用。
删掉那次 commit 也没有用。 Git 会保留历史,而且扫描程序早就抓走了。唯一有效的处理是立刻吊销那个 Key。
具体要注意:
- Session JSON 不要提交到任何仓库。 它按提交要求上传到网络学堂作业,不是放进 Git。Lab 2 和 Lab 4 虽然在 GitLab 仓库里做,Session 也是单独上传,不要 commit 进去。
~/.local/share/opencode/auth.json不要提交。 这是 OpenCode 存凭据的文件。- 不要把 Key 写进代码。 需要用密钥时从环境变量读,例如
std::env::var("SOME_API_KEY")。写进源码就迟早会跟着 commit 出去。 - 给仓库配好
.gitignore。 至少排除session-*.json和.env。 - 提交前用
git diff --staged看一眼,确认没有意外带上不该有的文件。
作业仓库是私有的,但仍然要小心
课程的 GitLab 仓库是私有的,风险比公开仓库低。但私有仓库不等于安全:仓库可能被误改成公开,你也可能把同一份文件顺手推到自己的 GitHub 上。
习惯上就不要让密钥进入任何 Git 仓库,这样不必每次判断"这个仓库安不安全"。
最省事的做法是一开始就不让敏感信息进入 Session:
- 不要在对话里贴 API Key。需要让 Agent 用某个密钥时,让它读环境变量,不要把值告诉它。
- 不要让 Agent 运行
env、printenv、set。排查环境问题时如果它想这么做,改成只查具体的某一个变量。 - 在项目目录下启动
opencode,不要在家目录启动。这样它默认的工作范围就是项目本身。 - 如果 Agent 想读项目外的文件,先想清楚有没有必要。
- Session 导出文件不要放在 Git 仓库目录里。放到仓库外面,或者先加进
.gitignore,避免哪次git add顺手带上去。
先吊销,再处理文件
如果发现 API Key 泄露给别人,第一件事是到提供方后台吊销它并重新生成,不是先改文件。
Key 一旦离开你的机器就应当视为已泄露,删掉文件里的痕迹并不能挽回。
吊销之后,只替换导出文件中的真实敏感值,并验证处理后的文件仍是合法 JSON:
python3 -m json.tool session-lab1.json > /dev/null && echo "JSON 有效"
看到 JSON 有效 后,再重新运行上面的四条扫描命令。
如果泄露的内容很多
如果扫出大量敏感内容(例如整个 shell 配置文件被读进去了),逐个替换不现实,也容易漏。这种情况建议在一个干净的环境里重做一遍作业,产生一个新的 Session。
重做时注意上面「预防」那一节的几条。
其他命令¶
查看会话数据库位置:
opencode db path
查看用量统计:
opencode stats
提交要求¶
四个 Lab 都必须提交 Session。 这是确认作业确实通过 vibe coding 完成的依据。
每个 Lab 都要在网络学堂作业中上传一个或多个已经检查、并在必要时完成脱敏的 Session JSON。只有一个时命名为 session-lab<N>.json;有多个时依次命名为 session-lab<N>-1.json、session-lab<N>-2.json 等。
一个 Lab 用多个会话是正常的
一个 Lab 分几次做,或者会话太长后新开一个会话都很正常。将用到的 Session 分别导出、检查,并在必要时完成脱敏后全部上传即可。
Lab 2 和 Lab 4 还要在网络学堂作业的正文输入框中填写最终提交到 GitLab 的 commit 哈希。在仓库根目录运行 git rev-parse HEAD,复制它输出的完整哈希即可。正文中的 commit 必须与最终用于评分的 GitLab 提交一致。
常见问题¶
找不到 Session ID
用 opencode session list --format json,输出里有完整的 ID 和创建时间。
导出的文件很大,有好几 MB
正常。Session 包含完整对话和文件改动记录。不要手工裁剪,那会破坏文件结构导致助教无法导入。
Agent 写出的代码用了第三方库
Lab 1 和 Lab 3 在 OJ 上评测,只能使用题目允许的依赖。Lab 2 和 Lab 4 在课程分配的 GitLab 仓库中完成;是否可以增加依赖、允许修改哪些文件,以各 Lab 的说明为准。
Agent 一直改不对怎么办
先自己确认问题描述是否准确 —— 很多时候是"现象"没说清。带上具体的输入、期望输出和实际输出再问一次。如果同一个地方反复失败,可以要求它先解释这段代码在做什么,往往能暴露它理解错了什么。