Skip to content

CLI Reference

Diffract can be used in two ways from the command line:

  • GUI mode - launch the app and pre-load one or two paths into the comparison view.
  • Headless mode - run a comparison entirely in the terminal with no window, writing the result to standard output.

GUI mode

Open a file comparison:

diffract left_file.txt right_file.txt

Open a directory comparison:

diffract left_directory/ right_directory/

Pre-fill only the left side:

diffract left_file.txt

Open the welcome screen (no pre-loaded paths):

diffract

Single-instance behaviour

If Diffract is already running when you invoke it from the command line, the new paths are sent to the running instance via a TCP loopback connection. A new comparison tab opens in the existing window without launching a second process.

The running instance's port is written to {systemTemp}/diffract_port.txt when the app starts. The CLI launcher reads this file to locate the running instance. If the file is absent or the connection fails, a new Diffract process is started.

Path rules

  • Paths can be absolute or relative to the current working directory.
  • If both paths point to directories, a directory comparison opens.
  • If one path is a file and the other is a directory, Diffract opens the file and leaves the directory-side path bar empty.
  • Archive files (.zip, .tar.gz, .jar) open in archive comparison mode (Pro).
  • Image, Excel, Word, and PDF files open in their respective comparison modes (Pro).

Exit behaviour

GUI mode returns immediately after sending the paths to the running instance (or after launching a new process). It does not wait for the comparison to complete.

Note

For use as a git difftool, see Git Integration.


Headless mode

Headless mode runs a comparison without opening any window and prints the result to standard output. It is intended for scripts, CI pipelines, and editor integrations.

Basic usage

diffract --headless left_file.txt right_file.txt

Directory comparison:

diffract --headless left_directory/ right_directory/

Options

Option Description
--format / -f Output format: unified (default), json, or summary.
--exit-code Exit with code 0 if files are identical, 1 if they differ. Without this flag the exit code is always 0 on success.
--algo Diff algorithm: myers (default), patience, histogram. semantic is also available with a Pro licence.
--ignore-case Treat uppercase and lowercase letters as identical.
--ignore-whitespace Ignore all whitespace differences.
--ignore-trailing-whitespace Ignore trailing spaces and tabs on each line.
--ignore-line-endings Treat CRLF and LF line endings as identical.
--auth-header HTTP header for remote (http/https) paths, e.g. --auth-header "Authorization: Bearer <token>". Repeatable. (Pro)
--ssh-password Password for ssh/scp remote paths. (Pro)
--ssh-key Path to an OpenSSH ed25519 or RSA private key for ssh/scp paths.
--ssh-passphrase Passphrase for an encrypted --ssh-key.
--aws-access-key / --aws-secret-key AWS access key ID / secret for s3:// paths. (Pro)
--aws-region AWS region for s3:// paths (default us-east-1).
--aws-endpoint Custom S3-compatible endpoint (MinIO / R2 / Wasabi) for s3:// paths.
--azure-account Azure storage account name for az:// paths.
--azure-key / --azure-sas Azure shared key / SAS token for az:// paths.
--gcs-token GCS OAuth bearer token for gs:// paths.
--ftp-user / --ftp-password Username / password for ftp:// / ftps:// paths (default: anonymous). (Pro)
--help / -h Print usage information and exit.

Remote paths

Either path argument can be a remote URL. Diffract fetches it to a temporary file and then runs the normal comparison.

HTTP / HTTPS - public URLs need no extra flags:

diffract --headless compare https://example.com/a.txt local/b.txt

For authenticated endpoints, pass one or more --auth-header flags:

diffract --headless compare \
  https://api.example.com/config.yaml local/config.yaml \
  --auth-header "Authorization: Bearer $TOKEN"

SSH / SFTP - use an scp://user@host[:port]/path (or user@host:/path) path with a password or an ed25519 key:

# Password auth
diffract --headless compare scp://deploy@web01/etc/nginx/nginx.conf ./nginx.conf \
  --ssh-password "$SSH_PASSWORD"

