Reference

Every command, option, status and file format in Remixware 0.2. The README that ships with the program covers the same ground.

Commands

remixware index <folder>... [--out FILE]      fingerprint third-party code into an index
remixware scan [project] --index FILE         compare a project with indexes, list the matches
remixware check [project] --index FILE        the same, as a pass/fail gate for CI
remixware notice [project] --index FILE       write third-party notices for what you copied
remixware licenses                            list the licences Remixware knows
remixware version

scan, check and notice compare the project with --index files, with --from results files, with the SCANOSS service (--scanoss), or with any mix of them. The project defaults to the current folder. Flags can come before or after it, and remixware help <command> lists a command’s flags.

index

Option What it does
--out FILE The index file to write. Default remixware.rmx
--name NAME Component name for the folder, when you index one folder
--version V Component version for the folder, when you index one folder
--license EXPR Licence of the components, as an SPDX expression, instead of what Remixware finds. A file’s own header or SPDX tag still adds to it
--exclude PATTERN Leave out paths that match. Repeatable
--max-common N Drop fingerprints found in more than N components. 0 picks a value, -1 keeps all
--quiet Print nothing but errors

Components are found by go.mod, package.json, Cargo.toml, composer.json, pyproject.toml and .dist-info folders, and by folders with a licence file. A component’s licence comes from its manifest, its licence files and a REUSE LICENSES/ folder. A folder with no licence of its own takes the licence of the folder above it, except across node_modules, vendor, third_party and similar folders.

  • Several licence files all apply, except files that each name one licence, such as LICENSE-MIT and LICENSE-APACHE, or a short file saying the project is dual licensed: those are a choice, as in Apache-2.0 OR MIT.
  • A crate with license.workspace = true takes its workspace’s licence when the workspace is inside the indexed folder, and Python distributions that share a folder are told apart by their RECORD files.
  • A file’s own header can say more. An SPDX-License-Identifier line in the comments at its top is that file’s licence. A licence notice there that differs from the component’s is counted along with it, so a file headed MIT inside a GPL project counts as both. Licences a header offers as a choice (“BSD, or alternatively the GPL”, “either the GPL or the CDDL”, “at your option”) count as one; a GNU notice’s “version 2, or (at your option) any later version” is a choice of versions only. Where the component has no licence, a header that only names the licence of the code it came from gives the file none. Code never counts, only comments.
  • A licence text with a condition on top, such as the Commons Clause after the Apache License, counts as both.
  • Symbolic links aren’t followed, only regular files are read, and nothing outside the indexed folders is read, even when a manifest names a licence file there through a link.

scan, check and notice

Option What it does
--index FILE An index made by remixware index. Repeatable
--from FILE A SCANOSS results file (scanoss-py scan -o FILE, or --scanoss-out) or a findings file from remixware scan --json. Repeatable
--scanoss Also ask the SCANOSS service. Only fingerprints are sent, see SCANOSS
--scanoss-key KEY A SCANOSS API key. Default: SCANOSS_API_KEY
--scanoss-url URL The SCANOSS service to ask; Remixware asks /scan/direct on its host. Default: SCANOSS_SCAN_URL, else https://api.osskb.org, or https://api.scanoss.com with a key
--scanoss-out FILE Save SCANOSS’s answers as a results file, which --from reads
--license EXPR Your project’s licence, instead of its licence file or the policy
--policy FILE The policy file. Default .remixware.json in the project, if there is one
--exclude PATTERN Leave out project paths that match. Repeatable
--include-deps Also scan vendor, node_modules, third_party and virtual environments
--min-tokens N Smallest match from an index to report, in tokens. Default 50
--min-lines N Smallest match from an index to report, in lines. Default 5
--quiet Print only the findings and errors
--json FILE (scan, check) Write the findings as JSON
--html FILE (scan, check) Write a self-contained HTML report
--spdx FILE (scan) Write an SPDX 2.3 document
--fail-on LIST (check) Statuses that fail the check, comma separated
--out FILE (notice) Notices file to add entries to. Default: print them
--all (notice) Also write entries for copies that are already credited

