popov95s/sensez

Help your coding agents come to their senses

16

stars

258

commits

Rust

primary language

Sep 10, 2026

updated

README

sensez

PyPI npm CI Website Documentation License: MIT

Coding agents produce tech debt. Bring them to their senses.

Coding agents forget the maintainability rules you give them. They hide logic in nested functions, reach for dict[str, Any] instead of a typed model, and pass around boolean flags whose meaning only exists in the agent’s current context.

Instructions help, but they’re soft constraints. Static analysis tools in your CI pipeline catch the problem too late and it starts rotting in a Jira ticket.

sensez adds fast, deterministic static feedback that agents can act on while they’re still working. It runs inside the coding-agent loop, giving agents fast, structured feedback on duplication, dead code, cycles, architecture violations, and design smells—so they fix problems before technical debt compounds.

In controlled evaluations, agents using Sensez produced 86% fewer code smells, 90% less duplicated code, and 67% fewer lines.

Website · Documentation · MCP and agent guide · Configuration reference

Quick start

Python

uv add --dev sensez      # or install globally: uv tool install sensez
uv run sensez init       # writes a starter config and registers the MCP server
uv run sensez noze .     # scan once — no install needed with: uvx sensez noze .

JavaScript and TypeScript

npm install --save-dev sensez
npx sensez init
npx sensez noze .

sensez init writes a commented starter sensez.toml and registers Sensez as an MCP server with your coding agent — Claude Code, Cursor, Cline, Codex, OpenCode, and Pi are supported. Restart the agent afterwards so the server is picked up. sensez . and sensez noze . both run the default scan.

A report is one screen, focused on what to fix first:

$ sensez noze .
sensez — structural maintainability report

Circular imports (1)
    [warning] ↻ shop.promo → shop.cart
        ./shop/promo.py:1  shop.promo → shop.cart
        ./shop/cart.py:1  shop.cart → shop.promo

Duplication (1)
    [advisory] structural clone (53):
      ./shop/clone_a.py:1-12
      ./shop/clone_b.py:1-12

Dead code candidates (2)
    [advisory] ./shop/legacy.py:1  shop.legacy::orphan_helper (function) [high]
    [advisory] ./shop/promo.py:10  shop.promo::recap (function) [high]

Code smells (0)

Boundary violations (not configured)

Why Sensez?

Coding agents are excellent at producing code—and, occasionally, at producing the same helper three times, gently ignoring architecture notes, and replacing type-safe models with dict[str, Any]. The vibes are immaculate; the result can still be a slopocalypse that takes hours to untangle.

Sensez closes that feedback loop while an edit is still fresh. It gives agents short, structured feedback on the repository's shape, so problems can be fixed before they become load-bearing.

The gap is especially visible in agent-driven work:

  • Context rots. Architecture guidance fades across long, summarized turns.
  • CI is too late. Small, non-blocking structural warnings are easy to defer.
  • Slow checks do not fit the turn. If a check takes minutes, it cannot run in every feedback loop—and debt has time to accumulate.
[Agent proposes turn finish] ──> [Sensez MCP sniff] ──> [Finds cycle / clone / smell]
                                      │
                                      └──> Immediate, actionable feedback

Sensez complements—not replaces—Ruff, ty, mypy, ESLint, TypeScript, rustc, and Clippy. Use those tools for local correctness; use Sensez for the structural relationships across the codebase.

What it finds

AreaOutput keyWhat it catches
DuplicationduplicationStructural clones, including local-rename copies.
Dead codedead_codeUnreferenced symbols with confidence tiers.
CyclescyclesImport loops and load-order tangles.
BoundariesboundariesImports that cross configured architecture rules.
SmellssmellsDesign pressure inside functions, classes, modules, and the graph.

Some examples of the included smells:

