diff compiles your package in memory, fetches the definitions the revision actually holds, and reports the gap
between them. It writes no file, uploads nothing, and creates nothing.
It is the command to run before a deploy, and the command to run after one
stops. Almost every hint the CLI prints points here, because diff needs only read access and refuses to fail
on the input you are trying to understand.
Synopsis
There is no
--dry-run and no --force: diff has no side effect to withhold and nothing to overwrite.
It always exits 0
diff is a report, not a gate. Every state it can discover — a definition missing on either side, a topology
that has moved, code that no longer matches, a port edited in the visual editor, even a package that does not
compile — is printed, and the exit code stays 0.
That is deliberate. diff is the escape hatch that MANIFEST_INVALID, MANIFEST_NOT_FOUND,
REVISION_NOT_WRITABLE and REVISION_NOT_ACCESSIBLE all send you to, so dying on a broken import would kill
the CLI’s own diagnostic on precisely the input a user runs it to understand.
What can still fail is what diff cannot reach: an unreadable manifest, a blob or revision it cannot resolve, a
credential problem, a transport failure. Those exit 1 like anywhere else. Once diff has a manifest, a
revision and a listing, nothing it finds changes its exit code — so do not use it as a CI gate. To fail a
build on a real difference, read the --json payload, or use build --strict-imports for import certainty and
check for validity.
What it reports
One block per definition, drift first:
Under
--json the payload carries definitions — each with category, alias, presence,
components_added, components_removed, connections_changed, code_changed, compile_error and state —
plus drift, alongside the envelope’s schema_version.
The state line is about the platform’s copy
build and deploy classify the code port in your local definition file. diff classifies the remote one,
which is what makes it the only command that sees a visual-editor edit before you have pulled it.
So
REMOTE_EDIT here is a warning to act on, not a refusal you will hit later. Pull it, or eject it, before you
deploy over it. When a definition binds several code components, the worst state wins, because that is the one
that decides what happens next.
state is absent when the definition is not on the revision, and when the manifest binds no code components to
it.
Compilation is offline here
Likebuild, diff reads the import allowlist from the local cache rather than fetching it, so it does not need
an admin key and works with a stale or missing cache. Unresolved imports raise IMPORT_UNVERIFIED as an
advisory; --strict-imports does not exist on this command, since a report has nothing to be strict about.
Errors
Every compiler code —
IMPORT_UNAVAILABLE, SYMBOL_COLLISION, IMPORT_CYCLE and the rest — appears as a
definition’s compile_error rather than as a failure. It is the same code you would get from build, reported
instead of raised.
Every code above, with its remediation, is in Error codes.
See also
blobhub workflow deploy— whatdiffis describing.blobhub workflow pull— how aREMOTE_EDITstate gets onto disk.blobhub blob show— whendiffitself cannot resolve the blob or revision.- Concepts — managed code ports and the three states behind
state.

