Skip to main content

Why can't coding agents detect code smells? Because they don't have a noze.

Coding agents are very good at producing code. They are also very good at producing the same helper three times, gently ignoring your architecture notes, and using dict[str, Any] when you ask for type safety. You ask it to complete a task like "a staff software engineer", you ask it to follow SOLID principles and use strong type safety. It happily agrees, and starts working on the task. The vibes are immaculate. You come back a few minutes later to a slopocalypse that looks nothing like what your AGENTS.md says and you spend hours trying to understand where to start.

Sensez is a suite of Rust CLIs with an MCP server for maintenance before tech debt accumulates. It runs beside your linter and type-checker and looks for cross-file problems they usually do not own: duplication, dead code, import cycles, boundary violations, and design smells. It is designed to give your coding agent the noze to detect code smells, the bonez to respect architectural boundaries, and the spine to do it fast.

Supported language profiles currently include Python, JavaScript, TypeScript, and Rust (for dogfooding primarily).

Docs: https://popov95s.github.io/sensez/latest/

Quick Start

Python

# Add as a project dev dependency; run it with `uv run sensez ...`
uv add --dev sensez
uv run sensez init

# Install as a global CLI so `sensez ...` works directly
uv tool install sensez
sensez init

# or run a one-off scan with uv
uvx sensez noze .

JS/TS

# Add as a dev dependency
npm install --save-dev sensez
# Generate a sensez.toml starter config
npx sensez init . 

# Run a one-off scan with npx
npx sensez noze .

sensez . and sensez noze . both run the default scan. The verbose form is still available as sensez noze sniff ..

Performance Snapshot

xychart-beta
  title "pylint benchmark seconds"
  x-axis ["sensez", "vulture", "repowise", "symilar"]
  y-axis "seconds" 0 --> 20
  bar [0.27, 1.29, 17.26, 20]

sensez scans all structural pillars in one pass (0.27s). vulture checks Python dead code (1.29s). repowise uses a custom ranking mechanism, including dead code (17.26s). symilar checks line-based duplication (234.12s; chart capped at 20s).

JS/TS

xychart-beta
  title "zod benchmark seconds"
  x-axis ["sensez", "fallow", "repowise"]
  y-axis "seconds" 0 --> 6
  bar [0.16, 0.48, 5.75]

sensez scans all structural pillars in one pass (0.16s). fallow checks JS/TS structural dead-code and dependency findings (0.48s). repowise checks repo intelligence signals, including dead code (5.75s).

sensez tries to lower dead code noise and allows for configuration of what gets reported. It also includes a few more Python and TS/JS opinionated smells, apart from overall structural consistency metrics.

Agent Impact

We gave the same coding agent 70 real-world Python tasks from SWE-PolyBench and SWE-bench Verified, plus 21 synthetic tasks designed to trigger specific maintainability traps. Both variants received SOLID/DRY principles. The Sensez variant additionally used the noze_sniff MCP tool in a mandatory feedback loop before declaring each task complete.

New quality issues Clone tokens New clones Lines written Tokens used
Without Sensez 14 1,251 129 2,080 1.23M
With Sensez 2 126 0 682 1.34M
Reduction 86% 90% 100% 67% +8.7% overhead

Sensez agents produced structurally cleaner code with 67% fewer lines.

Benchmarks used: SWE-PolyBench_500, SWE-bench Verified, and synthetic pillar tests. Full methodology and per-benchmark results in evals/.

The Problem

Coding agents drift. Not due to bad intentions, but because their loop is leaky.

  1. Context rots. You told the agent to respect boundaries, follow SOLID, and think like a staff engineer. Six turns later, the context has been summarized twice and the agent is confidently rewriting the same csv file parser your colleague wrote two weeks ago.

  2. CI is too late. CI is great at saying "absolutely not." It is much worse at saying "hm, this duplication is small but suspicious." Non-blocking warnings have a natural habitat: ignored forever.

  3. Slow checks do not fit the turn. If a check takes minutes, it should not run every agent turn. If it does not run every turn, the slop has time to ferment.

[Agent Proposes Turn Finish] ──> [ 👃 Sensez MCP Sniff ] ──> [ Catches Import Cycle / Duplication ]
                                   │
                                   └──> (Immediate Agent Feedback: "Loose typing violation on line 40 of code.py. Replace loose collections with dataclass/model.")

