https://github.com/forketyfork/zwanzig
A static analyzer and linter for Zig
https://github.com/forketyfork/zwanzig
code-quality linter static-analysis zig
Last synced: about 23 hours ago
JSON representation
A static analyzer and linter for Zig
- Host: GitHub
- URL: https://github.com/forketyfork/zwanzig
- Owner: forketyfork
- License: mit
- Created: 2026-01-19T05:38:40.000Z (16 days ago)
- Default Branch: main
- Last Pushed: 2026-01-23T21:50:03.000Z (12 days ago)
- Last Synced: 2026-01-24T00:37:15.849Z (12 days ago)
- Topics: code-quality, linter, static-analysis, zig
- Language: Zig
- Homepage:
- Size: 432 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# zwanzig
[](https://github.com/forketyfork/zwanzig/actions/workflows/build.yml)
[](LICENSE)
[](https://ziglang.org/)
Zwanzig is a static analyzer and linter for Zig code, combining fast AST/token rules with CFG-driven analysis built on ZIR output.
## Quick usage
### Local
```bash
zig build
zig build run -- src/
```
### GitHub Actions (SARIF)
```yaml
permissions:
contents: read
security-events: write
- name: Run zwanzig analysis
run: |
zig build run -- --format sarif src/ > results.sarif || true
- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
```
## Features
- Rule/checker registration with shared `--do`/`--skip` filtering
- Lazy parsing with cached AST/tokens per file
- Type-aware analysis via ZIR
- CFG-based, path-sensitive checkers
- Graphviz DOT dumps for CFGs, exploded graphs, and path traces
- Parallel analysis across files
## Rules
AST/token rules:
- dupe-import: duplicate `@import` statements
- todo: `// TODO` comments
- file-as-struct: file naming based on struct-like top-level fields
- unused-decl: unused container-level declarations
- unused-parameter: unused function parameters
- unreachable-code: code after unconditional terminators or fully terminating branches
- empty-defer: empty `defer {}` blocks
- empty-errdefer: empty `errdefer {}` blocks
- shadowed-variable: name reuse across scopes
- sentinel-alloc: sentinel-terminated allocations losing sentinel type
- identifier-style: naming conventions for types/functions/values
Engine-backed checkers:
- unreachable-code-engine: constant-condition unreachable code
- optional-unwrap: forced optional unwraps with `.?`
- empty-catch-engine: empty `catch {}` blocks
- swallowed-error: catch blocks that ignore errors without rethrowing or logging
- store-violations-engine: allocator/resource misuse (double-free, leaks, use-after-free/close)
- stack-escape-engine: stack-backed values escaping via return or async/thread capture
## Limitations
- ZIR/type info requires valid, parseable Zig code
- Full type resolution needs complete build context; standalone analysis has limited type inference
- Nested-scope type info is still limited to module-level declarations
- Interprocedural analysis is limited to simple direct calls in a single file; cross-file calls are treated as external
- Incremental cache stores metadata only; CFG caching is planned but not yet wired in
## Docs
- Usage and CLI: [docs/USAGE.md](docs/USAGE.md)
- Configuration: [docs/CONFIG.md](docs/CONFIG.md)
- Output formats: [docs/OUTPUT.md](docs/OUTPUT.md)
- CI integration: [docs/CI.md](docs/CI.md)
- Inline suppressions: [docs/SUPPRESSIONS.md](docs/SUPPRESSIONS.md)
- Development notes: [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md)
- Rules and checker details: [docs/RULES.md](docs/RULES.md)
- Implementation notes: [docs/IMPLEMENTATION.md](docs/IMPLEMENTATION.md)
- CFG/analysis visualization: [docs/VISUALIZATION.md](docs/VISUALIZATION.md)
- Release process: [docs/RELEASE.md](docs/RELEASE.md)
- Sample config: [docs/zwanzig.sample.json](docs/zwanzig.sample.json)
## License
MIT