SmellWhy Sensez flags it
tuple_packingPositional tuples hide meaning; tuple[int, str, int] is not a data model.
loose_typingAny, schema-erasing maps, and primitive containers erase caller contracts.
boolean_blindnessdo_thing(True, False) makes argument meaning a guessing game.
implicit_schemaRepeated string-key access often means a real shape is hiding in a dict.
mutated_parameterA function returns a parameter after chewing it up.
feature_envyA method that mostly uses another object's data may belong elsewhere.
message_chainLong a.b.c.d chains couple callers to deep object plumbing.
god_moduleOne module has become the place everything depends on.
magic_string_default|| "" or or "" hides a string that should be required.
split_variableMultiple reassignments of a variable in one scope add hidden state.
nested_loopBeta, opt-in: nested iteration may have unintended complexity.
nested_ternaryNested conditional expressions make agent-generated decisions hard to follow.
n_plus_one_callBeta, opt-in: one-by-one external calls may need batching.

The default report is intentionally fixable in one screen: each pillar shows its top five offenders, each smell kind shows its total plus its top three examples, and dead-code output includes high-confidence findings only. Use --all for every finding, or --max N to set another cap.

# Focus a CI check on the pillars you care about
sensez noze . --duplicates
sensez noze . --duplicates --dead-code --json

Performance

Sensez evaluates all structural pillars in one pass.

Python: pylint benchmark

Python benchmark: Sensez 0.27 s, Vulture 1.29 s, Repowise 17.26 s, Symilar 234.12 s

ToolTimeScope
sensez0.27 sAll structural pillars in one pass
vulture1.29 sPython dead code
repowise17.26 sRepository intelligence, including dead code
symilar234.12 sLine-based duplication

JavaScript / TypeScript: zod benchmark

JavaScript and TypeScript benchmark: Sensez 0.16 s, Fallow 0.48 s, Repowise 5.75 s

ToolTimeScope
sensez0.16 sAll structural pillars in one pass
fallow0.48 sJS/TS structural dead-code and dependency findings
repowise5.75 sRepository intelligence, including dead code

Agent impact

The same coding agent completed 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 had to call noze_sniff in a feedback loop before it could declare a task complete.

New quality issuesClone tokensNew clonesLines writtenTokens used
Without Sensez141,2511292,0801.23M
With Sensez212606821.34M
Reduction86%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. See the evaluation suite for the methodology and per-benchmark results.

MCP for agents

MCP is the recommended integration when Sensez should run repeatedly during a coding session rather than as a one-off shell command. sensez init registers the server with your coding agent, which then launches it automatically at startup — there is nothing to run by hand.

ToolUse
noze_sniffScan the repository for smells and structural issues.
noze_gateExperimental end-of-turn diff gate; may be noisy for short or Q&A turns.
noze_explainExplain a finding category.
get_configuration_summarySummarize the effective configuration and noisiest rules when tuning.
brainz_reportSummarize local usage and resolution metrics.
brainz_triageRecord user-approved debt or false-positive verdicts.
eyez_search_docsDisabled unless eyez is enabled; searches docstrings and comments.

Sensez can also run standalone in GitHub Actions. See the GitHub Action guide.

Configuration

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

sensez init

The main configuration areas are:

  • [duplication] for clone thresholds
  • [dead_code] for dynamic entry points
  • [cycles] for cycle-only path excludes
  • [smells] for smell toggles and thresholds
  • [[boundaries.forbidden]] for architecture contracts
  • [action] for how strongly agents and gates treat each pillar
  • [accept] for shared accepted findings
  • [self_improvement] for local metrics
  • [cache] enables MCP/LSP process-memory reuse; CLI scans always stay stateless
[duplication]
threshold = 50

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

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

# The beta performance heuristics are disabled by default.
[smells.rules.nested_loop]
enabled = true

[smells.rules.n_plus_one_call]
enabled = true

Smell rules can also be overridden per language, and every finding carries an action level (infomust_fix) that drives gates and CI. See the Configuration reference for action levels, per-language overrides, boundary patterns, and accepting findings.

Local-only metrics and privacy

brainz records scans, gate blocks, triage decisions, resolved findings, regressions, detector precision, and usage reports locally.

sensez brainz report .
sensez brainz report . --json

Everything remains under .sensez/local-metrics/. Sensez sends no telemetry and uploads no source code. Disable local metrics for a repository with:

[self_improvement]
enabled = false

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.
  • 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: starter configuration, MCP registration, and hook setup.

Disclaimer

Please review DISCLAIMER.md for the project disclaimer.

Contributors

popov95s

255 commits

popov95s/sensez