Sensez provides short, structured feedback directly to the agent while the edit is still fresh. Less archaeology, more "fix it before it becomes load-bearing."

noze

noze takes care of the gorgonzola coding agents love so much:

Area Output key What it catches
Duplication duplication Structural clones, including local rename copies.
Dead code dead_code Unreferenced symbols with confidence tiers.
Cycles cycles Import loops and load-order tangles.
Boundaries boundaries Imports crossing configured architecture rules.
Smells smells Design pressure inside functions, classes, modules, and the graph.

Some smell examples:

Smell Why noze flags it
tuple_packing Positional tuples hide meaning. tuple[int, str, int] is not a data model.
loose_typing Any and vague containers erase the contract callers need.
boolean_blindness do_thing(True, False) is a guessing game with arguments.
implicit_schema Repeated string-key access usually means a real shape is hiding in a dict.
mutated_parameter You pass a parameter and the function you sent it to returns it all chewed up. Disgusting.
feature_envy A method that mostly uses another object's data may belong somewhere else.
message_chain Long a.b.c.d chains couple callers to deep object plumbing.
god_module One module has become the place everything depends on.
magic_string_default Trying to lie to the type checker by adding an || "" or or "" to hide a string that should be required.
split_variable Multiple reassignments of the same variable within the same scope. Set to 1 to keep them constant within the scope and enforce helper functions for complex assignment logic.
nested_loops [BETA, can be noisy] Nested iterations may blow up exponentially if not handled properly
n_plus_one_call [BETA, can be noisy] Making external calls 1 by 1 (e.g. to a database) instead of using a batched approach.

noze is not a formatter, linter, or type-checker. Keep using Ruff, ty, mypy, ESLint, TypeScript, rustc, and Clippy. noze sits next to them and watches the repo-level shape.

The default report is intentionally fixable in one screen: each pillar shows only its top 5 offenders, each smell kind shows its own total plus top 3 examples, and dead-code output includes high-confidence findings only. Use --all to print every finding, or --max N to choose a different cap.

For CI, filter to the pillars you care about:

sensez noze . --duplicates
sensez noze . --duplicates --dead-code --json

MCP

MCP is the default integration path for agents. Use it when Sensez should run repeatedly during a coding session instead of shelling out for one-off scans.

sensez mcp serve

The MCP tools are themed but explicit:

Tool Use
noze_sniff Scan the repo for smells and structure issues.
noze_gate End-of-turn diff gate for agent hooks; experimental and can be noisy on short/Q&A turns.
noze_explain Explain a finding category.
brainz_report Summarize local usage and resolution metrics.
brainz_triage Record user-approved debt or false-positive verdicts.
eyez_search_docs [disabled] Search docstrings/comments when eyez is enabled.

You can also use the sensez noze CLI standalone in GitHub Actions.

brainz

brainz is local-only memory. It records scans, gate blocks, triage decisions, resolved findings, regressions, detector precision, and usage reports.

sensez brainz report .
sensez brainz report . --json

Everything stays under:

.sensez/local-metrics/

No telemetry. No source upload. Disable it per repo:

[self_improvement]
enabled = false

Configuration

Sensez reads sensez.toml from the project root, or [tool.sensez] from pyproject.toml when sensez.toml is absent.

sensez init . --yes

Main knobs:

  • [duplication] for clone thresholds
  • [dead_code] for dynamic entrypoints
  • [smells] for smell toggles and thresholds
  • [[boundaries.forbidden]] for architecture contracts
  • [action] for how strongly agents/gates treat each pillar
  • [accept] for shared accepted findings
  • [self_improvement] for local metrics

Small example:

[duplication]
threshold = 50

[dead_code]
entrypoint_names = ["register", "main", "setup"]

[smells.rules.long_function]
max_lines = 80
action = "warning"

Project Anatomy

  • spine: file discovery, parsing, shared IR, and dependency graph.
  • profiles: language adapters for Python, JS/TS, TSX, and Rust.
  • noze: duplication, dead code, cycles, and design smells.
  • bonez: architecture boundary auditing. Not yet enabled.
  • brainz: local-only metrics and feedback memory.
  • eyez: optional doc/comment search. Not yet enabled.
  • mcp: JSON-RPC/MCP surface for agent integration.
  • reporter: terminal and JSON output.
  • setup: sensez init, starter config, MCP registration, and hook setup.

