- Zig 94.1%
- Python 4.5%
- Shell 1.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
test / test (push) Successful in 33s
- build.zig: Run.addPassthruArgs() replaces b.args; the corpus step takes
the stdlib as a LazyPath (std.Build.LazyPath.zig_lib) now that
b.graph.zig_lib_directory is gone.
- std.zig.Ast.parse takes ParseOptions: `.zig` becomes `.{}` (mode .zig,
recovering, as before).
- forEachChild: `errdefer` lost its |err| capture in 0.17, so its data is
a plain .node like `defer` (reading .opt_token_and_node panicked on any
file with an errdefer); `array_mult` is gone with the `**` operator.
`zig build corpus` walks the whole 0.17 stdlib without a panic.
- CI: the runner's PATH finds Zig 0.16; run on /opt/zig-0.17.0.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uZv7g8MJCfBfN4FRzUVtt
|
||
| .forgejo/workflows | ||
| scripts | ||
| src | ||
| tools | ||
| .gitignore | ||
| build.zig | ||
| CLAUDE.md | ||
| context.md | ||
| DESIGN.md | ||
| LICENSE | ||
| README.md | ||
simgrep
A fast structural clone detector for Zig codebases. It finds duplicated shapes — code with the same AST structure but different identifiers and literals — which plain text search and line-diff tools miss.
How it works
File Walker ──▶ Zig Parser ──▶ Fingerprint ──▶ Report
(std.zig) (Merkle)
Each subtree is fingerprinted with a Merkle hash computed over its structure,
not its spelling, so fn addUser(a: u32) and fn addItem(b: u32) with the
same body collapse to the same fingerprint.
Build
zig build -Doptimize=ReleaseFast
# -> zig-out/bin/simgrep
Usage
simgrep [options] <path>
| option | meaning |
|---|---|
--min-lines=N |
minimum line span to consider (default: 5) |
--min-clones=M |
minimum occurrences to report (default: 2) |
--format=FORMAT |
text or json (default: text) |
--ignore=PATTERN |
skip matching paths, repeatable |
--show-source, -s |
show the code of each clone's first occurrence |
--no-fail |
always exit 0, even when clones are found |
--help, -h |
show help |
Ignore patterns: * does not cross /, ** does. A pattern without / also
matches any path component — --ignore=*_test.zig skips test files anywhere.
Exit status
| code | meaning |
|---|---|
0 |
no clones found |
2 |
clones found (suppress with --no-fail) |
The non-zero exit on findings is deliberate, so simgrep can gate a build.
Examples
# survey a source tree, ignoring tests
simgrep --ignore=*_test.zig src/
# only substantial, widespread duplication
simgrep --min-lines=20 --min-clones=3 src/
# machine-readable, never fail the build
simgrep --format=json --no-fail src/
Raising --min-lines is the main noise control: short spans repeat naturally
in any codebase, so the default of 5 is a floor rather than a recommendation
for large trees.
License
MIT — see LICENSE.