developer tooling for coding agents

Bring your coding agent to its senses.

Agents drift, CI is too late, and existing static checks are too slow to run every turn. sensez is a small suite of CLIs that return structured signals — duplication, dead code, cycles, boundary violations, and design smells — in under a millisecond, so the agent can catch itself before the slop compounds.

Install sensez
$uv add --dev sensez
The problem

Coding agents drift because their feedback loop is leaky.

Three things compound on every agent-authored repo. sensez exists because fixing any one of them in isolation doesn't work.

01 · context rot

Instructions fade mid-task.

You tell it to respect boundaries, follow SOLID, and think like a staff engineer. A few turns and two context summaries later, it confidently rewrites the same CSV parser a colleague shipped two weeks ago.

follow the architectural boundary between modules…
follow the architectural boundary between modules…
follow the architectural boundary between modules…
follow the architectural boundary between modules…
follow the architectural boundary between modules…
turn n →
02 · CI is too late

Soft signals arrive where nobody acts.

CI is excellent at saying “absolutely not.” It is much worse at saying “this duplication is small, but suspicious.” You cannot block every PR over a few repeated lines, and non-blocking warnings have a natural habitat: ignored forever.

duplicate block ×3ignored
similar parser foundignored
nested branch smellignored
03 · too slow to be in-loop

Existing checks can't run every turn.

pylint's symilar took nearly four minutes on its own repository, and that's just duplicate detection. Nothing that takes minutes belongs inside an agent's edit loop.

symilar · pylint234.12s
repowise · pylint17.26s
sensez · pylint0.27s
what sensez does

A small suite of CLIs fast enough to run on every agent turn. Each one returns a short, structured signal — duplication, dead code, cycles, boundary violations, design smells — so the agent can react before the slop compounds, and before CI ever sees it.

actsenseadaptactsenseadaptµs loop · always on
Toolchain

A few small Rust CLIs.

Each tool is a single binary you can call from an agent loop, a git hook, or your terminal. The "senses" naming is just a mental model for what each one looks at.

noze
Code smells

Sniffs out duplication, dead code, import cycles, and design smells your linter and type checker don't own — in a compact format an agent can parse.

$ sense noze . → 3 smells · 412µs
bonez
Architecture

Audits the boundaries you declared in sensez.toml. If domain code starts importing the web layer, bonez says so before it ossifies.

$ sense bonez . → 1 forbidden import
brainz
Local memory

Local-only metrics: scans, gate blocks, triage decisions, resolved findings. No telemetry, no source upload — everything stays under .sensez/local-metrics/.

$ sense brainz report → 7 resolved · 2 accepted
eyez · optional

Doc and comment search for first-pass orientation — a lead finder, not a complete code search. Downloads an embedding model on first use, then stays local.

soon
Inside noze

What noze actually looks for.

A small, opinionated set of code smells — the ones agents trip on most often. Each one is tuned to be cheap enough to run on every turn.

tuple_packing

Tuple Packing

Agents love returning tuple[int, str, int]. To a human reader, positional tuples hide what each slot means — noze flags them so you can swap in a NamedTuple or dataclass.

loose_typing

Loose Typing

An agent will slap dict[str, Any] on a return type and call it a day. The contract becomes invisible to callers and type checkers. noze nudges you toward a tighter signature.

duplication

Duplication

Agents rarely check whether a helper already exists, and confidently re-implement it. noze cross-checks structural duplicates so you don't pay maintenance twice.

Why waste time write many code, when few code do trick?
Full smell catalogexpand
  • Boolean BlindnessBare booleans at the call site — use an enum or keyword args.
  • Data ClumpThe same group of values passed together everywhere — bundle them.
  • Deep NestingMany levels deep — flatten with early returns.
  • Divergent ChangeOne module edited for many reasons — split responsibilities.
  • Feature EnvyA method that uses another object's data more than its own.
  • God ModuleToo much of the codebase depends on it — a coupling hotspot.
  • Heavy Nested FunctionA nested function that grew large — promote it.
  • High Cognitive ComplexityHard to follow — branches and loops weighted by depth.
  • High Cyclomatic ComplexityMany independent paths — hard to test fully.
  • Implicit SchemaA dict accessed by many string keys — an unwritten schema.
  • Inappropriate IntimacyTwo classes reach into each other's internals.
  • Large ClassToo many methods and responsibilities — split it.
  • Literal MembershipBranching on `x in ['a','b']` — use an Enum.
  • Long FunctionToo many lines to grasp at once — extract pieces.
  • Long Parameter ListToo many parameters — group related ones.
  • Loose TypingPublic signature leans on `Any` or untyped — tighten it.
  • Magic NumbersUnexplained numeric literals — name them as constants.
  • Message ChainLong `a.b.c.d` chains — Law of Demeter.
  • Mutated ParameterFunction mutates a caller's argument in place.
  • Reassigned ParameterA parameter rebound mid-body — use a local.
  • Refused BequestSubclass inherits methods it doesn't use.
  • Shotgun Surgery HazardOne change ripples across many modules.
  • Split VariableOne local reassigned to mean different things.
  • Too Many ReturnsMany exit points — consolidate, or split the function.
  • Tuple PackingPositional tuples whose fields aren't named.
Install

Pick your package manager.

sensez ships as two language-native distributions: the Python package analyzes Python projects, and the JS/TS package analyzes JS/TS projects. Pick the one that matches your codebase.

Heads up: the PyPI and npm packages are still on their way to being published. No Cargo, Docker, or Homebrew distributions planned.

Use uv for one-off scans, or add it as a dev dependency.

$uvx --from sensez sense noze .
# run a one-off scan with uv
$uv add --dev sensez
# add as a dev dependency
$pip install sensez
# or install with pip
Performance snapshot

One structural pass. A fraction of the wait.

sensez scans the structural pillars together instead of paying for a chain of narrowly focused tools. Lower is faster; all values are measured wall-clock seconds from the generated benchmark runs.

repository scanlower is faster
Python

pylint repository

0–20s · capped
sensez0.27s
vulture1.29s
repowise17.26s
symilar234.12s
JavaScript / TypeScript

zod repository

0–5.75s
sensez0.16s
fallow0.48s
repowise5.75s

Python › sensez covers all structural pillars in 0.27s. Vulture focuses on dead code; repowise applies custom ranking that includes dead code.

Scale note › symilar checks line-based duplication and took 234.12s. Its bar is capped at 20s so the faster results remain readable.