sem: entity-level diffs, blame and impact analysis on top of Git
Semantic version control => entity-level diffs, blame, and impact analysis on top of git. 28 languages via tree-sitter. Built for coding agents.
At a glance
- What is it?
- sem parses a repository with tree-sitter and diffs functions, methods and classes instead of lines. The pitch is aimed at coding agents, and the README is explicit about what it does and where it collides with existing tools.
- Who is it for?
- Adopt sem if you are wiring a coding agent into a Git repository and want structured change data, or if you review large diffs and want to see which functions moved rather than which line ranges shifted. Skip it if your work is mostly configuration, prose or data files, where tree-sitter entities do not exist and line diffs remain the honest representation.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The line diff problem sem is aimed at
A line diff answers a question about text. When a function is renamed, moved within a file, or reformatted, the line diff reports a deletion block and an insertion block, and the reviewer has to reconstruct the intent. sem takes the position that the unit of change in source code is the entity: a function, a method, a class. The README states the goal directly, that instead of lines changed sem tells you what entities changed. The tool is built for coding agents, and that framing matters. An agent that has just edited a file needs to know which functions it touched and what else depends on them, not which line numbers shifted. The same output is useful to a human reviewer, but the agent use case is the one the project organises itself around, and the surrounding Ataraxy Labs stack (weave for entity-level merge, inspect for semantic code review, opensessions for a tmux sidebar) is consistent with that.
How tree-sitter parsing turns a commit into an entity list
sem parses code with tree-sitter, extracts every function, class and method as an entity, and diffs at that level. The README claims support for 28 languages in the repository description and shows a badge reading 32, so the language count is not internally consistent in the material and should be checked against the current release notes rather than taken from either number. Two mechanisms are named in the command documentation that do real work here. The first is rename detection, which is what lets a moved or renamed entity be reported as the same entity rather than as a delete plus an add. The second is structural hashing, which is presumably how sem decides two entities are equivalent when their surrounding text has changed. sem stores its entity cache in SQLite outside the repository, under the OS cache directory by default. That choice keeps cache files out of the working tree, and the README states that repo-local overrides are ignored on purpose so the cache cannot dirty the tree. The cache root is controlled by the SEM_CACHE_DIR environment variable.
Installing sem and the GNU Parallel collision
The primary install path is a shell script pulled from the repository: curl -fsSL https://raw.githubusercontent.com/Ataraxy-Labs/sem/main/install.sh | sh. Homebrew users get brew install sem-cli, Windows users have winget install AtaraxyLabs.sem or scoop install sem, and Rust users can run cargo install sem-cli from crates.io or cargo install --git https://github.com/Ataraxy-Labs/sem sem-cli to build the latest main. There is a Docker path as well, building the image locally and running it with the current user id and a bind mount of the working directory. The npm wrapper installs into node_modules as @ataraxy-labs/sem; with Bun the README notes you must run bun pm trust @ataraxy-labs/sem so the postinstall script is allowed to download the binary. The name conflict is the part worth reading twice. GNU Parallel ships a sem binary at /usr/bin/sem as a symlink to parallel, and if both are installed they collide. The README's own diagnostic is sem --version, which tells you which binary answered. The suggested fixes are an alias to $HOME/.cargo/bin/sem, putting $HOME/.cargo/bin first on PATH, or using the npm and bun installs, which invoke through npx sem or bunx sem from node_modules/.bin and avoid the clash entirely. This is a real friction point on Linux machines that already have GNU Parallel, and it is the kind of thing that produces a confusing error before you have run a single semantic diff.
The four commands and what each one returns
sem diff is the core. With no arguments it diffs working changes; --staged restricts to the index, --commit takes a single revision, and --from with --to takes a range. Output format is selectable: -v adds word-level inline diffs for each entity, --format plain gives git status style output, --format json is documented as the format for AI agents and CI pipelines, and --format markdown targets pull requests and reports. Two modes work without a Git repository at all: sem diff file1.ts file2.ts compares two files directly, and sem diff --stdin reads a JSON array of file changes from standard input, with filePath, status, beforeContent and afterContent fields shown in the README example. sem impact takes an entity name and walks a cross-file dependency graph to show what breaks if that entity changes, with --deps for direct dependencies, --dependents for direct dependents, --tests to narrow to affected tests, --file to disambiguate when a name appears in more than one file, and --no-default-excludes to pull in paths that are excluded by default, which the README lists as generated, fixture, vendor, benchmark and build trees. sem blame reports who last modified each function, class or method in a file. sem log tracks a single entity through history, with -v to show the content diff between versions and --limit to cap the commits scanned. Run with no entity name, sem log reports repository-level hotspots (most-changed functions and classes, with author counts) and co-change pairs, described in the README as entities that repeatedly change in the same commits.
Where sem is the wrong tool
Entity-level analysis depends on tree-sitter being able to parse the file into named constructs. Files that contain no functions, classes or methods have nothing for sem to extract, and the entity diff has no vocabulary to describe them. Configuration files, prose, SQL migrations, data fixtures and generated artefacts fall into that category, and the README's own default exclusion list for impact analysis already names generated, fixture, vendor, benchmark and build trees, which suggests the authors expect those paths to be noise rather than signal. The second limitation is the cache. Because the entity cache lives outside the repository under the OS cache directory and repo-local overrides are deliberately ignored, the cache is shared across checkouts of the same machine rather than scoped per working tree. That is the right call for keeping the tree clean, but it means cache behaviour is tied to the machine and the environment variable rather than to the repository, which is worth knowing before you try to reproduce an agent's output on a different host. The third is the name collision described above: on a system with GNU Parallel installed, an unqualified sem may not be this tool at all. None of these are defects in the semantic model. They are boundaries on where the model applies.
How sem differs from git diff and from language servers
The nearest comparison is plain git diff, and the difference is the unit of comparison. git diff compares lines and leaves rename and move detection to heuristics that operate on text. sem compares entities and uses rename detection plus structural hashing to decide identity, so a function that moved within a file is reported as the same function in a new place rather than as two unrelated hunks. The second comparison is a language server or an IDE refactoring engine. Those also build a semantic model of the code, and they answer questions about references and definitions, but they do so inside an editor session, tied to a project configuration and a running process. sem puts the same class of question into a command that runs in any Git repository with no setup, and emits JSON that a pipeline or an agent can consume. The trade is depth for reach: a language server knows more about a specific language than a tree-sitter grammar does, and sem gives up that depth to work across the language set uniformly and to run headless. The third comparison is the rest of the Ataraxy Labs stack. weave is described as an entity-level git merge driver and inspect as semantic code review, so sem is the analysis layer rather than the merge or review layer, and the components are meant to be used together.
Maintenance, releases and licence
The project is active and not archived, with v0.24.0 released on 2026-08-31 and a push to main on 2026-09-09. The release cadence visible in the material is three releases across August 2026: v0.23.0 and v0.23.1 on the same day, then v0.24.0 nine days later. Pre-1.0 version numbers mean the command surface and output schemas can still move between minors, and anything you build against --format json should be pinned to a version you have checked. Upgrades have a dedicated path: sem update moves an existing installation to the latest release. The licence situation needs care rather than a summary. The repository metadata reports Apache-2.0, the README badge links to a LICENSE-MIT file and reads MIT, and the install instructions reference a crates.io package named sem-cli. Those three signals do not agree, and the discrepancy is something to resolve by reading the licence files in the repository before you depend on the tool in a distributed product. This is not legal advice; it is a note that the material contradicts itself on the licence identifier.
Editorial conclusion
Adopt sem if you are wiring a coding agent into a Git repository and want structured change data, or if you review large diffs and want to see which functions moved rather than which line ranges shifted. Skip it if your work is mostly configuration, prose or data files, where tree-sitter entities do not exist and line diffs remain the honest representation. Before relying on it, run sem --version to confirm you are calling the Rust binary and not the GNU Parallel symlink at /usr/bin/sem, and check whether the entity cache under the OS cache directory is acceptable for your environment or needs SEM_CACHE_DIR pointed somewhere else.
Community notes