跳转至

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

  1. 打开 AI Platform 并登录。如果登录后看不到对应功能,请联系课程组确认账号权限。
  2. 在右侧边栏中打开 代理 API 密钥(Proxy API Keys)
  3. 点击右上角的 创建(Create)
  4. 填写密钥名称,例如 opencode-lab。过期时间可以留空,但建议设置为课程结束后不久,减少长期泄露的风险。
  5. 创建后立即复制完整密钥。密钥只会完整显示一次;关闭提示后,平台只保留便于识别的前缀,不能再次查看原值。

如果密钥丢失,可以在同一页面重新生成;如果不再使用,或者怀疑已经泄露,应当立即删除该密钥并创建新的密钥。

不要公开 API Key

不要把 API Key 写入 Git 仓库、opencode.jsonAGENTS.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,然后:

  1. 在 Provider 列表底部选择 Other
  2. Provider ID 输入 thu-ai,必须与 opencode.json 中的键一致。
  3. 粘贴从 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,provider ID 是否为 thu-ainpm 是否为 @ai-sdk/openai-compatiblebaseURL 是否完整包含 /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 配置 配置文件中的环境变量和密钥
运行 envprintenvset 当前环境变量
在对话中粘贴 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 运行 envprintenvset。排查环境问题时如果它想这么做,改成只查具体的某一个变量。
  • 在项目目录下启动 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.jsonsession-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 一直改不对怎么办

先自己确认问题描述是否准确 —— 很多时候是"现象"没说清。带上具体的输入、期望输出和实际输出再问一次。如果同一个地方反复失败,可以要求它先解释这段代码在做什么,往往能暴露它理解错了什么。