Skip to content
Fallow home
All docs pages

Semantic similar code

Find JavaScript and TypeScript functions that may do the same job under different names and syntax, so you can review them for consolidation. Uses a pinned local model, and a person or agent decides.

fallow similar-code finds functions that may do the same kind of work, even when their code looks different. Use the results to find logic that you can possibly consolidate and that fallow dupes does not find.

fallow dupes finds exact, normalized, and near-miss copies. Similar-code discovery compares the meaning of complete functions. Run it after fallow dupes.

Every result is an unverified candidate. A similarity score is not a probability. It does not prove that the behavior matches, and it does not mean that a refactor is safe. Inspect both functions and their tests before you decide.

Set up the local model

The main fallow npm package installs the matching native companion. To check whether its pinned model is ready, run:

fallow similar-code status

The first download needs your explicit confirmation:

fallow similar-code setup --local

Before it asks, setup shows the model, the license, and the download size. Use --yes only when you already approved the download and need a command without a prompt. Project config and agents cannot approve setup for you.

After setup, the analysis runs offline and function source stays on your machine. The companion receives size-limited source over local process input and does not save it. Fallow stores derived vectors in a user-local cache with a separate namespace for each project, so later runs are faster.

Find candidates

fallow similar-code

The JSON output has its own top-level format:

fallow similar-code --format json --quiet > similar-code.json

A candidate looks like this:

{
  "candidate_id": "similar-code:candidate:v1:...",
  "review_key": "similar-code:review:v1:...",
  "left": {
    "path": "src/orders/normalize.ts",
    "name": "normalizeOrder",
    "start_line": 12,
    "end_line": 34,
    "source_sha256": "..."
  },
  "right": {
    "path": "src/imports/clean.ts",
    "name": "cleanImportedOrder",
    "start_line": 8,
    "end_line": 31,
    "source_sha256": "..."
  },
  "similarity": 0.91,
  "similarity_band": "high",
  "verification_status": "unverified"
}

The score has meaning only for the pinned model and the current settings. Use it to rank review work. Do not use it to compare projects or to set a general quality bar.

The top level of the output also records:

  • The exact companion, model revision, artifact digest, and parameters.
  • Whether every analysis phase completed.
  • Limits and skipped work.
  • Vector-cache hits and misses.
  • Diagnostics without a severity.

An empty candidate list proves that there are no candidates only when completion.status is "complete". A "partial" run tells you which limit or provider problem made the result incomplete.

fallow similar-code --file src/orders/normalize.ts
fallow similar-code --changed-since main
fallow similar-code --workspace @acme/orders
fallow similar-code --threshold 0.88 --min-lines 6 --top 20

--file keeps only the pairs that include the selected file. --changed-since and the workspace options scope the project in the same way as other fallow analyses.

Inspect before judging

Copy the candidate_id from the discovery output. Pass the saved discovery JSON with --candidates:

fallow similar-code inspect similar-code:candidate:v1:... \
  --candidates similar-code.json --format json --quiet

Run this command from the same project root. Inspect reads the candidate from the discovery JSON, so you do not repeat the discovery options. The human discovery output prints this inspect command for each candidate. MCP callers pass the candidate_id and the candidate snapshot from the find_similar_code response to inspect_similar_code.

Inspect first reproduces the candidate against your current source. If either function changed since discovery, you do not review a stale result. Inspect then adds size-limited evidence, where it is available:

  • Source windows for both functions.
  • Import-graph relationship and entry-point reachability.
  • Callers and callees.
  • CODEOWNERS ownership and recent churn.
  • Related tests.
  • Overlap with deterministic duplication results.
  • Syntax clues such as async behavior, throws, awaits, and possible side effects.

Every evidence source has an availability state. Fallow reports missing context as missing. It does not treat absent evidence as a positive verdict.

Record a separate verdict

Fallow never changes the raw candidate document. After a person or agent inspects the code, they write a separate verdict:

{
  "schema_version": "1",
  "verdicts": [
    {
      "candidate_id": "similar-code:candidate:v1:...",
      "review_key": "similar-code:review:v1:...",
      "candidate_worthy": true,
      "behaviorally_equivalent": false,
      "refactor_safe": false,
      "outcome": "related-but-distinct",
      "rationale": "Both normalize orders, but only the import path preserves external IDs."
    }
  ]
}

To join the two documents, run:

fallow similar-code review \
  --candidates similar-code.json \
  --verdicts verdicts.json \
  --require-verdict-for-each-candidate \
  --format json --quiet

Review matches a verdict to a candidate by candidate_id first. A verdict with an unknown candidate_id matches by its review_key. The review_key hashes only the two function sources. When a function is copied verbatim into two files, two candidates can therefore share one review_key. The rules are:

  • Verdicts that match by candidate_id can repeat a review_key. Write one verdict for each candidate to pass --require-verdict-for-each-candidate.
  • A review_key must be unique only among the verdicts that match by review_key.
  • Review does not apply a review_key verdict that matches more than one candidate.
  • A duplicate candidate_id, or a review_key that does not match its candidate_id, fails the review.

Each of the three judgments is yes, no, or unknown, and each answers a different question:

FieldQuestion
candidate_worthyIs this pair useful enough to review?
behaviorally_equivalentDo both functions behave the same for relevant inputs and side effects?
refactor_safeIs consolidation safe in the current architecture?

Use null when you cannot answer. refactor_safe: true requires behaviorally_equivalent: true, and behaviorally_equivalent: true requires candidate_worthy: true.

The available outcomes are same-responsibility, related-but-distinct, intentional-duplication, unrelated, and needs-human-review.

Use it with an agent

The MCP server has two read-only tools:

  • find_similar_code returns unverified candidates, with provenance and completion status.
  • inspect_similar_code reproduces one candidate and returns its evidence packet.

Neither tool downloads a model, edits source, or produces a verdict. If setup is missing, the agent should ask you to run fallow similar-code setup --local. When tests, callers, behavior, or side effects are unclear, the agent should return needs-human-review.

Configure project defaults

{
  "similarCode": {
    "threshold": 0.8,
    "minLines": 3,
    "ignore": ["src/generated/**"]
  }
}

These fields change only candidate discovery. Config cannot choose a model, provider, executable, download, or credential.

To clear the derived project vectors and keep the downloaded model, run:

fallow similar-code cache clear --yes

Where it does not run

Similar-code discovery does not run in bare fallow, audit, dupes, CI gates, SARIF, LSP, VS Code diagnostics, or auto-fix. It is a review aid and does not add a finding category. It accepts only the official pinned local model and never sends source to a remote provider.

See also