关于 sem
sem 是基于 Git 的语义版本控制命令行工具,面向开发者和编码 Agent。它按函数、类和方法分析变更,并提供影响分析、检查、历史查询和审查证书。
主要功能
- 01按代码实体比较差异
- 02查找定义与引用
- 03分析变更影响和测试
- 04选择性运行项目检查
- 05生成审查证书
- 06查看代码图谱与历史
适用场景
- 01审查函数和类的变更
- 02找出代码修改影响的测试
- 03修改实体前追踪调用方
- 04为人工审查汇总提交范围
MCP 相关
`sem mcp` 命令将 sem 的各项操作作为 MCP 工具提供给 Agent。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
属于 Ataraxy Labs 技术栈的一部分:面向软件开发的 Agent 原生基础设施。另请参阅:weave(实体级 Git 合并驱动程序) · inspect(语义代码审查) · opensessions(编码 Agent 的 tmux 侧边栏)。
阅读宣言:https://ataraxy-labs.com/#thesis · 文章:https://ataraxy-labs.com/blogs · 大模型:https://ataraxy-labs.com/llms.txt
基于 Git 构建的语义版本控制。
sem 不会告诉你哪些行发生了更改,而是告诉你哪些实体发生了更改:函数、方法、类。
为什么选择 sem? · 将 sem 与 Agent 配合使用 · 安装 · 命令 · Agent(MCP) · 云端授权 · 发行版本
sem 是一款基于 Git 运行的语义版本控制工具。它使用 tree-sitter 解析代码,将每个函数、类和方法提取为实体,并以实体而非行作为 diff 的单位。这意味着你看到的是“函数 blahh 已修改”,而不是“第 x-y 行发生了更改”。
它适用于任何 Git 仓库,无需设置。
云端查询按仓库选择加入:登录不会上传仓库或发送查询。有关公开/私有仓库的状态、预览界面、本地审计日志和忘记数据的控件,请参阅云端授权流程。
将 sem 与 Agent 配合使用
四个问题,四个动词。每个动词都支持 --json。
| 问题 | 动词 |
|---|---|
| 它在哪里? | sem find、sem grep |
| 我的更改影响了什么? | sem impact |
| 它是否正确? | sem check |
| 人工应该审查什么? | sem certify |
它在哪里? 按名称查找函数、类或方法:
sem find parse_config
function parse_config src/config.py:1
谁调用了它(--callers)、它使用了什么(--refs),或查看它的代码及其调用者和被调用者(--context):
sem find parse_config --callers
function parse_config src/config.py:1
function load src/config.py:6
function test_parse_config tests/test_config.py:4
搜索文本,类似于 rg:
sem grep splitlines
src/config.py:2: pairs = [line.split("=", 1) for line in text.splitlines() if line]
我的更改影响了什么? 所有依赖某个实体的内容,以及需要运行的测试:
sem impact parse_config --tests
⚡ 1 tests affected:
tests/test_config.py
function test_parse_config (L4–5)
sem impact --diff HEAD --tests 可以针对你所有未提交的更改给出同样的答案。
它是否正确? 运行项目自己的编译器、类型检查器、代码检查工具和测试;如果只重新检查受更改影响的部分也能得出相同答案,就只检查这些部分。退出码 0 表示通过,1 表示失败,2 表示无法判断:
sem check
cmd FAIL full sh (0 rechecked, 279 ms)
`python3 -m pytest -q tests` exited 1:
E AssertionError: assert {'a': '1'} == {'a': '2'}
人工应该审查什么? 获取某个提交范围的审查证书:更改了什么、更改会遗留哪些调用者,以及哪些测试能够触达更改:
sem certify main..HEAD
# sem certificate 94f4bd74e26e..d73d4d092b43
1 files, 2 entities changed (1 added, 1 modified, 0 deleted, 0 renamed, 0 moved).
- modified `parse_config` (src/config.py:1): 2 static caller(s) in 2 file(s) that this change does not modify
对于支持 MCP 的 Agent,sem mcp 会将相同的动词作为工具提供(参见与 AI Agent 配合使用)。
安装
curl -fsSL https://raw.githubusercontent.com/Ataraxy-Labs/sem/main/install.sh | sh
或通过 Homebrew 安装:
brew install sem-cli
或在 Windows 上通过 winget 安装:
winget install AtaraxyLabs.sem
或在 Windows 上通过 Scoop 安装:
scoop install sem
或将 npm 封装安装到 node_modules:
npm install --save-dev @ataraxy-labs/sem
使用 Bun 时,信任此软件包,以便其 postinstall 脚本可以下载二进制文件:
bun add -d @ataraxy-labs/sem
bun pm trust @ataraxy-labs/sem
安装后,可随时更新到最新版本:
sem config update
或通过 cargo 从 crates.io 安装:
cargo install sem-cli
或从源代码构建最新的 main(需要 Rust):
cargo install --git https://github.com/Ataraxy-Labs/sem sem-cli
或从 GitHub Releases 获取二进制文件。
或通过 Docker 运行:
docker build -t sem .
docker run --rm -it -u "$(id -u):$(id -g)" -v "$(pwd):/repo" sem diff
与 GNU Parallel 的名称冲突
GNU Parallel 附带一个 sem 二进制文件(/usr/bin/sem),它是指向 parallel 的符号链接。如果两者都已安装,就会发生冲突。运行 sem --version 检查当前使用的是哪个版本。(#77)
快速解决方法:
# Option 1: alias in your shell profile (~/.bashrc, ~/.zshrc)
alias sem="$HOME/.cargo/bin/sem"
# Option 2: make sure cargo bin comes first in PATH
export PATH="$HOME/.cargo/bin:$PATH"
# Option 3: if installed via Homebrew
export PATH="$(brew --prefix)/bin:$PATH"
如果通过 npm/bun 安装,二进制文件位于 node_modules/.bin/sem,并通过 npx sem 或 bunx sem 调用,因此可以完全避免冲突。
命令
可在任何 Git 仓库中使用,无需设置。在 Git 仓库之外也可用于任意文件比较。
| 动词 | 回答的问题 |
|---|---|
sem find | 定义在哪里?谁调用它、它使用什么、周围有什么? |
sem grep | 这段文本出现在哪里? |
sem impact | 更改此实体或此差异会影响什么? |
sem check | 我的更改正确吗? |
sem certify | 人工应该审查此提交范围内的哪些内容? |
sem diff | 哪些函数和类发生了更改? |
sem graph | 代码之间是如何关联的? |
sem history | 此实体随时间发生了哪些变化?最后是谁更改的? |
sem cloud | 账户、云端审查、跨仓库查询 |
sem config | git diff 集成、遥测、补全、更新、统计 |
sem mcp | 面向 Agent 的 MCP 工具,提供相同的动词 |
sem <verb> --help 会显示所有标志及示例。
默认情况下,sem 会将 SQLite 实体缓存存储在仓库之外的操作系统缓存目录中。设置 SEM_CACHE_DIR=/path/to/cache 可覆盖缓存根目录;仓库本地的覆盖设置会被忽略,因此缓存文件不会弄脏工作树。
sem find
按名称查找实体定义,然后询问有关该实体的问题:谁调用它、它使用什么,或查看它及其周围代码。答案来自磁盘上的查询索引(index.sem,位于实体缓存旁边);首次在仓库中调用时会构建索引,后续调用则直接读取,无需守护进程。
sem find "function diff_command" # where it is defined ("type name" narrows by kind)
sem find diff_command load_config # several names in one call
sem find diff_command --callers # who calls it; says when the caller set may be incomplete
sem find diff_command --refs # what it calls and references
sem find diff_command --context # its code plus callers and callees, within a token budget
sem find diff_command --context --budget 4000 --hops 1
sem find --in src/auth.ts # every entity in a file or directory
sem find diff_command --in src/ # only definitions under src/
sem find --text "retry budget" # entity bodies containing a string, named by entity
sem find diff_command --json # JSON on any of the above
使用 --context 时,如果目标签名本身无法容纳,JSON 输出会报告 target_omitted: true。
sem grep
跨源文件进行文本搜索,输出兼容 rg 的 file:line:text 格式;如果索引中存在三元组倒排记录,则通过该记录提供搜索结果。
sem grep "TODO"
sem grep -i todo src/ # case-insensitive, under src/
sem grep -e foo -e bar --json # several patterns, hits kept apart
sem impact
如果某个实体发生更改,哪些内容会出问题:它的依赖项、传递依赖于它的内容,以及能够关联到它的测试。
sem impact authenticateUser # full impact
sem impact authenticateUser --deps # direct dependencies only
sem impact authenticateUser --dependents
sem impact authenticateUser --tests # the tests to run
sem impact authenticateUser --file src/auth.ts # disambiguate by file
sem impact --diff HEAD --tests # tests for the uncommitted change
sem impact --diff main..HEAD --json # one impact report per changed entity
在 JS/TS 工作区中使用 --diff 和 --tests 时,答案是模块图针对已更改文件选择的受影响测试(sem graph --modules affected-tests);其他情况下,答案来自实体图。--no-default-excludes 会包含生成文件、夹具、供应商、基准测试和构建目录。
sem check
在工作树上运行项目的编译器、类型检查器、代码检查器和测试,并输出一个判定结果:退出码 0 表示通过,1 表示失败,2 表示无法判定。每个检查器给出的判定结果都与该工具检查整个项目时一致;如果能证明只需重新检查变更可能影响的部分,且结果相同,就只重新检查这些部分,否则会完整运行该工具并说明原因。没有可检查的内容时返回 2,绝不视为通过。
sem check # every checker the project has
sem check --checkers ts,lint,tests # only these
sem check --base origin/main # against origin/main instead of HEAD
sem check --promises # also prove every promise in .sem/promises can fail
sem check --json # one JSON object with a verification certificate
检查器会根据项目自动检测。TypeScript、代码检查和 JS 测试(vitest、jest)会沿着模块图检查;Go 会重新检查受影响的包;Python 类型检查(按导入范围检查的 pyright,或 mypy)和 pytest 只会重新运行变更可能影响到的文件;C 和 C++ 只会重新编译 compile_commands.json 中包含变更文件的编译单元。Cargo、Gradle 或 Maven、dotnet 和 SwiftPM 会运行各自的构建流程,这些流程本身已经只会重新构建发生变更的部分;如果自上次通过以来没有输入变更,则会直接跳过(修改 TypeScript 文件绝不会触发 Rust 构建)。
如果修改的是 Python 函数体,且该函数声明了返回类型,那么其他文件可见的内容不会改变,因此只会重新检查该文件。
自定义命令放在 .sem/check.json 中,例如:{"commands": [{"run": "make lint", "inputs": ["src/**"]}]}。指定了 inputs 的命令,如果自上次通过以来这些输入都没有变更,就会跳过;未指定 inputs 的命令则每次都会运行。
sem certify
为一个提交范围生成审查证书:涉及的实体、签名变更及其遗留调用方、被调用方差异、履行或违背的承诺(及其佐证)、模块可达性变化(JS/TS)、受影响的测试,以及静态引用锥。--arch 则改为提供架构视图:新增或移除的数据路径、副作用、依赖、循环依赖和未发生变化的内容,并按重要程度排序。
sem certify main..HEAD # markdown certificate
sem certify main..HEAD --json # the full certificate
sem certify main..HEAD --arch # architecture delta
sem certify main..HEAD --arch --view # at most 10 ranked items
sem certify main..HEAD --html > view.html # one self-contained page
<base>...<head> 使用合并基点;只有一个引用时,表示 <ref>..HEAD。
sem diff
实体级差异,支持重命名检测、结构哈希和词级行内高亮。
# Semantic diff of working changes
sem diff
# Staged changes only
sem diff --staged
# Specific commit
sem diff --commit abc1234
# Commit range
sem diff --from HEAD~5 --to HEAD
# Verbose mode (word-level inline diffs for each entity)
sem diff -v
# Plain text output (git status style)
sem diff --format plain
# JSON output (for AI agents, CI pipelines)
sem diff --format json
# Markdown output (for PRs, reports)
sem diff --format markdown
# Compare any two files (no git repo needed)
sem diff file1.ts file2.ts
# Read file changes from stdin (no git repo needed)
echo '[{"filePath":"src/main.rs","status":"modified","beforeContent":"...","afterContent":"..."}]' \
| sem diff --stdin --format json
# Only specific file types
sem diff --file-exts .py .rs
sem graph
展示代码之间的连接关系。不带标志时显示实体依赖图(sem impact 和 sem find --context 所基于的图);通过标志选择其他层级。
sem graph --json # entities and the calls/references between them
sem graph --modules metrics # JS/TS module graph: density, cycles, depth, centrality
sem graph --modules blast-radius pkg-a # who breaks if pkg-a changes
sem graph --modules path src/a.ts src/b.ts
sem graph --dataflow # reads, writes and source -> sink paths
sem graph --dataflow --witness # experimental: witness tasks per static flow
sem graph --system # exact dependency versions from every lockfile
sem graph --system build --out sys/ # the layered whole-system graph
sem history
展示某个实体在 git 历史中的变更,并区分逻辑变更与外观变更。
sem history authenticateUser
sem history authenticateUser -v # with the content diff of each version
sem history authenticateUser --limit 20
sem history # repo hotspots and co-change pairs
sem history --blame src/auth.ts # who last changed each entity in the file
未指定实体时,sem history 会在实体级别分析仓库近期历史:热点(变更次数最多的函数/类及作者数量)和共同变更对(在相同提交中反复一同变更的实体:“修改其中一个时,别忘了另一个”)。
sem cloud、sem config
sem cloud login # API key, or GitHub when omitted
sem cloud enable # cloud queries for this public repo (shows what is sent, asks first)
sem cloud disable # stop cloud for this repo
sem cloud review listen <diff-id> # attach an agent to a cloud code review
sem cloud xref --json # cross-repo dependencies
sem cloud repos # where your code is stored
sem config setup # make `git diff` show sem's entity diff
sem config telemetry off
sem config completions zsh # shell completions
sem config update
sem config stats # local diff counters; nothing leaves your machine
旧命令名称
此前的所有命令名称和标志仍然可用,输出也保持不变。在终端中,sem 会在标准错误流中打印一行说明,告知新的写法;在 --json 模式下或输出被管道转发时,不会额外打印任何内容。
| 旧名称 | 新名称 |
|---|---|
sem callers X | sem find X --callers |
sem refs X | sem find X --refs |
sem context X | sem find X --context |
sem entities PATH | sem find --in PATH |
sem log X | sem history X |
sem blame FILE | sem history --blame FILE |
sem arch-diff RANGE | sem certify RANGE --arch |
sem topology OP | sem graph --modules OP |
sem dataflow | sem graph --dataflow |
sem system OP | sem graph --system OP |
sem promises verify | sem check --promises |
sem login、logout、whoami、review、xref、repos | sem cloud ... |
sem cloud never | sem cloud disable |
sem setup、unsetup、telemetry、completions、update、stats | sem config ... |
承诺
承诺是 Agent(或某个人)对代码库作出的声明,并以一项非通过即失败的检查记录下来。“完成”意味着检查通过。承诺存放在 .sem/promises/*.json 中;每条规则都可以附带一段人工编写的 "promise"。代码形状规则是 tree-sitter 查询,可用于 sem 能解析的任何语言;名称不以 _ 开头的每个捕获都算作违规,并且嵌套捕获只会在最外层节点报告一次。例如,.sem/promises/jsx-no-logic.json:
{ "laws": [
{ "id": "jsx-no-logic/conditionals",
"promise": "JSX contains no conditional rendering",
"forbidPattern": { "from": ["**/*.tsx", "**/*.jsx"], "within": ["jsx_expression"],
"query": "(ternary_expression) @conditional" } },
{ "id": "jsx-no-logic/inline-handler-bodies",
"promise": "JSX event handlers are references, not block bodies",
"forbidPattern": { "from": ["**/*.tsx", "**/*.jsx"], "within": ["jsx_attribute"],
"query": "(arrow_function body: (statement_block (_))) @handler_body" } }
] }
sem promises check # KEPT / BROKEN n per promise, then file:line:col capture snippet; exit 1 if any broken
sem promises check --changed src/App.tsx # only violations in these files (what an edit hook runs)
sem promises check --since main # only files changed since a ref, uncommitted and untracked included
sem promises status --json # id, kept, violation count per promise
sem check --promises # prove every promise can fail (each needs a mutation)
sem promises 未列在 sem --help 中;sem certify 会报告某个范围内哪些承诺已履行或遭到违反。同一文件也可与 sem graph --modules check --laws <file> 配合使用,从而为 JS/TS 工作区添加图和导入规则(forbid、only、acyclic、layers、forbidImport、allowImports)。使用 --changed 或 --since 时,这些规则仍会针对整个图运行,但只报告涉及已更改文件(或包含该文件的软件包)的违规。
若要让 Agent 在编辑后立即看到被违反的承诺,请在每次编辑后运行 scripts/promises-hook.sh。承诺遭到违反时,脚本会以状态码 2 退出,并将违规内容打印到 stderr;否则保持静默。在 Claude Code 中,可将其添加到设置中,作为 PostToolUse 钩子:
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write|MultiEdit",
"hooks": [ { "type": "command", "command": "sh /path/to/sem/scripts/promises-hook.sh" } ] } ] } }
脚本会从钩子 stdin 中读取 tool_input.file_path。其他运行环境也可以将已编辑的路径作为参数传入。例如,在 pi 中,扩展可在编辑和写入工具的 tool_result 处理程序中执行此操作:运行 sh promises-hook.sh <path>,并在脚本以状态码 2 退出时,将 stderr 追加到工具结果中。
用作默认 Git 差异视图
将 git diff 输出替换为实体级差异。无需更改任何命令,Agent 和人工用户都会自动获得 sem 输出。
sem config setup
现在,git diff 会显示实体级变更,而非行级变更。无需提示词,也无需配置 Agent。所有调用 git diff 的地方都会自动获得 sem 输出。此外,还会安装一个 pre-commit 钩子,显示暂存变更的实体级影响范围。
在 macOS 和 Linux 上,sem config setup 还会注册一个 Claude Code UserPromptSubmit 钩子(sem hook prompt-submit),用于在提交提示词时注入上下文;并会在 Edit、Write 和 MultiEdit 工具周围安装 sem hook tool。每次编辑后,该钩子都会告知 Agent 哪些同级实现未随已更改的方法一同修改、哪些调用方仍在使用刚刚更改的方法签名,以及哪些测试会触及此项变更,并提供运行这些测试的命令;无事可报告时则保持静默。它会以幂等方式编辑 ~/.claude/settings.json,先创建备份,并保留你已有的所有钩子。
如需禁用并恢复为常规的 git diff(同时移除会话钩子):
sem config unsetup
在每个拉取请求中显示实体级差异
添加 GitHub Action 后,每个 PR 都会收到一条固定评论,显示哪些函数、类和方法发生了变更。每次推送后,评论都会原地更新,并明确指出仅包含格式调整或注释修改的 PR:
# .github/workflows/entity-diff.yml
name: Entity diff
on: pull_request
permissions:
contents: read
pull-requests: write
jobs:
entity-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Ataraxy-Labs/sem/[email protected]
无需配置,无需 API 密钥,也绝不会导致构建失败。详情请参阅 action/。
云端加速(适用于大规模代码库和团队)
本地功能始终免费,而且始终快速:即使在冷启动的进程中,磁盘上的索引也能在几毫秒内响应日常查询,因此无需让进程保持运行,也不需要登录。你无需付费就能让自己的笔记本电脑运行得更快。
云端用于处理笔记本电脑无法胜任的任务。对于超大型单体代码库,首次在本地构建图可能需要几秒钟;团队共享的图不应由每位开发者各自重建;而 CI 希望无需检出代码就能使用图。sem cloud login 会将这些情况连接到 sem cloud,后者会为已注册的代码库保留预先构建且随时可用的图,并直接用它处理繁重的查询,而不是在本地重建。
sem cloud login # GitHub device flow, one time
sem impact myFunc --file src/foo.rs # served from the cloud's warm graph
它完全可选,而且过程透明:
- 尚未登录,或无法连接云端?sem 会在本地计算,并输出完全相同的结果。不会失败,结果也没有差异。
SEM_LOCAL=1会强制使用本地计算,即使你已登录也一样。- 小型代码库不会有任何变化,本地计算本来就很快。对于每次都要重建图、且这已成为瓶颈的大型代码库,云端才会带来提升。
以下相关命令均限定在云端账户范围内:
sem cloud logout # log out
sem cloud whoami # show current cloud identity
sem cloud enable # turn on cloud queries for a public repo (shows what's sent first)
sem cloud disable # stop cloud for this repo
sem cloud xref --json # cross-repo dependencies across your indexed repos
sem cloud repos # where your code is stored: cloud-indexed repos + local caches
sem cloud status # cloud + telemetry state for this repo (offline; sends nothing)
sem cloud share # cloud queries for a private repo, with extra confirmation
sem cloud forget # delete this repo's cloud index and unregister it
status、share、forget、list、preview 和 log 不会显示在 sem cloud --help 中,但都可按所列方式使用;每个命令均为只读操作,或会在发送任何内容前要求明确确认。
如果你的团队通过 sem cloud 进行代码审查,sem cloud review listen <diff-id-or-url> 会启动一个预先配置好的编码 Agent,使其加入审查并作为实时监听者,根据 diff 中的特定行回答审查者的问题。
解析内容
通过 tree-sitter 对 32 种编程语言进行完整的实体提取:
| 语言 | 扩展名 | 实体 |
|---|---|---|
| TypeScript | .ts .tsx .mts .cts | 函数、类、接口、类型、枚举、导出 |
| JavaScript | .js .jsx .mjs .cjs .es6 | 函数、类、变量、导出 |
| Python | .py .pyi | 函数、类、带装饰器的定义 |
| Starlark(Bazel、Buck2) | BUILD BUCK WORKSPACE PACKAGE .bzl .bazel .bxl .star | 构建目标、函数 |
| Go | .go | 函数、方法、类型、变量、常量 |
| Rust | .rs | 函数、结构体、枚举、impl、trait、模块、常量 |
| Java | .java | 类、方法、接口、枚举、字段、构造函数 |
| C | .c .h | 函数、结构体、枚举、联合体、typedef |
| C++ | .cpp .cc .cxx .hpp .hh .hxx | 函数、类、结构体、枚举、命名空间、模板 |
| C# | .cs | 类、方法、接口、枚举、结构体、属性 |
| Ruby | .rb | 方法、类、模块 |
| PHP | .php .inc .phtml .module | 函数、类、方法、接口、trait、枚举 |
| Swift | .swift | 函数、类、协议、结构体、枚举、属性 |
| Elixir | .ex .exs | 模块、函数、宏、守卫、协议 |
| Bash | .sh | 函数 |
| Fish | .fish | 函数 |
| Lua | .lua | 函数(全局、局部、表和方法形式) |
| HCL/Terraform | .hcl .tf .tfvars | 块、属性(嵌套块使用限定名称) |
| Kotlin | .kt .kts | 类、接口、对象、函数、属性、伴生对象 |
| Fortran | .f90 .f95 .f03 .f08 .f .for | 函数、子程序、模块、程序 |
| Vue | .vue | template/script/style 块 + 内部 TS/JS 实体 |
| XML | .xml .plist .svg .csproj + 另外 9 种 MSBuild/资源扩展名 | 元素(嵌套,按标签名标识) |
| ERB | .erb .html.erb | 块、表达式、代码标签 |
| Svelte | .svelte .svelte.js .svelte.ts(+ .test/.spec 变体) | 组件块 + rune JS/TS 模块 |
| Perl | .pl .pm .t | 子程序、包 |
| Dart | .dart | 类、mixin、扩展、枚举、类型别名、函数 |
| OCaml | .ml .mli | 值、模块、类型、类、外部声明 |
| Scala | .scala .sc .sbt .kojo .mill | 类、对象、trait、枚举、函数、val、扩展 |
| Nix | .nix | 绑定、inherit 声明 |
| Haskell | .hs | 函数、签名、数据类型、newtype、类、实例、类型同义词 |
| Elm | .elm | 值声明、类型别名、类型声明、端口注解、中缀声明 |
| Clojure | .clj .cljs .cljc | var、函数、宏、多方法、协议、记录、类型 |
| D | .d .di | 模块、函数、类、结构体、接口、联合体、枚举、模板、别名、单元测试 |
| Zig | .zig | 函数、测试、变量 |
| SQL | .sql .psql .pgsql .ddl | 表、视图、函数、索引、类型、模式、触发器、序列 |
此外还支持结构化数据格式:
| 格式 | 扩展名 | 实体 |
|---|---|---|
| JSON | .json | 属性、对象(RFC 6901 路径) |
| YAML | .yml .yaml | 节、属性(点分路径) |
| TOML | .toml | 节、属性 |
| EDN | .edn | 顶层映射条目(键为关键字) |
| CSV | .csv .tsv | 行(以第一列作为标识) |
| Markdown | .md .mdx | 基于标题的节 |
| LaTeX | .tex .latex .cls .sty | 节(part/chapter/section/…),以及 theorem/lemma/proof/figure/table/algorithm 和其他受跟踪的环境 |
其他所有内容都会回退到基于块的差异比较。
自定义扩展名和无扩展名文件
对于非标准扩展名的文件,请在项目根目录创建 .semrc:
.xyz = cpp
.j = json
.mypy = python
如果你已经配置了 .gitattributes 模式(diff= 和 linguist-language=),sem 也会读取这些模式。当两者定义了相同扩展名时,.semrc 优先。
对于完全没有扩展名的文件,sem 会根据内容自动检测语言(shebang 行、vim modeline,以及 package/import/use 语句等结构启发式规则)。无需配置即可支持 30 多种语言。
匹配方式
分三个阶段匹配实体:
- 精确 ID 匹配:修改前后是同一实体 = 已修改或未变化
- 结构哈希匹配:AST 结构相同但名称不同 = 已重命名或移动(忽略空白和注释)
- 模糊相似度:词元重叠率 >80% = 可能已重命名
这意味着 sem 不仅能检测新增和删除,还能检测重命名和移动。结构哈希还能区分外观变化(空白、格式)和实际逻辑变化。
与 AI Agent 配合使用(MCP)
需要基于 URL 的客户端?Streamable HTTP 预览版提供经过身份验证的本地只读访问;默认仍使用 stdio。
在 macOS 和 Linux 上,位于同一检出目录的客户端共用一个预热的仓库守护进程。
运行 sem mcp --status 检查状态。有关会话隔离、回退行为和当前平台限制,请参阅共享运行时约定和可复现基准测试。
sem mcp 会通过 stdin/stdout 启动一个 Model Context Protocol 服务。这不是一个供你亲自运行并查看输出的命令:而是由编码 Agent 在后台启动的服务,让它在工作期间可以向 sem 提问。这就是 mcp 与常规命令并列的原因。Agent 可以将核心操作用作工具:
| 工具 | 可解答的问题 |
|---|---|
sem_find | 它定义在哪里?mode:callers、refs 或 context;in 用于列出文件或目录 |
sem_grep | 这段文本出现在哪里? |
sem_impact | 修改此实体会影响什么?依赖项、依赖方、测试 |
sem_check | 我的修改正确吗?给出判定:通过、失败、无法确定 |
sem_certify | 人工应在此提交范围内审核什么? |
sem_diff | 两个引用之间哪些实体发生了变化? |
sem_graph | 实体、模块、数据流或系统图 |
sem_history | 某个实体是如何变化的?对文件使用 blame |
调用早期工具名称(sem_entities、sem_context、sem_callers、sem_log、sem_blame)的客户端仍能获得答复;这些名称只是不会列出。在审核监听器会话中(由 sem mcp --review 启动,sem cloud review listen 会进行设置),还会列出 join_review、wait_for_branch、reply_to_branch 和 list_open_branches。
Agent 为什么需要这些工具:它无需读取整个文件并消耗大量 token,而是可以询问“如果我修改 submitOrder,会有什么内容受到影响?”(sem_impact),或“只提供重构此函数所需的上下文”(使用 context 模式的 sem_find,会返回该函数的源代码,以及它的调用方和被调用方),并从依赖图中获得精确、确定的答案,而不是可能漏掉调用方的 grep 结果。
添加一次,然后像平常一样与 Agent 对话。它会自行调用这些工具。
Claude Code:
claude mcp add sem -- sem mcp
也可以使用一条命令同时安装技能,让 Agent 知道何时该使用 sem:
npx @ataraxy-labs/sem-skill
Cursor、Claude Desktop 或任何使用 mcpServers 配置的客户端:
{
"mcpServers": {
"sem": {
"command": "sem",
"args": ["mcp"]
}
}
}
如果 Agent 的 PATH 中找不到 sem,请使用二进制文件的绝对路径。无需单独安装:sem mcp 与其他所有命令都包含在同一个二进制文件中。
JSON 输出
sem diff --format json
实际输出示例,展示从一行逻辑变更到 Python 函数的变化:
{
"summary": {
"fileCount": 1,
"added": 0,
"modified": 1,
"deleted": 0,
"moved": 0,
"renamed": 0,
"reordered": 0,
"binary": 0,
"orphan": 0,
"total": 1
},
"changes": [
{
"entityId": "auth.py::function::authenticate_user",
"changeType": "modified",
"entityType": "function",
"entityName": "authenticate_user",
"startLine": 1,
"endLine": 6,
"oldStartLine": 1,
"oldEndLine": 4,
"oldEntityName": null,
"filePath": "auth.py",
"oldFilePath": null,
"oldParentId": null,
"beforeContent": "def authenticate_user(username, password):\n if not username or not password:\n return False\n return check_credentials(username, password)",
"afterContent": "def authenticate_user(username, password):\n if not username or not password:\n return False\n if not check_credentials(username, password):\n return False\n return True",
"commitSha": null,
"author": null,
"structuralChange": true
}
],
"binaryChanges": []
}
命名的变更类型分类(added、modified、deleted、moved、renamed、reordered)之和始终等于 total。orphan 是针对模块级变更的跨类别元数据计数,这些变更已包含在命名的变更类型分类中。beforeContent/afterContent 携带变更前后实体的完整源代码;当差异仅为表面差异(空白、注释)时,structuralChange 为 false。
作为库使用
sem-core 可通过 crates.io 作为 Rust 库依赖项使用:
[dependencies]
sem-core = "0.23"
weave(语义合并驱动程序)和 inspect(实体级代码审查)都使用了它。
架构
- 使用 tree-sitter 解析代码(原生 Rust,而非 WASM)
- 使用 git2 执行 Git 操作
- 使用 rayon 并行处理文件
- 使用 xxhash 进行结构哈希
- 每个仓库都有一个缓存目录(SQLite 实体缓存 + 可内存映射的查询索引),为
find/callers/refs/grep提供冷进程查询,无需后台守护进程 - 用于添加新语言和格式的插件系统(参见 CONTRIBUTING.md)
遥测
默认在本地运行:sem 只会在你自己的机器上统计命令名称(例如 diff、impact),且在这种模式下不会上传任何数据。不会记录代码、文件路径、仓库名称或用户身份,也不会进行网络调用。
sem config telemetry preview # see current mode and exactly what would be sent
sem config telemetry on # opt in: also upload counts to help improve sem
sem config telemetry off # record nothing at all
无论当前模式如何,设置 SEM_NO_TELEMETRY=1 或 DO_NOT_TRACK=1 都会强制不记录任何数据。开发版本(从 cargo build 的 target/ 目录运行的任何版本)绝不会记录数据,因此开发 sem 本身不会影响统计数据。
贡献
想要添加新语言?请参阅 CONTRIBUTING.md,了解分步指南。
Star 历史
许可证
MIT OR Apache-2.0
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。
