JournalDeveloper Tools

Field guide / 5

sem gives coding agents entity-level diffs, not program semantics

sem can show agents which functions changed and what depends on them, but its tree-sitter graph remains a structural lens rather than proof of behavior.

Sep 4, 20265By ISH Team
sem gives coding agents entity-level diffs, not program semantics
Advertisement

sem gives coding agents entity-level diffs, not program semantics

Git can tell you which lines moved. A coding agent often needs a different map: which functions changed, and what calls them?

sem adds that view on top of Git. The independent open-source tool parses code with tree-sitter, extracts named entities such as functions, classes, methods, and types, then compares them across working changes, staged changes, commits, or arbitrary files. GitHub lists v0.24.0, published August 31, 2026, as its latest release.

The project describes this as “semantic version control.” sem recognizes more code structure than a line diff, but it does not understand behavior like a compiler, test suite, or formal model. It is structural code intelligence, useful for directing attention but unable to decide whether a program is correct.

Replace anonymous hunks with named entities

Git's default patch format groups added and deleted lines into hunks with nearby context. The Git documentation includes several algorithms and presentation controls, but lines remain the basic objects in the patch.

sem diff reports entities as added, modified, deleted, moved, renamed, or reordered. Its verbose view includes word-level changes inside an entity. JSON and Markdown output can feed an agent, CI job, or pull-request comment.

sem diff
sem diff --staged
sem diff --from HEAD~5 --to HEAD
sem diff --format json

The documented matcher works in three passes. First comes an exact entity ID. Next, a structural hash can match the same abstract syntax tree under another name. Finally, more than 80% token overlap counts as a probable rename. Whitespace and comments do not alter the structural hash.

This helps during a formatting sweep, where a line patch can bury the few meaningful changes. It can also present a moved function as a move rather than one deletion plus one addition. Named entities give agents stable retrieval targets instead of anonymous line ranges.

Diff is only one part of the tool

sem impact queries a cross-file dependency graph for dependencies, dependents, or affected tests. sem context puts an entity and its callers and callees into a chosen token budget. sem blame reports the last modification per entity, while sem log follows one entity through repository history.

sem impact authenticateUser --dependents
sem impact authenticateUser --tests
sem context authenticateUser --budget 4000
sem log authenticateUser -v

The README currently lists full entity extraction for 32 programming languages. TypeScript, Python, Go, Rust, Java, Swift, C++, SQL, and web component formats are included, though the extracted entity types differ. Python support identifies functions and classes. SQL support covers tables, views, functions, indexes, and other schema objects.

Its MCP server exposes eight corresponding operations to compatible coding agents. A refactor can begin with the target entity and its neighborhood, continue with the edit, and finish with an entity diff. If a team works across models through ish.chat or api.ish.chat, the structural query layer can stay independent of whichever model consumes it.

Syntax trees are not program behavior

Tree-sitter is an incremental parser that builds concrete syntax trees and can return useful results even when code contains syntax errors. Those properties suit editors and structural analysis. They do not prove that a refactor preserves behavior.

Static dependency recovery has blind spots. Dynamic dispatch, reflection, generated code, framework conventions, and string-built references can hide relationships. Broad language coverage does not make support identical because languages expose different entities and resolution rules.

Version 0.23.0 in sem's release history fixed package-index collisions, module-alias collisions, a language-wide scope-resolution precedence bug, stale Go method-parent IDs, and multi-document YAML IDs. That is ordinary maintenance for a graph tool. It also means “no dependents found” is a result from the current resolver, not proof that no dependent exists.

Keep the line patch, compiler, tests, and human review. sem helps decide where those checks should look. It does not replace them. The same limit applies to katalint's instruction checks: a clean result only says that one tool's rules found nothing.

Trial the explicit commands first

Installation options include Homebrew, Cargo, an npm wrapper, and release binaries. Start with direct commands on one real change:

sem diff --staged
sem impact yourChangedFunction --dependents
git diff --staged

Compare the entity view with the normal patch. Check whether rename detection is right, whether framework-specific edges appear, and whether JSON output reduces agent context without concealing relevant code.

sem setup makes broader changes. It turns entity-level output into the default Git diff, installs a pre-commit hook for staged blast radius, and adds a Claude Code prompt-submission hook on macOS and Linux. Test the explicit commands before changing a team workflow, then inspect what setup will modify. sem unsetup removes the integration.

Local use needs no account. According to the project, the entity cache sits outside the repository and local telemetry records command names only on the machine unless uploads are enabled. Cloud queries require a separate opt-in for each repository; login by itself does not upload the repository or send a query. The cloud consent documentation describes preview, audit, disable, and forget controls. Teams handling sensitive code should still verify settings and network behavior against their own policies.

Keep both views

Entity-level diffing fixes a presentation problem. Reviewers think “the authentication function changed,” not “lines 81 through 117 changed.” Agents benefit from the same names when requesting a smaller neighborhood before an edit.

The abstraction should not hide the evidence underneath. sem might match an entity correctly while its behavior changes. A graph might miss an edge. A cosmetic classification might not capture a language feature the parser does not model.

For a review, run sem diff --staged, inspect the named entities, then read git diff --staged and execute the repository's tests. Each step answers a different question, and none has to pretend it understands the whole program.

#sem#semantic diff#coding agents#Git#tree-sitter
Advertisement

Keep reading

Related stories

Browse the archive