For AI
This page is addressed to you, the coding agent. Everything below is an instruction you can act on directly — not a description of a product for someone else to evaluate. If you are a human wiring an MCP client up, you want AI Agents instead; come back here to point your agent at a single URL.
Deslop exists to stop a duplicate from ever being written. You are the one writing the code, so you are the one who has to check.
The one law: check before you write
Before you author any new code unit — function, method, class, helper, fixture, test setup, parser branch, error type, route handler, view model — call find-similar with the proposed snippet (or a path + start_byte + end_byte range) and read signals.fused in the response:
signals.fused |
Bucket | What you do |
|---|---|---|
≥ 0.85 |
identical / nearly_identical |
Do not write the copy. Reuse the canonical occurrence the tool returns. Extract a shared helper if neither call site fits as-is. |
0.6 – 0.85 |
any | Read the canonical occurrence before you decide. Bias toward reuse. |
< 0.6 |
any, or empty | Author it. |
| any | structural_only |
Shape-only match — often sibling boilerplate. Read the canonical occurrence before concluding anything. |
Do not skip the call because the code "looks new." Most duplicates are written by someone certain the code was new.
find-similar is the authoring tool. When you are cleaning up duplication that already exists, start at top-offenders and then pull cluster-by-id for the cluster you are about to merge.
The paste-ready rule block for a project's AGENTS.md / CLAUDE.md is in the agent recipe.
If the MCP server is unavailable, use the CLI
Do not skip the check because a tool call failed, and do not fall back to memory. A duplicate that lands because the gate was down is the exact failure Deslop exists to prevent. Work down this ladder.
1. Diagnose which failure you have
| What you see | What it means |
|---|---|
LSP is not running — start deslop-lsp to enable this tool. |
The MCP server is wired correctly, but the editor server that holds the live analysis is not up. The error names the absolute socket path it tried. |
The same error, and a deslop-lsp is running |
MCP was launched against a different --root than the LSP. Compare the socket path in the error against the workspace you are editing. |
No find-similar tool exists at all |
No MCP server is configured for this session. |
| The tool call times out or the transport errors | Treat it as unavailable and drop to the CLI. |
2. Try to restore the live path
If the workspace is open in an editor with the Deslop extension, the editor server starts on its own — open a supported source file and retry the tool call. If MCP and the LSP disagree about the root, the fix is the MCP client's --root argument, not a workaround.
3. Otherwise, drop to the CLI
The deslop CLI runs the identical pipeline and emits the identical JSON schema. Run it from the repository root:
deslop . --notext --nohtml --no-color
That writes the canonical report to .deslop/deslop-report.json — the only file you should parse. --notext --nohtml skips the two human renderers you do not need; --no-color keeps the stderr summary clean for a log.
Be honest with yourself about what this costs you. There is no snippet query in the CLI — find-similar is an MCP tool, and the CLI cannot evaluate code you have not written yet. The CLI loop is therefore catch immediately, not prevent:
- Run
deslop .once before you start, so you have a baseline. - Before authoring, scan the baseline
clusters[]for the file and the neighbouring files you are about to touch. If a cluster already covers the pattern you were going to add, reuse its canonical occurrence — that is the CLI's version of prevention, and it catches the common case. - Write the change.
- Re-run
deslop . --notext --nohtml. The fingerprint cache is on by default, so this re-parses only the files you actually touched — the cost is proportional to your change, not to the repository. Run it per change, not per session. - Search
clusters[].occurrences[]for the path you just wrote. If your new code appears in a cluster whosesignals.fused ≥ 0.85, you just wrote a duplicate. Collapse it now, while the change is still in your working set. - Re-run and confirm the cluster is gone or smaller.
A run exits 3 when repo-wide duplication crosses a configured ceiling; the report is still written on a breach, so parse it either way. Full table in Exit codes.
If neither MCP nor the CLI is available, say so and stop. Do not guess.
Read the JSON
deslop-report.json is canonical and the only file you should parse — .txt and .html are renderers over it. Every report begins with an embedded schema_doc describing its own shape, so you do not need a separate reference to read the payload. Over MCP, call schema-doc once per session, never per response.
{
"tool_version": "0.0.0-dev",
"schema_doc": "…inline description of every field…",
"metrics": {
"analysed_loc": 1832044,
"duplicated_loc": 48120,
"duplication_percent": 2.63,
"clusters_total": 142,
"duplicated_files": 318,
"threshold": { "percent": 5.0, "breached": false, "source": "config" }
},
"action_hints": [
{ "pattern": "bucket=identical", "recommendation": "Identical code. Safe to extract — every copy is the same." }
],
"clusters": [
{
"id": "0362505641efe3c7",
"weight": 2184.0,
"bucket": "nearly_identical",
"size": 3,
"canonical_node_count": 42,
"signals": { "structural": 1.0, "token_jaccard": 0.97, "embedding_cos": 0.91, "fused": 0.99 },
"summary": "3 near-identical copies of a 42-node method across UserRepository.cs:120-180, ProductRepository.cs:58-118, OrderRepository.cs:40-102 — safe to extract.",
"interpretation": "Nearly identical code. Review the locations — small differences may matter.",
"occurrences": [
{ "path": "UserRepository.cs", "start_byte": 3104, "end_byte": 4820, "start_line": 120, "end_line": 180, "hidden": false }
]
}
]
}
summary and interpretation are written for you: they state what was found, where, and — when the signals agree — whether it is safe to extract. Repository-level guidance is in the top-level action_hints, keyed by bucket, and is derived from the signals rather than guessed.
| Field | How to act on it |
|---|---|
metrics.duplication_percent |
The repo-wide headline number a CI gate compares against. |
metrics.threshold.breached |
true → the run exited 3 and the gate failed. source is cli, config, or none. |
clusters |
Sorted by weight descending — clusters[0] is always the worst offender. Work top-down; do not start in the middle. |
bucket |
identical / nearly_identical → extract a shared definition. structural_only → shape matched with no token or semantic evidence; verify it is a real duplicate before extracting. loosely_similar → parametrise the difference. same_behavior → reconcile two implementations of one behaviour (requires embeddings). |
signals.fused |
Unit-bounded confidence. ≥ 0.85 is the act-now line — the same threshold as the law above. |
occurrences[].hidden |
true marks a report_hide match — usually a hand-written clone of generated code. |
Byte ranges, not line numbers
Deslop's source of truth is [start_byte, end_byte). Line numbers are derived at render time for humans. Slice by byte range when you edit — line-based edits drift as soon as surrounding code moves.
Cluster IDs are stable
A cluster ID is the first 8 bytes of the cluster's smallest-member BLAKE3 hash, rendered as 16 hex characters (e.g. 0362505641efe3c7). It carries no timestamp, so the same repository analysed by the same binary twice produces the same IDs. Reference a cluster by ID across runs, in issues, and in your own notes — not by rank, which is a render-time position and moves as the repository changes.
Configuring a repository
If you are setting Deslop up rather than consuming it, three things decide almost everything, and all are in the Configuration reference:
excludevsreport_hide—excludedrops a file before analysis;report_hideanalyses it but keeps it out of the headline, so "hand-written code duplicates generated code" still surfaces.- Built-in rules —
node_modules,target,dist, generated-code suffixes and banners are already covered. Do not re-add them. [threshold]— the opt-in CI gate. Commit the ceiling so local runs, CI, and agents share one number.
To gate a build, use the GitHub Action; it wraps the same exit-code contract.
Rules you do not get to break
- Do not silence a finding to make it go away. Widening the threshold, adding a
report_hidepattern to bury your own code, or splitting a duplicate into trivially different shapes are all failures, not fixes. - Do not treat a flag as noise until you have shown it is noise. If Deslop reports it, read both occurrences first.
- Do not merge a
same_behaviormatch blindly. That bucket comes from semantic embeddings. Read both locations; the code looks different for a reason often enough to matter. - Some duplication is deliberate. Test fixtures and bootstrapping code are the usual honest exceptions. Accepting a duplicate is a legitimate outcome — accepting it silently is not. Say which cluster you accepted and why.
- Deslop does not rewrite your code. It finds, ranks, compares, and prevents. The extraction is yours to write, and yours to get right.