An index can hold code inside your project, such as your own vendor folder, or the whole project when you index a folder above it. Indexed code inside the project is third-party code when it sits in a folder such as vendor or third_party, has a licence of its own that differs from the project’s, or comes from an index of a folder inside the project: the rest of the project is checked for code copied from it, and no file is reported as a copy of the component it’s part of. Everything else inside the project is the project’s own code, scanned like the rest, and nothing is reported as copied from it. An index never makes a scan skip a file. Symbolic links in the project aren’t followed, and the scan says how many it passed over.

An index is data. One made elsewhere can’t show a scan a file on your machine that it doesn’t hold: an indexed file is read back only when its bytes match the checksum in the index. One that doesn’t hold together, unpacks to far more than its size or lists more files than it could hold is refused as damaged.

Results files, findings files and SCANOSS answers are data too. Characters a terminal acts on (escape sequences, line breaks inside a name, direction marks) are taken out of their text and of the text in indexes, which otherwise stays as it is so copyright lines still match, and everything Remixware prints goes through the same filter. A copyright line that would start a Markdown block in a notices file is escaped. An entry whose path points outside the project, or holds such characters, is left out with a warning, and check then exits with 2. A results file may give one file at most 100 SCANOSS matches, each listing at most 100 licences, copyright lines or package URLs, and a findings file at most 20,000 findings per file, each with at most 100 copyright lines.

SCANOSS

With --scanoss, Remixware fingerprints the files a scan reads, plus the minified files a scan skips (.min.js and .min.css files, and source files with very long lines), which SCANOSS can name as a whole, and sends the fingerprints to the SCANOSS service in batches of up to 32 files. It makes them the way SCANOSS’s own scanner does, with one difference: that scanner takes a few text files for binary by their first bytes, such as a source file starting with “BM”, and sends no hashes for them, while Remixware hashes them. For each file it sends a number with the file’s extension, the file’s MD5 checksum and size, a second checksum taken with the other kind of line endings, and hashes of short runs of the file’s letters and digits: no code and no file names. Each request also names Remixware’s version and carries a random request ID, and your API key if you set one. The answers come back about the numbers. An answer about anything Remixware didn’t send is dropped, and an answer has to cover every file sent: one that leaves files out is asked for again, and then the command exits with 2.

The free service at https://api.osskb.org is run by the Software Transparency Foundation, under its terms. When the service asks Remixware to slow down, Remixware waits as long as it asks, a minute at a time, and tries again, up to five times, with a line saying so. When it asks for a longer wait than that, as it does once a usage limit is used up, Remixware stops and says how long, and for a long wait until when. A SCANOSS API key avoids the free service’s limits. Remixware asks /scan/direct on the host of the URL it’s given, as SCANOSS’s scanner does, and doesn’t follow redirects, which could take the key and the fingerprints elsewhere. A user name, password or query in the URL never shows up in output or reports.

Exit codes

Code Meaning
0 All went well, and check found nothing that breaks the policy
1 check found findings that break the policy
2 Bad arguments, an unreadable or damaged file, a check that found no source files to scan or none to send to SCANOSS, a SCANOSS service that didn’t answer or turned the request away, a check with a results file it could only read in part, or another error

Statuses

Status Meaning
conflict The copied code’s licence can’t be combined with your project’s licence as it stands, for example GPL code in an MIT project
no-license No licence was found for the source, so nobody has given permission to copy it
review A person has to look: a file-level copyleft licence such as MPL-2.0 or LGPL, code that fits only if your project moves to another licence version (Apache-2.0 into GPL-2.0-or-later), a licence text Remixware doesn’t recognise, or the same code also found under stricter terms. A copy that also needs its notice shows as attribution-missing until your notices have it
attribution-missing The licence allows the copy, but its copyright line and licence text have to ship with your code, and your notice files don’t have them
attributed Allowed and credited: your notice files name the source, or the copied file kept its original copyright header
allowed Accepted by a rule in your policy file
ok Public domain or similar: nothing to do

check fails on conflict, no-license and attribution-missing unless the policy or --fail-on says otherwise. Without any licence, your own project is treated as proprietary.

Each finding also says how the code was copied: verbatim (as is, perhaps reformatted or with comments changed), edited (some lines changed), renamed (names changed throughout), and for SCANOSS results file or snippet. Its ID, such as RW-5441d221, stays the same from scan to scan while the file and the source stay the same.

