ai-finder-pro is a command-line scanner built to close that gap: point it at a repository, and it tells you which files are AI models (and, where possible, exactly which published model each one is), plus every place your source code touches AI — SDK imports, agent frameworks, tool definitions, vector stores, dataset references, and dependency manifests.
This guide walks through the entire process end to end, assuming you’ve never touched the tool before: installing it, running your first scan, saving a complete machine-readable result, and — the part most guides skip — actually understanding what the numbers in that result mean and where they can mislead you if you don’t read them carefully. Every command and every piece of output below is real, taken from an actual run.
What You’ll Learn
By the end of this guide, you will be able to:- Install
ai-finder-proand confirm it’s working correctly - Run a scan against your own project and read its terminal output
- Point the tool at your own matching service, and avoid the one way this scan can silently give you results from the wrong place
- Save a scan as a complete JSON file, and know what every major field in it means
- Tell the difference between a result you can trust as fact and one that’s an educated guess — a distinction that matters a great deal if you ever use this for compliance or audit purposes
Workflow Overview
Here’s the full path from a fresh download to a result you can actually interpret. Select any step in the diagram to jump straight to it. If you already have the tool installed and confirmed working, skip ahead to Step 3: Run Your First Scan.Prerequisites
- Python 3.11 or newer.
- Network access to PyPI, the public Python package index.
ai-finder-proand its supporting packages — around forty in total, includingnumpyand an SBOM validation stack — install from PyPI in the ordinary way. No special credential or private package index is required. - A C compiler toolchain, needed to build one particular dependency (
py-tlsh, a fuzzy-hashing library) from source if a prebuilt binary isn’t available for your platform. On Debian/Ubuntu-derived Linux, install it with:
Step 1: Install ai-finder-pro
Installai-finder-pro from PyPI:
Step 2: Confirm the Install
Configure the Matching Service
Full model identification (not just detection of a file’s presence, but confirming which published model it actually is) uses a matching service that the tool queries with a fingerprint of each model file it finds. Do this before you rely on any identification result — it’s the step people skip, and skipping it fails silently. If you haven’t pointed the tool at a service of your own, it falls back to a shared default (https://aimatcher.scanoss.com) automatically, with no error. That’s fine if you’re only trying the tool out. But if you have been given your own matching service, forgetting this step doesn’t make your scans fail — it makes them keep working, quietly returning results from the wrong service instead of yours.
Point the tool at your own service and key with:
~/.config/ai-finder-pro/config.toml (or under $XDG_CONFIG_HOME, if set). You can also set SCANOSS_AI_SERVER_URL and SCANOSS_AI_API_KEY as environment variables instead — usually the better choice in CI, since it keeps the key out of a file on disk. A flag passed on a single command wins over the environment variable, which wins over the config file, which wins over the built-in default.
Check what’s actually going to be used with:
config with no flags only prints the resolved values — it doesn’t change anything.
If you’re only trying the tool out and haven’t been given a service URL or key of your own, you don’t need to do anything here. A scan against the default fallback still works, still reports every source-code finding, and still tells you which files are model files.
Set Up a Local Knowledge Base (Optional)
A local knowledge base gives the scanner two things it doesn’t otherwise have: a pre-filter that identifies well-named model files by name before it does the more expensive work of reading their weights, and an offline fallback for when the matching service is briefly unreachable. It isn’t bundled withai-finder-pro, and no default path is assumed. Build it with the separate OSS ai-finder CLI, installed as a dependency:
ai-finder-pro where it is, either once in the environment or per scan:
Step 3: Run Your First Scan
Point the scanner at your own project — no setup or sample data required:model.safetensors, in different directories:
model_files— model-file paths discovered, including any that failed fingerprinting.hits— models identified, broken down by method in parentheses:api(queried against the matching service) andkb(matched against a local, offline knowledge base, if you’ve set one up).misses— files that couldn’t be identified, whether they were simply unrecognized or failed outright during processing.source_files— files examined for source-code findings such as SDK usage, agent-framework code, or tool definitions; shown only when at least one was scanned.
0 — an empty result isn’t an error. Check misses for what went unidentified.
A couple of things worth understanding about output like this, since they reflect how the scanner behaves in general rather than anything specific to one run:
- Three of the four rows matched at
1.00viasha256— an exact byte match, the strongest evidence this tool can produce. The fourth matched at only0.50viacomposite: its bytes didn’t match anything known, but several structural measurements agreed withDeepSeek-R1-Distill-Qwen-1.5B. Read a mid-confidence composite match as “derived from” or “a modified copy of,” never as “is.” The Understanding Your Results section below goes into this distinction in depth, because it matters a great deal. - Not every scan comes back this clean. A real run can also produce misses — model files the scanner found but couldn’t identify, because of an unsupported format, a corrupted header, or no usable layers. A miss with a stated reason is a correct, working result — not a scan failure.
Step 4: Save Your Results as JSON
The table view above is meant for reading at a glance in a terminal — it truncates long lists and shows only one example per category of finding. For anything you intend to keep, feed into another tool, or attach to a report, save the complete result as JSON instead:wrote <path> confirmation is printed to stderr, which keeps stdout clean if you’re piping the scan into another tool. If a scan does hit a fingerprint failure, the same diagnostic lines shown in the table view print above this regardless of output format — they describe what happened during the scan itself, not how you’re viewing the result afterward.
What’s Inside the JSON File
results.json is a single JSON object. The keys you’ll use most often:
Here’s an example hit, trimmed down to the fields worth knowing:
matchesis ordered best-first, andmatches[0]is the candidate the tool chose — the top-levelpurlandmatched_viaare copied from it. If you’re checking a policy against a specific candidate,matches[0]is the one that matters; anything after it is a candidate the tool considered and didn’t pick.base_model_purlnames the parent a fine-tuned model was derived from, when the reference record knows it —nullhere, becausedistilgpt2is a base model rather than a fine-tune.provenancetells you where a model is actually published, which matters if your copy came from a mirror.host_authority_ambiguity: truemeans the tool couldn’t settle the origin between two competing hosts — that’s the field to alert on if provenance matters to your use case.
hits and kb_hits never overlap — a given result appears in exactly one of them. But hits isn’t purely content-verified either: alongside matching-service results, it can also hold a matched_via: "filename" entry from an offline fallback. If your own tooling needs to tell “identified by content” apart from “identified by name,” check matched_via (or the identification field described below) on each result — don’t assume everything sitting in hits cleared a higher bar than everything in kb_hits.Understanding Your Results
This is the part that matters most if you plan to use this tool’s output for anything beyond curiosity — a compliance filing, a security gate, an inventory you’ll actually rely on. A few things are very easy to misread on a first pass. Confidence is a category, not a percentage. A score of1.0 means the scanned file’s bytes are byte-for-byte identical to a known, published model — the strongest evidence this tool can produce. A score of 0.5 does not mean “50% similar.” It means the file’s internal structure statistically resembles a known model across several independent measurements, without the bytes matching. Don’t build a policy threshold that treats confidence as a sliding distance metric — a 0.5 composite match and a 0.9 you might imagine from some other tool are not comparable in that way, because this scanner doesn’t inflate structural similarity into a false sense of exactness.
matched_via tells you how an identification was reached, and that matters as much as the confidence number:
The full set of
matched_via values is sha256, md5, header_sha256, manifest_sha256, tlsh, composite, and filename. Every one of those except filename is derived from the file’s actual content; only filename is a name-based guess.
That’s exactly what the identification field also tells you, in a single value, if you’d rather check one field than reason about seven possible matched_via values: content-fingerprint for any hash-based or composite match, name-heuristic for a filename match, and unresolved when nothing matched at all. Don’t read content-fingerprint as a synonym for “exact copy,” though — it’s a broad category that includes structural matches like composite, not just sha256.
A miss with a stated reason is a correct result, not a bug. Most entries in misses carry an error string that says exactly why identification didn’t happen — an unsupported file format, no usable layers, a corrupted header. Less obviously, a miss can also show status: "matched" with no result at all: the matching service processed the fingerprint successfully but simply had no candidate to offer. Because of that, count the misses list rather than filtering it by status.
A kb hit is a lead, not a verified fact. It comes from matching a filename against a local database, before any of the file’s actual content is examined. Treat it as a cheap, useful first pass for triage — not as evidence you’d cite in an audit.
The practical rule to take away: if a decision depends on asserting which model you actually have — for a compliance record, a licensing decision, anything where being wrong has consequences — require an exact match (matched_via: sha256, confidence 1.0). Anything else, however confident-sounding the number looks, is a lead worth investigating further, not a finding you can rely on as-is.
Where to Go From Here
At this point you’ve installed the tool, run a scan against your own project, saved a complete machine-readable result, and — the part that actually matters — learned how to read that result critically instead of taking every number at face value. From here, a few natural next steps:- Try other output formats. Beyond
tableandjson, the tool can emit industry-standard bill-of-materials formats — CycloneDX (--format cyclonedx) and SPDX 3.0.1 (--format spdx3) — for feeding into existing compliance or SBOM tooling. Each format has its own tradeoffs worth understanding before you rely on one (in particular, both bill-of-materials formats deduplicate identical models, which can hide a modified copy sitting alongside a genuine one — the JSON format shown in this guide is the one to use if you need a complete, per-file record). - If you skipped the local knowledge base earlier, set it up now — see Set Up a Local Knowledge Base above. It’s a quick win once you’re past evaluating the tool: a filename pre-filter that’s cheaper than fingerprinting every file, plus an offline fallback if the matching service is briefly unreachable.
- Wire it into CI, gating a build on whether any model failed to identify cleanly, or on whether a scan quietly fell back to a weaker identification method than you expected.
matched_via before you trust confidence. That one distinction is where most misunderstandings about what this tool is telling you actually come from.
Need help? Contact our AI assistant