Privacy

Sensez does not send telemetry or source code anywhere. Local metrics stay under .sensez/local-metrics/.


Disclaimer: DISCLAIMER.md

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

sensez-0.1.12-py3-none-win_amd64.whl (2.8 MB view details)

Uploaded Python 3Windows x86-64

sensez-0.1.12-py3-none-manylinux_2_39_x86_64.whl (3.3 MB view details)

Uploaded Python 3manylinux: glibc 2.39+ x86-64

sensez-0.1.12-py3-none-manylinux_2_39_aarch64.whl (3.2 MB view details)

Uploaded Python 3manylinux: glibc 2.39+ ARM64

sensez-0.1.12-py3-none-macosx_11_0_arm64.whl (3.0 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

sensez-0.1.12-py3-none-macosx_10_12_x86_64.whl (3.1 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file sensez-0.1.12-py3-none-win_amd64.whl.

File metadata

  • Download URL: sensez-0.1.12-py3-none-win_amd64.whl
  • Upload date:
  • Size: 2.8 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sensez-0.1.12-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 c41f4d6a3d8a90dd2ee9cdde14f0aaf2cdf846bf35491d1050a016bff5138594
MD5 246ad2bb8a8069b9751031203eaede5b
BLAKE2b-256 53ecb91042a3e0684cc399a3a1965359d731de5c2f03e30bc836d067572ab051

See more details on using hashes here.

Provenance

The following attestation bundles were made for sensez-0.1.12-py3-none-win_amd64.whl:

Publisher: release.yml on popov95s/sensez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sensez-0.1.12-py3-none-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for sensez-0.1.12-py3-none-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 87e6d03c8c5af030b9cb93e9f6e9abefb4168021a6c7406f91220a8aba755d97
MD5 09fe667de0fbf47f667b2f4a7212657e
BLAKE2b-256 6e753f8faaa392a18630d82700efc1a97bcb4d6d6366b12bee480cb93aaa038b

See more details on using hashes here.

Provenance

The following attestation bundles were made for sensez-0.1.12-py3-none-manylinux_2_39_x86_64.whl:

Publisher: release.yml on popov95s/sensez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sensez-0.1.12-py3-none-manylinux_2_39_aarch64.whl.

File metadata

File hashes

Hashes for sensez-0.1.12-py3-none-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 217b78028848cb235c6d683b7465cdf3a380ca0d8a9be919a9e407bec2939a08
MD5 dd74a614e23d4646042a0d141c80c22b
BLAKE2b-256 2f1ca0d7e3ce53b38bb0ce396d67396209c9a3a739e8bd6c3224cc246df701d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for sensez-0.1.12-py3-none-manylinux_2_39_aarch64.whl:

Publisher: release.yml on popov95s/sensez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sensez-0.1.12-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sensez-0.1.12-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 07f9e517903565c1f3c95d85b9489889d6e8e8a2609c24e9eb5d8d4a2762d70a
MD5 837d9e84e460ae1757555309615db311
BLAKE2b-256 258ec354a4501fc543c569f5b19da6ce526ec3497fbf53698e97fbd83c954b39

See more details on using hashes here.

Provenance

The following attestation bundles were made for sensez-0.1.12-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on popov95s/sensez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sensez-0.1.12-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for sensez-0.1.12-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 ef1ecd5f379749eb65be5ba18c2d2f8779c13dda2e8ff3c9d86b5acb688aff16
MD5 98422b97c966c1e76b02db85f67cc842
BLAKE2b-256 6a13b5430b14785c077e1ec3681bef0703937843877598e0ca62d90232e9a970

See more details on using hashes here.

Provenance

The following attestation bundles were made for sensez-0.1.12-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on popov95s/sensez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.1

5 files

0.3.0

5 files

0.2.5

5 files

0.2.4

5 files

0.2.3

5 files

0.2.2

5 files

0.2.1

5 files

0.2.0

5 files

This release

0.1.12 This release

5 files

0.1.11

5 files

0.1.10

5 files

0.1.9

5 files

0.1.8

5 files

0.1.7

5 files

0.1.6

5 files

0.1.5

5 files

0.1.4

5 files

0.1.3

5 files

0.1.1

5 files

0.1.0

5 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page