Help your coding agents come to their senses

16

stars

258

commits

Rust

primary language

Sep 10, 2026

updated

README

sensez

PyPI npm CI Website Documentation License: MIT

Coding agents produce tech debt. Bring them to their senses.

Coding agents forget the maintainability rules you give them. They hide logic in nested functions, reach for dict[str, Any] instead of a typed model, and pass around boolean flags whose meaning only exists in the agent’s current context.

Instructions help, but they’re soft constraints. Static analysis tools in your CI pipeline catch the problem too late and it starts rotting in a Jira ticket.

sensez adds fast, deterministic static feedback that agents can act on while they’re still working. It runs inside the coding-agent loop, giving agents fast, structured feedback on duplication, dead code, cycles, architecture violations, and design smells—so they fix problems before technical debt compounds.

In controlled evaluations, agents using Sensez produced 86% fewer code smells, 90% less duplicated code, and 67% fewer lines.

Website · Documentation · MCP and agent guide · Configuration reference

Quick start

Python

uv add --dev sensez      # or install globally: uv tool install sensez
uv run sensez init       # writes a starter config and registers the MCP server
uv run sensez noze .     # scan once — no install needed with: uvx sensez noze .

JavaScript and TypeScript

npm install --save-dev sensez
npx sensez init
npx sensez noze .

sensez init writes a commented starter sensez.toml and registers Sensez as an MCP server with your coding agent — Claude Code, Cursor, Cline, Codex, OpenCode, and Pi are supported. Restart the agent afterwards so the server is picked up. sensez . and sensez noze . both run the default scan.

A report is one screen, focused on what to fix first:

$ sensez noze .
sensez — structural maintainability report

Circular imports (1)
    [warning] ↻ shop.promo → shop.cart
        ./shop/promo.py:1  shop.promo → shop.cart
        ./shop/cart.py:1  shop.cart → shop.promo

Duplication (1)
    [advisory] structural clone (53):
      ./shop/clone_a.py:1-12
      ./shop/clone_b.py:1-12

Dead code candidates (2)
    [advisory] ./shop/legacy.py:1  shop.legacy::orphan_helper (function) [high]
    [advisory] ./shop/promo.py:10  shop.promo::recap (function) [high]

Code smells (0)

Boundary violations (not configured)

Why Sensez?

Coding agents are excellent at producing code—and, occasionally, at producing the same helper three times, gently ignoring architecture notes, and replacing type-safe models with dict[str, Any]. The vibes are immaculate; the result can still be a slopocalypse that takes hours to untangle.

Sensez closes that feedback loop while an edit is still fresh. It gives agents short, structured feedback on the repository's shape, so problems can be fixed before they become load-bearing.

The gap is especially visible in agent-driven work:

  • Context rots. Architecture guidance fades across long, summarized turns.
  • CI is too late. Small, non-blocking structural warnings are easy to defer.
  • Slow checks do not fit the turn. If a check takes minutes, it cannot run in every feedback loop—and debt has time to accumulate.
[Agent proposes turn finish] ──> [Sensez MCP sniff] ──> [Finds cycle / clone / smell]
                                      │
                                      └──> Immediate, actionable feedback

Sensez complements—not replaces—Ruff, ty, mypy, ESLint, TypeScript, rustc, and Clippy. Use those tools for local correctness; use Sensez for the structural relationships across the codebase.

What it finds

AreaOutput keyWhat it catches
DuplicationduplicationStructural clones, including local-rename copies.
Dead codedead_codeUnreferenced symbols with confidence tiers.
CyclescyclesImport loops and load-order tangles.
BoundariesboundariesImports that cross configured architecture rules.
SmellssmellsDesign pressure inside functions, classes, modules, and the graph.

Some examples of the included smells:

