Gemini CLI:面向开发者的上下文感知工程代理 📅 2026/6/16 12:43:54 1. 什么是 Gemini CLI它不是另一个“终端聊天框”我第一次在终端里敲下gemini看到那个带 Google 蓝色图标的交互界面弹出来时并没有立刻去问“你好吗”——而是直接把当前目录下三个关键文件拖进 prompt 框敲了句“用 50 字以内告诉我这个项目到底在解决什么问题”三秒后它回了我一句精准到让我后颈发凉的话“一个基于 A2A 协议的轻量级多智能体调度框架核心是让 agent 之间能安全传递嵌套 JSON 任务但当前序列化层缺失。”这不是魔法。这是 Gemini CLI 的底层逻辑它不把你当“用户”而当“协作者”。它默认启动时就已加载当前工作目录的完整文件树结构.gitignore规则生效自动识别语言类型、依赖关系、测试入口和主流程入口。你不需要手动file或folder注入上下文——它已经站在你的工程视角里和你一起看代码。它也不是 Claude Code 的复刻。Claude Code 更像一位严谨的资深同事每一步推理都写在纸上而 Gemini CLI 更像一个你刚招进来的、刚读完全部代码库的应届生工程师——反应快、敢试错、会主动追问、能边改边测甚至会在你忘记加--dry-run时弹出确认框“你要真的覆盖src/agents/router.ts吗里面第 47 行有个未处理的 Promise 链。”关键词不是“AI”或“CLI”而是“上下文感知的工程代理”。它把 LLM 从“回答问题的机器”拉回到“参与开发的成员”位置。你给它一个git diff它能告诉你影响面你扔给它一个 GitHub issue URL它能自动 fetch 原始 issue 描述 相关 PR 最近三次 commit 的变更摘要再结合本地代码做交叉验证。这种能力不是靠 prompt 工程堆出来的而是靠它内置的Model Context ProtocolMCP——一种为代码协作专门设计的状态管理协议比传统 memory 更轻、更可追溯、更支持多人协同上下文共享。我实测过在一个 12 万行的 TypeScript 微服务项目里用gemini启动后首次ReadFolder ./src耗时 8.3 秒但后续所有FindFiles auth、ReadFile ./src/auth/middleware.ts、Edit ./src/auth/middleware.ts --line 124操作平均响应时间压在 1.7 秒内。为什么这么快因为它不是每次请求都重载整个 AST而是用增量索引缓存了符号表、调用链、依赖图三层元数据。你改了一行import它只刷新对应模块的引用关系而不是重新 parse 全项目。所以别把它当成“命令行版 Gemini 网页版”。它是 Google 把 Gemini 模型深度缝进开发者工作流的一次外科手术式集成——切口小但直达神经末梢。2. 安装与认证为什么必须用 Node.js v22背后有硬性约束很多人卡在第一步npx https://github.com/google-gemini/gemini-cli报错ERR_OSSL_EVP_UNSUPPORTED。这不是网络问题是 OpenSSL 版本不兼容。Node.js v18 默认用 OpenSSL 3.0而 Gemini CLI 的底层向量嵌入模块用于代码语义检索强制要求 OpenSSL 3.2 的EVP_PKEY_get_bn_param接口。v20 虽然支持但存在 TLS 1.3 握手超时缺陷v22 是第一个在 macOS ARM64、Windows WSL2、Linux x86_64 三大平台全链路通过 CI 测试的版本。提示不要用brew install node或 Windows 官方安装包。它们打包的二进制可能被系统 OpenSSL 劫持。必须用 NVM 精确控制运行时环境。我踩过的坑在 M2 Mac 上用 Homebrew 装的 Node v20.12gemini启动后能登录但执行search时永远卡在 “Fetching GitHub metadata…”。抓包发现它在尝试用 QUIC 协议连接 GitHub API而 Homebrew Node 的 libuv 编译时没启用 QUIC 支持。换 NVM 安装 v22.17.0 后问题消失。2.1 NVM 初始化的隐藏陷阱原文说source $HOME/.nvm/nvm.sh就完事但这是个巨大误区。NVM 的 shell 初始化分两层第一层shell 启动时加载$HOME/.nvm/nvm.sh注册nvm命令本身第二层nvm use 时动态 patchPATH、NODE_OPTIONS、npm_config_prefix并注入NODE_ENVdevelopment。很多人的.zshrc只写了第一层导致nvm use 22后node -v显示正确但npm install -g google/gemini-cli实际装到了系统 npm 全局目录/usr/local/lib/node_modules而非 NVM 管理的~/.nvm/versions/node/v22.17.0/lib/node_modules。结果就是gemini命令找不到或者找到的是旧版本。正确做法是把这两行都加进.zshrc或.bashrcexport NVM_DIR$HOME/.nvm [ -s $NVM_DIR/nvm.sh ] \. $NVM_DIR/nvm.sh # This loads nvm [ -s $NVM_DIR/bash_completion ] \. $NVM_DIR/bash_completion # This loads nvm bash_completion然后执行source ~/.zshrc nvm install 22.17.0 nvm use 22.17.0 nvm alias default 22.17.0验证是否真正生效which node # 应输出 ~/.nvm/versions/node/v22.17.0/bin/node which npm # 应输出 ~/.nvm/versions/node/v22.17.0/bin/npm npm config get prefix # 应输出 ~/.nvm/versions/node/v22.17.02.2 认证方式的实战权衡Google 登录 vs API Key vs Vertex AI三种认证方式不是平级选项而是按使用场景严格分层的认证方式适用场景请求配额安全边界我的实测延迟P95Google 登录个人学习、单机调试、临时项目探索60 RPM / 1000 QPD绑定 Google 账户无项目级隔离1.2s直连 Google AI endpointAPI KeyAI Studio中小型团队 CI/CD 集成、自动化脚本、需要日志审计可申请提升至 1000 RPM / 100k QPDKey 泄露账户泄露需配合.env gitignore1.8s经 Google Cloud Load BalancerVertex AI企业级生产环境、合规审计、私有模型微调、VPC 内网调用按项目配额支持自定义模型路由完全隔离于公共互联网支持 IAM 精细权限3.4s跨区域 gRPC 调用我推荐新手从 Google 登录开始但必须立即做一件事打开 AI Studio → Settings → “API Key Restrictions” → 勾选 “Restrict key to specific APIs” → 只选 “Gemini API”。否则一旦.env文件误提交你的 Google 账户就等于裸奔。API Key 方式要特别注意环境变量加载顺序。Gemini CLI 启动时会按以下优先级读取GEMINI_API_KEY环境变量最高优先级当前目录下的.env文件仅当dotenv包已全局安装~/.gemini/config.json中的apiKey字段最低优先级我遇到过最诡异的问题在项目根目录放了.env内容是GEMINI_API_KEYxxx但gemini死活读不到。排查发现是项目里package.json有type: module导致 Node.js 的 ESM 加载器拒绝读取 CommonJS 格式的.env。解决方案删掉.env改用export GEMINI_API_KEYxxx写进.zshrc或用npx dotenv -- dotenv run -- gemini启动。Vertex AI 方式适合已有 GCP 项目的团队。关键配置不是GOOGLE_APPLICATION_CREDENTIALS而是GEMINI_VERTEX_LOCATION必须显式设为us-central1或europe-west1和GEMINI_VERTEX_PROJECT_ID。漏设LOCATION会导致 403 错误提示 “Permission denied on resource project xxx”实际是 region 不匹配。3. 项目接入两种模式的本质区别与选择策略Gemini CLI 支持两种项目接入模式“新项目初始化”和“现有项目加载”。但它们的底层机制完全不同选错模式会导致 80% 的后续操作失败。3.1 新项目初始化它不是“创建空目录”而是“构建语义骨架”当你执行mkdir my-new-agent cd my-new-agent gemini然后输入 Write the encoder code for a transformer from scratch.Gemini CLI 并不会凭空生成代码。它做了三件事反向工程需求解析 prompt 中的 “transformer encoder” 关键词自动关联 PyTorch/Hugging Face 的标准实现范式如nn.MultiheadAttentionnn.LayerNormnn.Dropout组合并检测当前目录无requirements.txt推断需生成依赖声明骨架生成创建./src/encoder.py主逻辑、./tests/test_encoder.py占位测试、./requirements.txt含torch2.0、./README.md含 usage 示例上下文锚定在 MCP 内存中注册./src/encoder.py为 “primary module”后续所有Edit、Test操作默认作用于此文件除非你显式用/path切换。这相当于用 AI 做了一次 “TDD 前置建模”——它先帮你把接口契约、测试桩、依赖边界一次性定义清楚再填充实现。我对比过手动写同样功能平均节省 22 分钟从创建目录到可运行测试。注意新项目模式下search工具不可用。因为没有真实代码库供检索它会返回 “No search index available in empty context”。3.2 现有项目加载真正的杀手锏在于 “路径感知加载”原文说cd existing-project gemini就行但这是最危险的操作。Gemini CLI 默认只加载当前目录及其子目录完全忽略父目录和符号链接。如果你的项目结构是my-monorepo/ ├── packages/ │ └── core-agent/ ← 你想分析的包 ├── shared/ │ └── schemas/ ← 核心 schema 定义 └── tools/ └── ci-scripts/ ← 构建脚本而你cd my-monorepo/packages/core-agent gemini那么shared/schemas对 Gemini CLI 来说是 “不可见宇宙”——它看不到也猜不到。正确做法只有两种方案 A推荐用/path显式声明根目录启动gemini后在 prompt 框输入/path /Users/you/my-monorepo它会立即重建整个 monorepo 的文件索引包括shared/和tools/。耗时约 12~18 秒取决于文件数但后续所有跨包引用都能精准解析。方案 B用.geminiignore做精准裁剪在 monorepo 根目录创建.geminiignore# 忽略构建产物和大型数据集 node_modules/ dist/ *.log data/large-dataset.bin # 但强制包含关键共享目录 !shared/ !packages/core-agent/然后cd my-monorepo gemini。它会按 ignore 规则扫描只加载shared/和core-agent/跳过其他无关包速度提升 40%。我实测过一个 37 个包的 monorepo方案 A 加载耗时 15.2 秒方案 B 为 9.7 秒而盲目cd进子包导致的 “ModuleNotFoundError: No module named shared.schemas 错误平均让我多花 11 分钟 debug。3.3 项目上下文的 “热插拔” 能力为什么/path比重启更快Gemini CLI 的 MCP 协议支持运行时上下文切换。这意味着你不必为了分析不同项目而反复启停 CLI。比如你在分析core-agent时突然想查shared/schemas的某个 type 定义只需/path /Users/you/my-monorepo/shared/schemas它会卸载当前上下文加载schemas目录同时保留之前的对话历史MCP memory 不清空。再输/path /Users/you/my-monorepo/packages/core-agent它又切回来且记得你刚才在schemas里看过的TaskPayloadinterface。这种能力让 Gemini CLI 成为真正的 “多项目协作者”。我在一天内连续分析了 4 个不同技术栈的项目Python/Go/TypeScript/Rust全程只用一个gemini进程内存占用稳定在 480MB无任何泄漏。4. 核心能力实战从代码理解到可视化每个环节的避坑指南Gemini CLI 的五大能力代码理解、Bug 修复、测试生成、文档编写、可视化不是孤立功能而是一条完整的工程闭环。下面用我在Google-Agent-Development-Kit-Demo项目中的真实操作拆解每个环节的关键细节和血泪教训。4.1 代码理解别只问 “这是什么”要问 “它怎么被用”原文示例 Explore the current directory and describe the architecture of the project.是入门级用法。真正高效的方式是“角色驱动提问”。比如当我看到agents/目录下有router.ts,validator.ts,executor.ts三个文件我不问 “这三个文件干什么”而是问Act as a security auditor. Map all data flows that pass through router.ts, identify where sensitive fields (like api_key, token) are extracted, and flag any unvalidated deserialization points.Gemini CLI 的响应不再是泛泛而谈的 “router.ts 负责路由请求”而是数据流图HTTP Request → router.ts#parseRequest() → validator.ts#validate() → executor.ts#run()敏感字段提取点router.ts第 89 行const token req.headers.authorization?.split( )[1]未做正则校验风险点executor.ts第 152 行JSON.parse(task.payload)无 schema 校验可触发原型污染这种提问方式利用了 Gemini CLI 的工具链编排能力它自动调用ReadFile读取三个文件用FindFiles interface TaskPayload定位 schema再用Shell grep -n JSON.parse src/扫描反序列化点最后整合输出。实操心得对复杂项目首次理解务必用 “Act as [角色]” 开头。角色越具体如 “CI/CD 工程师”、“前端性能优化师”它调用的工具链越精准避免信息过载。4.2 Bug 修复为什么search不是万能的GitHub Issue 分析的三重验证原文中[search https://github.com/.../issues/1]看似简单但实际操作中90% 的失败源于 GitHub API 权限和上下文偏差。首先search工具不是直接爬网页而是调用 GitHub REST API 的GET /repos/{owner}/{repo}/issues/{issue_number}。这意味着如果 issue 是私有仓库必须用 Personal Access TokenPAT认证且 PAT 需有issues:readscope如果 issue 被 bot 自动关闭API 返回state: closed但 Gemini CLI 仍会尝试分析导致结论错误最致命的是API 返回的 issue body 是纯文本丢失所有 Markdown 渲染、代码块高亮、图片附件——而很多关键线索藏在截图里。我的解决方案是三重验证法API 层用search获取 issue 基础信息标题、描述、评论代码层用FindFiles json.dumpsReadFile定位疑似问题文件运行时层用Shell npm test -- --testPathPatternrouter复现错误捕获真实 stack trace。在ADK-Demo的 issue #1 中search返回的描述是 “Agent fails when sending nested objects”但 stack trace 显示TypeError: Converting circular structure to JSON。这时我立刻意识到问题不在json.dumps()缺失而在circular-json库未引入。search没法告诉你这个但Shell grep -r circular package.json可以。注意search的 URL 必须是完整 GitHub API 兼容格式。https://github.com/.../issues/1会被自动转为 API 调用但https://github.com/.../issues/1#issuecomment-123456会失败。务必用基础 URL。4.3 测试生成为什么pytest生成常失败关键在 “测试契约” 定义Gemini CLI 生成测试失败的主因不是代码写得差而是测试目标模糊。当你输入 Write a pytest unit test for this change in test_shared.py.它不知道你期望的测试粒度单元级集成级是否要 mock 外部依赖如 HTTP calls, database边界条件有哪些空输入、超长输入、特殊字符我的标准 prompt 模板是Generate a pytest unit test for the fix in shared/utils.ts. Requirements: - Test only the function serializeTaskPayload - Mock all external dependencies (no real network or file I/O) - Cover 3 cases: (1) normal nested object, (2) circular reference, (3) null input - Assert exact error message for case (2): Circular reference detected in task payload - Save test to ./tests/test_utils.py它生成的测试会严格遵循def test_serializeTaskPayload_circular_reference(): # Arrange circular_obj {} circular_obj[self] circular_obj # Act Assert with pytest.raises(ValueError, matchCircular reference detected): serializeTaskPayload(circular_obj)如果漏掉match断言它可能生成assert Circular in str(excinfo.value)这在 CI 中会因消息微调而失败。4.4 文档生成Markdown 不是终点summary.txt是交付物原文用 Save this summary in a .txt file and name it summary.txt生成文档但这只是起点。真正的工程价值在于让文档可追溯、可执行。我生成summary.txt后会立刻执行/path /Users/you/project-root WriteFile ./CHANGELOG.md --append然后粘贴summary.txt内容到 prompt 框但加上一行前缀[CHANGELOG v0.2.0] - Fixed: JSON serialization crash on circular references in agent tasks (fixes #1) - Added: Unit tests for serializeTaskPayload covering edge cases - Updated: README.md with new usage example for nested payloadsGemini CLI 会自动识别[CHANGELOG v0.2.0]为语义标记将内容插入CHANGELOG.md的正确位置按日期排序并更新README.md的 usage section。实操心得所有生成的文档必须用WriteFile直接写入项目文件而非保存为独立.txt。否则它只是 “幻觉产物”无法进入版本控制和 CI 流程。4.5 可视化Flowchart 不是画图是状态机导出原文 Generate a flowchart that shows how agents communicate...听起来很酷但 Gemini CLI 本身不生成图片。它调用的是MCP 导出的 DOT 语言描述。当你输入该 prompt它实际输出digraph AgentFlow { rankdirLR; node [shapebox, stylefilled, fillcolor#f0f8ff]; main [labelmain.py\n(Orchestrator)]; router [labelrouter.ts\n(Task Router)]; validator [labelvalidator.ts\n(Schema Validator)]; executor [labelexecutor.ts\n(Task Executor)]; main - router [labeltask request]; router - validator [labelvalidate payload]; validator - executor [labelvalid task]; executor - main [labelresult]; // Highlight fix location router [fillcolor#ffcccc, labelrouter.ts\n(Task Router)\n❌ Fixed: added json.dumps()]; }然后你可以复制这段 DOT 代码粘贴到 Graphviz Online 生成 PNG或用dot -Tpng flow.dot -o flow.png本地生成或更进一步用Shell pip install graphviz python -c \import graphviz; ...\自动化。这才是可视化的真实工作流Gemini CLI 输出可编程的中间表示DOT你用标准工具链渲染。它不绑定任何 UI却保证了可重复性和可审计性。5. 工具链详解每个内置工具的调用逻辑与失效场景Gemini CLI 的 12 个内置工具不是平铺列表而是按数据流向分层组织的。理解分层才能预判工具何时可用、为何失效。5.1 文件系统层工具ReadFile,WriteFile,Edit,FindFiles这是最底层也是最稳定的工具组。它们直接调用 Node.js 的fs模块不受网络影响。ReadFile path支持通配符ReadFile ./src/**/*.ts但会按字典序读取最大单次读取 2MB防 OOMWriteFile path --append追加模式下若文件不存在会自动创建但--force参数慎用它会静默覆盖Edit path --line 42不是 Vim 式编辑而是调用 AST 重写。它会解析文件为 ESTree定位第 42 行对应的 AST 节点再注入新代码。因此如果第 42 行是注释或空行它会报错 “No statement at line 42”FindFiles pattern本质是rg --type-add ts:*.ts -t ts pattern但结果会过滤掉node_modules/和.git/。想搜node_modules/必须用Shell rg pattern node_modules/。常见问题Edit修改后代码格式错乱因为 Gemini CLI 默认不调用 Prettier。解决方案在 prompt 中明确要求 “Use prettier.format() before saving”。5.2 代码分析层工具ReadFolder,ReadManyFiles,SaveMemory这些工具负责构建代码知识图谱。ReadFolder ./src递归读取所有文件生成file_index.json含文件大小、修改时间、语言类型和symbol_index.json含函数名、类名、导出项ReadManyFiles批量读取但最多 20 个文件。超过会自动分批增加延迟SaveMemory手动触发 MCP 内存持久化。默认每 5 分钟自动保存但大项目建议每完成一个任务后手动执行防止崩溃丢上下文。5.3 系统交互层工具Shell,GoogleSearch,WebFetch这是最易失效的层受网络、权限、沙箱限制。Shell command在受限沙箱中执行禁用sudo、rm -rf、curl -X POST等危险命令。想发 HTTP 请求必须用WebFetchGoogleSearch query调用 Google Custom Search API免费额度 100 次/天。搜索结果是纯文本摘要无链接WebFetch url支持 GET/POST但 POST 仅限application/json且请求体不能超过 1MB。它会自动处理重定向、gzip 解压、charset 转码。实操心得WebFetch是调试 API 的神器。比如你怀疑validator.ts调用的外部服务挂了直接WebFetch https://api.example.com/health它返回{ status: down, error: DB connection timeout }比翻日志快 10 倍。5.4 智能增强层工具search,Compress,Auth这些是 Gemini CLI 的差异化能力。search如前所述是 GitHub API 封装非通用搜索引擎Compress不是 ZIP而是语义压缩。它用 LLM 将 1000 行代码摘要为 200 字描述保留所有关键逻辑和风险点专为上下文长度受限设计Auth切换认证方式时它会自动清理旧 session 的 MCP 缓存防止凭据混用。6. 常见问题与排查技巧实录来自 37 个真实项目的故障库以下是我在 37 个不同项目Python/Go/TypeScript/Java/Rust中用 Gemini CLI 遇到的 Top 10 问题及根治方案。每一条都附带可复现的错误日志和一行修复命令。6.1 问题Error: Cannot find module typescript即使已全局安装现象gemini启动成功但执行ReadFolder ./src时崩溃报错找不到typescript模块。根因Gemini CLI 的 TypeScript 支持模块google/gemini-typescript-plugin需要本地node_modules/typescript而非全局。它不走NODE_PATH查找。修复在项目根目录执行npm install --save-dev typescript5.3.3注意必须指定版本。TS 5.4 的 AST 变更会导致插件解析失败。6.2 问题search返回 “Rate limit exceeded” 即使没调用过现象首次使用search就报限流但 GitHub 账户有充足配额。根因Gemini CLI 默认用未认证的 GitHub API60 次/小时而非你的账户。必须显式登录。修复在 CLI 中输入/auth login然后选择 “Login with GitHub”而非 “Login with Google”。6.3 问题Edit修改后npm test报语法错误现象Edit ./src/index.ts --line 10插入一行console.log(debug);保存后npm test失败提示SyntaxError: Unexpected token console。根因Edit工具默认插入代码时不检查当前文件的 TS/JSX 模式。index.ts是 TypeScript但console.log被插在了declare module块内。修复用ReadFile ./src/index.ts查看上下文再用精确 AST 插入Edit ./src/index.ts --ast-path Program.body[0] --insert console.log(debug);6.4 问题Shell npm run build卡住无输出现象Shell命令长时间无响应CtrlC 也无效。根因Shell工具默认设置timeout: 30000ms但npm run build可能超时。它不会显示进度只等结束。修复改用流式执行Shell npm run build --stream它会实时输出webpack的进度条。6.5 问题生成的test_*.py文件pytest找不到测试函数现象WriteFile ./tests/test_fix.py后Shell pytest tests/显示0 tests collected。根因Pytest 要求测试函数名以test_开头且文件名必须是test_*.py或*_test.py。Gemini CLI 生成的文件名是test_fix.py符合规则但函数名是def verify_fix():不符合。修复在 prompt 中强制命名规范Generate pytest file with functions named test_* and save as ./tests/test_router_serialization.py6.6 问题/path切换后ReadFile仍读旧文件现象执行/path /new/dir后ReadFile ./old/file.ts仍成功内容是旧的。根因ReadFile支持相对路径和绝对路径。./old/file.ts是相对路径它会从当前工作目录不是 MCP 上下文目录解析。修复一律用绝对路径ReadFile /new/dir/src/main.ts6.7 问题Compress后Edit无法定位原代码行现象用Compress生成摘要后再Edit某文件报错 “Line number out of range”。根因Compress不改变文件内容只改变 MCP 中的上下文表示。Edit仍按原始文件行号操作。摘要里的 “line 42” 是摘要的行号不是源文件的。修复Compress后先ReadFile确认当前文件状态再Edit。6.8 问题GoogleSearch返回结果全是广告现象GoogleSearch typescript optional chaining返回 10 条全是 “Best TypeScript Courses 2024”。根因Google Custom Search API 的免费层不支持广告过滤。修复换用WebFetch直接查权威源WebFetch https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#optional-chaining6.9 问题gemini进程内存持续增长最终 OOM现象长时间使用2 小时后gemini进程内存从 500MB 涨到 4GB系统变慢。根因MCP 内存未自动 GC尤其在频繁/path切换时旧上下文缓存堆积。修复定期执行SaveMemory --gc它会清理未引用的上下文块。6.10 问题WriteFile生成的文件Git 显示为 “not staged for commit”现象WriteFile ./README.md后git status不显示修改。根因WriteFile默认以0644权限写入但某些 Git 配置如core.filemodefalse会忽略权限变更导致 Git 认为文件未变。修复强制触发 Git 检测git add --chmodx ./README.md git restore --staged ./README.md或更简单WriteFile后执行Shell touch ./README.md。7. 进阶技巧让 Gemini CLI 成为你团队的 “隐形架构师”Gemini CLI 的终极价值不是替代你写代码而是把你从 “执行者” 升级为 “架构决策者”。以下是我在三个团队落地的实战模式。7.1 每日站会前自动生成 “Context Brief”我让团队成员每天晨会前执行cd $PROJECT_ROOT gemini EOF Act as engineering manager. Generate a 3-bullet Context Brief for todays standup: - What changed in last 24h? (git log --oneline -10) - What are top 3 open PRs? (gh pr list --limit 3 --state open) - What are failing CI jobs? (gh run list --limit 5 --status failure) Format as markdown, save to ./docs/daily-brief-$(date %Y%m%d).md EOFGemini CLI 自动调用Shell、WebFetch对接 GitHub CLI、WriteFile生成一份带链接的简报。晨