最近在多个项目里用 Claude Code 辅助开发时遇到一个比较烦人的现象每次让它生成提交信息或 PR 描述底部总会自动附带一个会话 URL。单看一次没什么但一旦团队多人都在用 AI 编程工具Git 提交历史里就会混入大量类似“Claude session URL”的链接PR 页面也会被一长串工具生成痕迹占据。这篇文章就围绕这个现象展开先讲清楚 URL 是怎么进入提交信息和 PR 描述的再介绍几种可以稳定控制、清理甚至彻底关闭它的方案。内容偏向工程落地包含可直接复用的 Git hook 脚本、后处理脚本和团队配置建议适合正在使用 Claude Code、或者准备在团队里推广 AI 编程工具的开发者。1. 问题描述提交信息和 PR 描述里多出来的会话 URL1.1 现象示例先看一个最典型的场景。我在本地仓库完成代码改动后让 Claude Code 根据 diff 生成一条提交信息结果它给出的提交信息类似下面这样feat: 优化用户列表查询性能 - 增加数据库索引 - 将 N1 查询改写为批量查询 - 补充接口缓存 Claude session: https://claude.ai/share/xxxx-xxxx-xxxx如果是生成 PR 描述则可能是## 变更内容 1. 用户列表接口性能优化 2. 新增批量查询逻辑 3. 调整索引结构 --- Claude session URL: https://claude.ai/share/xxxx-xxxx-xxxx第一眼看过去没什么问题但提交信息的作用是给后人快速理解“这次改动做了什么”而不是记录“这次改动是哪个 AI 会话生成的”。当仓库里几十个 commit 都带这种 URL 时提交历史会变得非常嘈杂。1.2 这个 URL 是什么这个 URL 本质上是 Claude / Claude Code 生成的会话链接用来表示“这段文本是由哪个 AI 会话辅助生成的”。它可能出现在提交信息里也可能出现在 PR 描述里具体取决于你使用 Claude Code 的方式、版本以及当时的交互模式。对个人项目来说这个链接可以帮你追溯某次提交背后 AI 的建议上下文对团队项目来说它更多是噪音甚至可能带来信息泄露风险因为会话链接背后往往关联着项目代码上下文。1.3 为什么默认会附加Claude Code 在设计上是一种“辅助编码代理”它生成提交信息和 PR 描述时会倾向于保留可追溯信息。这是工具为了透明性和可审计性做的设计并不代表所有团队都希望把这些内容写进 Git 历史。问题在于工具的默认行为和团队的实际需求经常不一致。默认值关注“来源可追溯”而团队更关注“提交信息干净、规范、可阅读”。1.4 影响范围这个现象影响的主要场景包括使用 Claude Code 生成 commit message 的开发者。使用 Claude Code 生成 PR 描述并直接提交到 GitHub / GitLab 的开发者。团队内多人使用 AI 工具且没有统一约定提交信息格式的情况。有严格提交信息校验如 commitlint、Conventional Commits的仓库。2. 环境准备与版本说明2.1 工具链本文涉及的实验环境是典型的本地开发环境包含以下部分操作系统macOS / Linux / WindowsGit hook 部分需要区分 shellWindows 建议使用 Git Bash。Git2.x 版本。Node.js用于运行后处理脚本。Claude Code当前文章写作时使用的 CLI 版本具体版本号会随着更新变化请以你本机实际安装版本为准。在开始之前请先确认 Claude Code 能正常工作claude --version如果提示claude: command not found说明还没有安装或没有加入 PATH。安装方式请参考官方 README常见方式是 npm 全局安装npm install -g anthropic-ai/claude-code需要注意的是不同版本的 Claude Code 在配置项名称、命令行参数上可能有差异。本文涉及的“关闭会话 URL”主要使用 Git hook 和脚本方案这类方案不依赖 Claude 内部配置稳定性更高。2.2 项目环境本文的示例项目是一个普通 Git 仓库包含一个模拟业务代码的文件。你可以用自己的仓库复现也可以按下面的命令初始化一个临时测试仓库# 创建一个临时测试目录 mkdir claude-session-url-demo cd claude-session-url-demo # 初始化 Git 仓库 git init # 创建示例文件 echo console.log(hello claude) index.js2.3 版本确认方法在阅读下文时如果某些命令在当前版本无效需要先查看当前版本的帮助信息claude --help同时也建议在官方文档中搜索“commit message”“session URL”“PR description”等关键词确认当前版本的默认行为是否发生了改变。因为 AI 编程工具迭代很快今天有效的方式下个版本可能会变化。3. 从 Git 提交到 PR 描述会话 URL 是怎么“跑”进去的3.1 Claude Code 生成提交信息的过程Claude Code 生成提交信息时通常会读取当前工作区的 Git diff、Git 状态以及最近几条提交记录然后调用大模型生成一段符合规范的提交信息。它会读取的信息大致包括git diff --staged暂存区的变更内容。git status哪些文件被新增、修改、删除。git log --oneline -5最近的提交风格尽量让生成的提交信息看起来符合仓库习惯。当模型生成提交信息时如果系统提示词或模型本身倾向于补充“AI 辅助生成”的标记那么输出就可能包含会话 URL。3.2 附加 URL 的触发条件根据我的观察并不是每次都会附加 URL以下情况更容易出现使用较新的 Claude Code 版本。在交互式会话中直接让它“生成提交信息”。使用claude命令并传入“输出提交信息”的提示词。当前项目目录下没有自定义 CLAUDE.md 规则。如果使用纯 API 接口自己写代码生成提交信息就不会有这个问题因为附加 URL 的行为来自 Claude Code 客户端而不是模型本身。3.3 为什么不是所有提交都带有些开发者可能发现自己用了很久提交信息里并没有 URL。这可能是因为你使用的是旧版本。它只在特定命令模式下才会附加。你的提交信息模板被其他工具覆盖了。你使用了git commit -m手动指定完全没有经过 Claude Code 生成。所以如果你需要复现这个现象更好的方式不是“所有提交都会带”而是“在 Claude Code 生成的提交信息中有概率出现”。这更像一个工程规范问题而不是绝对 bug。4. 完整复现与观察为了让后续方案更有说服力我们可以在临时仓库里完整复现一次“生成提交信息 - 观察 URL”的过程。4.1 初始化示例项目首先创建模拟代码并提交一次初始版本mkdir claude-session-url-demo cd claude-session-url-demo git init echo console.log(hello claude) index.js git add index.js git commit -m chore: init project然后修改代码制造一次新的变更echo console.log(hello claude with session url) index.js git add index.js此时我们有了一个暂存区变更。4.2 使用 Claude Code 生成提交信息在项目目录下运行claude然后输入提示词请根据当前暂存区变更生成一条符合 Conventional Commits 规范的提交信息Claude Code 可能会先展示它生成的提交信息然后询问你是否直接执行提交。如果你选择“是”git commit就会执行提交信息中可能包含会话 URL。如果使用的是非交互模式也可以这样尝试claude -p 根据当前 git diff 生成一条提交信息注意-p参数在不同版本中可能不同请以claude --help输出为准。4.3 使用 Claude Code 生成 PR 描述生成 PR 描述的流程类似可以在交互模式中输入请根据当前分支和最近提交生成一份 GitHub PR 描述Claude Code 会基于分支名、diff、提交历史生成一段描述。如果它把会话 URL 放在文末那么你直接粘贴到 GitHub / GitLab 提交时PR 描述里就会出现该 URL。4.4 观察结果查看刚才提交的信息git log -1如果生成了带 URL 的提交信息你会看到类似这样的内容feat: 更新示例代码 - 替换字符串 Claude session: https://claude.ai/share/xxxx-xxxx这就是整个“污染”过程。接下来我们关注如何控制。5. 三种关闭或控制方案5.1 方案一在配置层让 Claude Code 不附加 URL这是最直观的思路不过麻烦在于不同版本配置项不一致。在 Claude Code 中你可以通过项目级规则文件来约束生成风格。这里说的是CLAUDE.md把它放在项目根目录或者放在~/.claude/CLAUDE.md作为用户级规则。例如在CLAUDE.md中加入以下内容# 提交规范 - 生成提交信息时只输出提交信息正文不附加任何工具链接、说明或会话 URL。 - 生成 PR 描述时不要追加 Claude 相关链接。 - 如果历史提交中有类似内容不要模仿。这种方式不是“强制关闭”而是通过提示词约束生成结果。对多数情况有效但模型仍有可能在部分交互中忽略规则。另外建议执行claude --help查看当前版本是否提供“禁用 URL 嵌入”“关闭引用”之类的开关。如果存在直接开启即可如果没有就继续看后面的通用方案。5.2 方案二用 prepare-commit-msg 钩子自动清理Git 提供了prepare-commit-msg钩子它会在提交信息编辑器打开之前执行适合用来修改提交信息内容。我们可以在这个钩子里过滤掉包含“Claude session URL”或claude.ai/share的行。这样可以做到“无论哪个工具生成的提交信息只要包含会话 URL都会被自动清理”。5.2.1 创建 hook 文件在.git/hooks目录下创建prepare-commit-msgtouch .git/hooks/prepare-commit-msg chmod x .git/hooks/prepare-commit-msg5.2.2 Bash 版本 hook编辑.git/hooks/prepare-commit-msg写入以下内容#!/bin/sh COMMIT_MSG_FILE$1 COMMIT_SOURCE$2 SHA$3 # 备份原内容 MSG$(cat $COMMIT_MSG_FILE) # 删除包含 Claude session URL 的行 MSG$(printf %s\n $MSG | grep -v -i claude session ) MSG$(printf %s\n $MSG | grep -v -i claude.ai/share ) MSG$(printf %s\n $MSG | grep -v -i claude.*url ) # 清理多余空行 MSG$(printf %s\n $MSG | sed -e s/[[:space:]]*$// ) MSG$(printf %s\n $MSG | awk NF || !done { print; if (NF) done1 } ) MSG$(printf %s\n $MSG | awk NF { lastNR } { lines[NR]$0 } END { if (last0) for (i1; ilast; i) print lines[i] } ) # 写回提交信息文件 printf %s\n $MSG $COMMIT_MSG_FILE要点说明COMMIT_MSG_FILE是提交信息文件路径。grep -v -i用来删除包含关键词的行。最后几步用来清理行尾空格和文件尾部多余空行避免提交信息以空行结尾。这个方案的好处是不管提交信息是谁生成的只要包含claude session或claude.ai/share都会在提交时被自动移除。5.2.3 Node.js 版本 hook如果你和团队成员都安装了 Node.js用 Node 写 hook 更容易跨平台维护。下面是一个示例#!/usr/bin/env node const fs require(fs); const commitMsgFile process.argv[2]; if (!commitMsgFile) { process.exit(0); } let content fs.readFileSync(commitMsgFile, utf8); // 将内容按行拆分过滤掉包含会话 URL 的行 const lines content.split(/\r?\n/); const filtered lines.filter((line) { const lower line.toLowerCase(); if (lower.includes(claude session)) return false; if (lower.includes(claude.ai/share)) return false; if (lower.includes(claude session url)) return false; return true; }); // 去掉末尾多余空行 while (filtered.length 0 filtered[filtered.length - 1].trim() ) { filtered.pop(); } const result filtered.join(\n) \n; fs.writeFileSync(commitMsgFile, result, utf8);将这段内容保存为.git/hooks/prepare-commit-msg并设置执行权限chmod x .git/hooks/prepare-commit-msg之后再进行git commit只要提交信息里包含 Claude 会话 URL都会被自动过滤。如果想在团队里统一生效可以把该 hook 文件放到项目目录下的.githooks/中并通过core.hooksPath指定git config core.hooksPath .githooks这样所有克隆该项目的开发者都能使用同一套 hook 配置。5.3 方案三包装claude命令提交前展示并清理如果你希望保留“让 Claude 生成提交信息”的体验又不想手动清理可以写一个简单的包装脚本。思路是先让 Claude Code 输出提交信息到临时文件然后运行清理脚本再交给用户确认。下面是一个 bash 示例#!/bin/bash TMP_FILE$(mktemp) # 让 Claude Code 生成提交信息并写入临时文件 claude -p 根据当前 git 暂存区改动生成一条 Conventional Commits 规范的提交信息不要输出任何解释 $TMP_FILE # 清理 Claude 会话 URL 行 sed -i -e /claude session/d -e /claude.ai\\/share/d $TMP_FILE 2/dev/null || \ sed -i -e /claude session/d -e /claude.ai\\/share/d $TMP_FILE # 查看清理后的提交信息 echo clean commit message cat $TMP_FILE echo # 确认后提交 read -r -p Use this commit message? [Y/n]: answer case $answer in [Nn]* ) echo Commit aborted. rm $TMP_FILE exit 1 ;; * ) git commit -F $TMP_FILE rm $TMP_FILE ;; esac注意sed -i 是 macOS 的写法sed -i是 Linux 的写法脚本里做了兼容。不同版本的 Claude Code 对-p参数支持程度不同如果没有这个参数请以交互模式替代。5.4 方案四PR 描述后处理脚本提交信息可以用 Git hook 清理PR 描述则更适合用脚本后处理。比如你让 Claude Code 生成了 PR 描述并保存到pr.md可以写一个小脚本删除 URL 行然后再复制到 GitHub / GitLab。Python 版本import re def remove_claude_session_url(text: str) - str: lines text.splitlines() filtered [ line for line in lines if not re.search(rclaude\s*session\s*[:]?\s*https?://, line, re.I) and not re.search(rclaude\.ai/share, line, re.I) ] return \n.join(filtered).strip() \n if __name__ __main__: with open(pr.md, r, encodingutf-8) as f: content f.read() cleaned remove_claude_session_url(content) with open(pr-clean.md, w, encodingutf-8) as f: f.write(cleaned) print(cleaned content written to pr-clean.md)Node.js / JavaScript 版本也可以同时用来验证 URL 有效性const fs require(fs); function removeClaudeSessionUrl(text) { return text .split(/\r?\n/) .filter((line) { const lower line.toLowerCase(); // 判断这一行是否看起来像 Claude 会话 URL const isClaudeSessionLine lower.includes(claude session) /https?:\/\/[^\s]/.test(line); const isClaudeShareLink lower.includes(claude.ai/share); return !isClaudeSessionLine !isClaudeShareLink; }) .join(\n) .trim(); } const content fs.readFileSync(pr.md, utf8); const cleaned removeClaudeSessionUrl(content); fs.writeFileSync(pr-clean.md, cleaned, utf8); console.log(Done: pr-clean.md);这个脚本的思路同样适用于其他 AI 工具生成的链接只需要把关键词替换一下即可。5.5 方案五团队统一配置 CLAUDE.md 规则如果是团队协作建议把规则写进仓库根目录的CLAUDE.md这样任何使用 Claude Code 的人都会被项目级规则约束。示例# Git 提交信息规范 1. 使用 Conventional Commits。 2. 提交信息末尾不要附加 Claude 会话 URL、AI 工具链接或任何无意义签名。 3. PR 描述中不要包含 Claude 会话 URL。 4. 如果必须保留可追溯信息请写到 PR 描述最下方的隐藏区域但建议不要写入 Git 提交历史。 # 工具使用约定 - 禁止在提交信息中生成工具宣传语。 - 禁止在代码注释中生成大段 AI 生成声明。这种方式是“软约束”配合前文的 Git hook “硬清理”可以做到双保险。6. 常见问题与排查思路下面整理了一些使用过程中常见的问题和排查思路。问题现象常见原因解决思路提交信息里总是出现 Claude session URLClaude Code 生成时自动附加使用 prepare-commit-msg 钩子过滤或在 CLAUDE.md 中明确禁止PR 描述中带 URL生成后没有人工清理使用后处理脚本删除 URL 行Git hook 没生效hook 文件没有执行权限或 hooksPath 未配置执行chmod x .git/hooks/prepare-commit-msg检查git config core.hooksPath手动git commit -m时也出现 URL手动复制了带 URL 的文本粘贴前清理文本也可以使用 commitlint 校验关键词CLAUDE.md 规则偶尔不起作用模型可能在长对话中遗忘规则把规则作为用户级配置~/.claude/CLAUDE.md并尽量使用简短、明确的指令Windows 环境下 hook 无法运行hook 需要 shell 环境使用 Node.js 版本 hook并配置core.hooksPath其他 AI 工具也有类似问题很多工具都有引用来源设计复用同款 hook把关键词替换为对应工具名担心会话 URL 泄露代码上下文会话链接可能关联项目内容不要将带会话 URL 的内容提交到公共仓库在 CI 中增加关键词扫描排查时可以按以下顺序检查先确认当前提交信息内容使用git log -1查看。检查 hook 是否存在且可执行ls -l .git/hooks/prepare-commit-msg检查 Git hooksPathgit config --get core.hooksPath手动执行一次 hook 脚本看看是否报错echo test commit message /tmp/msg .git/hooks/prepare-commit-msg /tmp/msg cat /tmp/msg如果手动执行正常说明 hook 本身没问题问题出在调用链或文件路径上。7. 最佳实践与工程建议7.1 提交信息保持干净是团队底线Git 提交信息属于长期保留的工程资产。提交信息里可以写清楚“为什么改”但不应该混入工具生成的链接和口号。我建议团队至少做到提交信息首行是简洁的动词开头。提交信息正文描述动机而不是堆砌文件列表。不使用“Generated by”“Powered by”之类的工具签名。需要 AI 辅助时可以保留在 PR 描述里但不要写入 Git 历史。7.2 会话 URL 不一定要“全部删除”有时候需要追溯“这个提交是 AI 生成的”这个诉求是合理的。与其完全禁止不如把内容放到固定位置。例如Git commit 支持各种trailer你可以约定使用自定义 footerfeat: 优化用户列表查询性能 - 增加索引 - 解决 N1 查询 Co-Authored-By: Claude noreplyexample.com如果团队希望保留会话 URL也可以放在 PR 描述底部的“备注”区域而不是每次提交都带。这样既满足可追溯性又不破坏提交信息可读性。7.3 用 Git hook 做刚性约束我建议在团队中采用“软约束 硬约束”组合软约束CLAUDE.md告诉 Claude Code 不要生成 URL。硬约束.githooks/prepare-commit-msg在提交时删除 URL。硬约束脚本需要纳入版本库并且让所有开发者执行git config core.hooksPath .githooks如果你不希望手工配置可以考虑在package.json的postinstall脚本中统一设置或在 CI 中校验提交信息。7.4 在 CI 中增加提交信息校验如果团队使用 GitHub Actions、GitLab CI 或其他 CI 平台可以增加一个简单的校验任务禁止提交信息包含 Claude URL 关键词。GitHub Actions 示例check-commit.ymlname: Check Commit Message on: push: branches: - main jobs: check-commit: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkoutv4 - name: Check commit messages run: | for sha in $(git log --format%H -3); do msg$(git log -1 --format%B $sha) if echo $msg | grep -E -i claude session|claude\.ai/share; then echo Blocked: commit message contains Claude session URL exit 1 fi done这类检查能在 CI 层面防止“漏网之鱼”。7.5 安全边界使用 Claude Code 时会话 URL 可能会关联到你的项目上下文。如果团队仓库是公开仓库尤其要注意不要将包含会话 URL 的提交推送到公共仓库。不建议在提交信息中附加任何包含内部代码上下文的链接。如果误将带会话 URL 的提交推送到了远程仓库需要先移除该提交并检查是否有敏感信息泄漏风险。在团队私有仓库中也不能默认所有成员都能访问会话链接需要谨慎处理。7.6 定期检查和更新AI 编程工具发布频率很快默认行为可能会变化。建议每隔一段时间做一次检查claude --help claude version git config --get core.hooksPath同时关注官方更新日志确认默认提交信息行为是否有变化。8. 写在最后如果你只是个人开发者偶尔让 Claude Code 生成提交信息看到多出来的 URL 手动删除一下就好。但如果你在团队里推广 AI 编程工具或者维护一个长期迭代的仓库我建议尽早把“提交信息净化方案”落地。整篇文章的核心思路其实只有三点先确认会话 URL 是怎么进入提交信息 / PR 描述的。用 CLAUDE.md 做软约束提示工具不要附加 URL。用 Git hook 和 CI 脚本做硬约束确保最终提交信息保持干净。我在实际项目里采用的就是“CLAUDE.md 软约束 prepare-commit-msg hook CI 关键词扫描”这套组合拳。落地之后提交历史里再也没出现过 Claude 会话链接AI 辅助开发的体验也好了很多。如果你也遇到过类似问题建议先从 hook 方案开始因为它不依赖具体工具版本稳定性最高。希望这篇文章能帮你解决提交信息被“AI 痕迹”污染的问题。