# Key auth
diffract --headless compare deploy@web01:/etc/hosts ./hosts \
  --ssh-key ~/.ssh/id_ed25519

Cloud object storage - compare an s3://, az://, or gs:// object:

# Amazon S3 with explicit keys
diffract --headless compare s3://my-bucket/config.yaml ./config.yaml \
  --aws-access-key "$AWS_ACCESS_KEY_ID" \
  --aws-secret-key "$AWS_SECRET_ACCESS_KEY" --aws-region us-east-1

# S3-compatible (MinIO/R2/Wasabi) via a custom endpoint
diffract --headless compare s3://my-bucket/config.yaml ./config.yaml \
  --aws-access-key KEY --aws-secret-key SECRET --aws-endpoint http://localhost:9000

# Azure Blob (SAS token) and GCS (bearer token)
diffract --headless compare az://container/config.yaml ./config.yaml \
  --azure-account myacct --azure-sas "$AZURE_SAS"
diffract --headless compare gs://my-bucket/config.yaml ./config.yaml \
  --gcs-token "$(gcloud auth print-access-token)"

With no --aws-* keys (and no region/endpoint), S3 paths use the default AWS credential chain (environment variables, then ~/.aws/credentials); public buckets/objects work with no credentials at all.

FTP / FTPS - compare an ftp:// or ftps:// file:

# Authenticated FTPS (TLS)
diffract --headless compare ftps://files.example.com/pub/app.yaml ./app.yaml \
  --ftp-user deploy --ftp-password "$FTP_PASSWORD"

# Anonymous FTP (no flags needed)
diffract --headless compare ftp://files.example.com/pub/readme.txt ./readme.txt

With no --ftp-user, FTP paths log in anonymously. Plain ftp:// is unencrypted; prefer ftps:// on untrusted networks.

Host keys are trusted on first use and checked against ~/.ssh/known_hosts; a changed host key exits with code 2. An unreachable, denied, or directory path also exits with code 2 and a message on standard error. (Remote comparison requires a Pro licence in the GUI; the headless paths are provided for CI and scripting.)


Output formats

unified (default) - standard unified diff:

--- left_file.txt
+++ right_file.txt
@@ -1,4 +1,4 @@
 line one
-line two
+line TWO
 line three

json - array of diff objects, one per line pair:

[
  {
    "status": "same",
    "leftLine": 1,
    "rightLine": 1,
    "leftContent": "line one",
    "rightContent": "line one"
  },
  {
    "status": "modified",
    "leftLine": 2,
    "rightLine": 2,
    "leftContent": "line two",
    "rightContent": "line TWO"
  },
  {
    "status": "same",
    "leftLine": 3,
    "rightLine": 3,
    "leftContent": "line three",
    "rightContent": "line three"
  }
]

summary - single line with counts:

+2  -1  ~3  =140

Fields: added lines (+), removed lines (-), modified lines (~), unchanged lines (=). A ⇕N field is appended when moved blocks are detected.

For directory comparisons the summary counts files, not lines, and uses [+], [-], [~], and [=] badges per entry.

Exit codes

Code Meaning
0 Success. Files are identical, or differ and --exit-code was not passed.
1 Files differ (only when --exit-code is passed).
2 Error (missing path, unreadable file, bad arguments).

Examples

Check whether two config files differ in a script:

diffract --headless --exit-code prod.conf staging.conf
if [ $? -eq 1 ]; then echo "configs differ"; fi

Export a comparison as JSON for further processing:

diffract --headless --format json old.py new.py > diff.json

Case-insensitive summary of two directories:

diffract --headless --format summary --ignore-case dir_a/ dir_b/

AST-aware semantic comparison (Pro licence required):

diffract --headless --algo semantic old.py new.py

Note

--algo semantic requires a valid Pro licence key to be activated on the machine. It falls back to Myers silently if no licence is present or the language is unsupported.