SmellWhy Sensez flags it
tuple_packingPositional tuples hide meaning; tuple[int, str, int] is not a data model.
loose_typingAny, schema-erasing maps, and primitive containers erase caller contracts.
boolean_blindnessdo_thing(True, False) makes argument meaning a guessing game.
implicit_schemaRepeated string-key access often means a real shape is hiding in a dict.
mutated_parameterA function returns a parameter after chewing it up.
feature_envyA method that mostly uses another object's data may belong elsewhere.
message_chainLong a.b.c.d chains couple callers to deep object plumbing.
god_moduleOne module has become the place everything depends on.
magic_string_default|| "" or or "" hides a string that should be required.
split_variableMultiple reassignments of a variable in one scope add hidden state.
nested_loopBeta, opt-in: nested iteration may have unintended complexity.
nested_ternaryNested conditional expressions make agent-generated decisions hard to follow.
n_plus_one_callBeta, opt-in: one-by-one external calls may need batching.

The default report is intentionally fixable in one screen: each pillar shows its top five offenders, each smell kind shows its total plus its top three examples, and dead-code output includes high-confidence findings only. Use --all for every finding, or --max N to set another cap.

# Focus a CI check on the pillars you care about
sensez noze . --duplicates
sensez noze . --duplicates --dead-code --json

Performance

Sensez evaluates all structural pillars in one pass.

Python: pylint benchmark

Python benchmark: Sensez 0.27 s, Vulture 1.29 s, Repowise 17.26 s, Symilar 234.12 s

ToolTimeScope
sensez0.27 sAll structural pillars in one pass
vulture1.29 sPython dead code
repowise17.26 sRepository intelligence, including dead code
symilar234.12 sLine-based duplication

JavaScript / TypeScript: zod benchmark

JavaScript and TypeScript benchmark: Sensez 0.16 s, Fallow 0.48 s, Repowise 5.75 s

ToolTimeScope
sensez0.16 sAll structural pillars in one pass
fallow0.48 sJS/TS structural dead-code and dependency findings
repowise5.75 sRepository intelligence, including dead code

Agent impact

The same coding agent completed 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 had to call noze_sniff in a feedback loop before it could declare a task complete.

New quality issuesClone tokensNew clonesLines writtenTokens used
Without Sensez141,2511292,0801.23M
With Sensez212606821.34M
Reduction86%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. See the evaluation suite for the methodology and per-benchmark results.

MCP for agents

MCP is the recommended integration when Sensez should run repeatedly during a coding session rather than as a one-off shell command. sensez init registers the server with your coding agent, which then launches it automatically at startup — there is nothing to run by hand.

ToolUse
noze_sniffScan the repository for smells and structural issues.
noze_gateExperimental end-of-turn diff gate; may be noisy for short or Q&A turns.
noze_explainExplain a finding category.
get_configuration_summarySummarize the effective configuration and noisiest rules when tuning.
brainz_reportSummarize local usage and resolution metrics.
brainz_triageRecord user-approved debt or false-positive verdicts.
eyez_search_docsDisabled unless eyez is enabled; searches docstrings and comments.

Sensez can also run standalone in GitHub Actions. See the GitHub Action guide.

Configuration

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

sensez init

The main configuration areas are:

  • [duplication] for clone thresholds
  • [dead_code] for dynamic entry points
  • [cycles] for cycle-only path excludes
  • [smells] for smell toggles and thresholds
  • [[boundaries.forbidden]] for architecture contracts
  • [action] for how strongly agents and gates treat each pillar
  • [accept] for shared accepted findings
  • [self_improvement] for local metrics
  • [cache] enables MCP/LSP process-memory reuse; CLI scans always stay stateless
[duplication]
threshold = 50

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

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

# The beta performance heuristics are disabled by default.
[smells.rules.nested_loop]
enabled = true

[smells.rules.n_plus_one_call]
enabled = true

Smell rules can also be overridden per language, and every finding carries an action level (infomust_fix) that drives gates and CI. See the Configuration reference for action levels, per-language overrides, boundary patterns, and accepting findings.

Local-only metrics and privacy

brainz records scans, gate blocks, triage decisions, resolved findings, regressions, detector precision, and usage reports locally.

sensez brainz report .
sensez brainz report . --json

Everything remains under .sensez/local-metrics/. Sensez sends no telemetry and uploads no source code. Disable local metrics for a repository with:

[self_improvement]
enabled = false

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.
  • 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: starter configuration, MCP registration, and hook setup.

Disclaimer

Please review DISCLAIMER.md for the project disclaimer.

Contributors

popov95s

255 commits

Languages

Rust

82.7%

Python

14.0%

Shell

1.9%