Notice Files

A source counts as credited when one of your notice files has its full component name (such as github.com/acme/tool or click@8.1.7), its repository address, its package URL, one of its full copyright lines, or the Source: line that remixware notice writes, as a whole word: github.com/acme/tool-extras doesn’t credit github.com/acme/tool. A bare name like errors doesn’t count, since it’s an everyday word, and neither does an entry remixware notice left for you to finish.

Without notice_files in the policy, Remixware reads files in your project’s top folder named like NOTICE, THIRD_PARTY_NOTICES.md, CREDITS, ATTRIBUTION or ACKNOWLEDGEMENTS, and every file in folders such as licenses/ and third_party_licenses/.

Policy File

Put .remixware.json in your project’s top folder, or pass --policy FILE. Every field is optional. Unknown fields are errors, so a typo can’t quietly switch a rule off.

{
  "license": "MIT",
  "fail_on": ["conflict", "no-license", "attribution-missing"],
  "ignore": ["testdata/**", "docs/examples/**"],
  "notice_files": ["THIRD_PARTY_NOTICES.md"],
  "allow": [
    {"component": "github.com/acme/*", "reason": "Acme gave us a commercial licence in 2025"},
    {"license": "MPL-2.0", "file": "third_party/mpl/**", "reason": "MPL files are kept unchanged and published"}
  ],
  "min_tokens": 50,
  "min_lines": 5
}
Field What it does
license Your project’s licence, as an SPDX expression
fail_on The statuses that make check fail. An empty list is an error
ignore Project paths not to scan. * stays inside a folder, ** crosses folders, and a bare name matches at any depth
notice_files Where you credit third-party code, when the defaults don’t find it. Folders are read file by file
allow Findings you accept on purpose. Each rule names a component (* works as a wildcard), a file pattern, a license, or several of them, and must give a reason
min_tokens, min_lines The smallest match from an index to report

Reports

  • HTML (--html): one self-contained page with every finding and the reason for each status, with your code next to the source for matches from an index, and a link to the source for SCANOSS matches. It works offline and in dark mode.
  • JSON (--json): findings, each with id, file, lines, status, reason, source and match, plus counts per status and what was scanned. inputs lists what the project was compared with, each with a kind: index, scanoss (a results file), remixware (a findings file) or scanoss-api (the SCANOSS service, with its URL and the number of files sent), and for a results or findings file the number of entries dropped. --from reads it back.
  • SPDX (--spdx): an SPDX 2.3 document in JSON with each copied snippet’s byte and line ranges, its source, its licence and its copyright lines.
  • Notices (remixware notice): Markdown entries with the copyright lines, the licence texts and the files that use the code. Each entry carries the component’s own licence files when the index has them, and the standard text of any other licence the copy is under, built in for MIT, BSD-2-Clause, BSD-3-Clause, ISC, Zlib, BSL-1.0, Apache-2.0 and MPL-2.0. What notice can’t find, it asks you to fill in.

How Matching Works

Remixware reads source as tokens: it drops comments and layout, keeps keywords, operators and literals, and numbers each name in the order it first appears. A copy with new spacing, comments or variable names gives the same tokens. It hashes every run of 17 tokens and keeps a sample of those hashes, chosen so that a shared run of 28 tokens or more always leaves a shared hash. Hashes shared with an indexed file are chained into stretches that move through both files together. A stretch becomes a finding when it covers at least 50 tokens and 5 lines; when only the shape matches and the names don’t, it has to cover more, with fewer gaps, and where a line matches exactly, names included, that place wins over look-alike lines. Code that everyone writes the same way, such as a run of near-identical lines or Go’s sort.Interface methods, isn’t matched, and neither are tables of numbers or strings with no names in them, such as a hash function’s constants.

Remixware reads Go, C and C++, Objective-C, Java, C#, Dart, Kotlin, Swift, Scala, JavaScript and TypeScript (with Vue and Svelte files), Rust, Python, Ruby, PHP, shell, Perl, SQL, Lua, CSS and SCSS, R, Julia, Elixir, Nim, PowerShell and Tcl. Generated, minified and binary files are skipped, and so are files over 2 MB. With --scanoss, minified files go to SCANOSS too.