mcpField
S
sem

sem

本地服务
ataraxy-labs.com版本控制3.4k今天更新

关于 sem

sem 是基于 Git 的语义版本控制命令行工具,面向开发者和编码 Agent。它按函数、类和方法分析变更,并提供影响分析、检查、历史查询和审查证书。

主要功能

  1. 01按代码实体比较差异
  2. 02查找定义与引用
  3. 03分析变更影响和测试
  4. 04选择性运行项目检查
  5. 05生成审查证书
  6. 06查看代码图谱与历史

适用场景

  1. 01审查函数和类的变更
  2. 02找出代码修改影响的测试
  3. 03修改实体前追踪调用方
  4. 04为人工审查汇总提交范围

MCP 相关

`sem mcp` 命令将 sem 的各项操作作为 MCP 工具提供给 Agent。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"ataraxy-labs-sem": {
"command": "npx",
"args": [
"-y",
"@ataraxy-labs/sem"
]
}
}
}
启动命令npx -y @ataraxy-labs/sem

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@ataraxy-labs/sem0.28.2

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

属于 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

sem

Ataraxy-Labs%2Fsem | Trendshift

基于 Git 构建的语义版本控制。
sem 不会告诉你哪些行发生了更改,而是告诉你哪些实体发生了更改:函数、方法、类。

为什么选择 sem? · 将 sem 与 Agent 配合使用 · 安装 · 命令 · Agent(MCP) · 云端授权 · 发行版本

发行版本 Rust 测试 许可证 语言

sem 是一款基于 Git 运行的语义版本控制工具。它使用 tree-sitter 解析代码,将每个函数、类和方法提取为实体,并以实体而非行作为 diff 的单位。这意味着你看到的是“函数 blahh 已修改”,而不是“第 x-y 行发生了更改”。

它适用于任何 Git 仓库,无需设置。

云端查询按仓库选择加入:登录不会上传仓库或发送查询。有关公开/私有仓库的状态、预览界面、本地审计日志和忘记数据的控件,请参阅云端授权流程。

sem diff

将 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 configgit 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 Xsem find X --callers
sem refs Xsem find X --refs
sem context Xsem find X --context
sem entities PATHsem find --in PATH
sem log Xsem history X
sem blame FILEsem history --blame FILE
sem arch-diff RANGEsem certify RANGE --arch
sem topology OPsem graph --modules OP
sem dataflowsem graph --dataflow
sem system OPsem graph --system OP
sem promises verifysem check --promises
sem login、logout、whoami、review、xref、repossem cloud ...
sem cloud neversem cloud disable
sem setup、unsetup、telemetry、completions、update、statssem 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.vuetemplate/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 .cljcvar、函数、宏、多方法、协议、记录、类型
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 多种语言。

匹配方式

分三个阶段匹配实体:

  1. 精确 ID 匹配:修改前后是同一实体 = 已修改或未变化
  2. 结构哈希匹配:AST 结构相同但名称不同 = 已重命名或移动(忽略空白和注释)
  3. 模糊相似度:词元重叠率 >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 历史

Star 历史图表

许可证

MIT OR Apache-2.0

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。