magus-diff
Read the working tree's changes in the order they deserve attention
Synopsis
magus diff [--generated] [--impact] [--no-tui] [--watch] [--rev <base>...<head>] [--patch <file>|-] [<path>...] [flags]
Description
Read the working tree's uncommitted changes, annotated and ordered.
A changeset is not a list of files, it is a set of CONSEQUENCES, and a reader's attention is scarce. Alphabetical order spends it at random: it gives a regenerated lockfile the same weight as a signature change twelve packages depend on. This orders by what a change can BREAK.
Generated files - declared target outputs - are folded away by default. Reading one is reading a machine's restatement of a change made somewhere else, so the source edit is the review. Pass --generated to see them anyway.
At a terminal this opens an interactive viewer: the same annotations, plus navigation and a way to mark what you have read. It is the same report either way - the viewer renders the identical annotation lines - so nothing is hidden behind a keypress, and ] and [ walk hunks while q leaves.
The viewer stands aside on its own wherever it cannot draw: no terminal, -o json, --watch, a patch argument, or --impact. Those are not refusals, they are the report printing instead, so a script or an agent needs no flag. --no-tui is for a person who wants the report at a terminal anyway, and "magus config set key=diff.tui,value=false" makes that the standing preference.
One rule decides what a word on the command line means: the CHANGESET is always named by a flag - --rev, --patch, or the working tree by default - and every positional is a PATH that narrows it. So "magus diff internal/ledger/" reads only that subtree, and it means the same thing whichever source it is narrowing.
The patch source moved behind --patch for that rule. A bare - still reads stdin, because it is unambiguous and it is what every pipe in the world already types.
--rev reads a committed range as base...head rather than the working tree, which is how you review a branch: a colleague's, or the one your own agent just finished. It is the half a working-tree diff cannot reach, and it keeps the viewer, the navigation and the marks, because a revision is a tree state magus can address rather than a patch somebody handed it. Three dots: the answer is what head added since it diverged, never what the base gained meanwhile.
A receipt earned against a range attests to the blob at that revision, so it survives the working tree moving underneath and does not follow the branch when somebody force-pushes it. That is the whole difference from a working-tree receipt, and it is why --ack takes --rev where it refuses a patch: magus can name what a range receipt covers, and cannot name what a patch on stdin covers.
Each file carries the evidence behind its rank: how many files reference the widest changed symbol it defines, whether any of those referents cross a project boundary or the module boundary (which is the question a version bump turns on), and the coverage a prior run observed. None of it is a verdict. magus does not claim a change is breaking - deciding that needs signature compatibility, which needs a base-side index magus does not keep and language semantics it does not model - it reports who can see the thing you changed and lets you decide.
The console's Diff surface reads the same annotations over the same session, and an agent can join that session through the magus_diff MCP tool.
--impact appends the blast radius of landing the change: which projects rebuild and which were merely edited, who has been changing them, an estimate of the rebuild from recorded run durations, what the workspace's advisors say, which human-authored notes anchor a file or symbol you touched, and what the authors asked magus while writing it. It is the same question magus affected --impact answers, asked of a changeset instead of a target. It is context and never a verdict - nothing is gated on it and the exit code is unchanged; neither the flag nor the section it prints says "preflight", because in this workspace's magusfiles a preflight target IS a gate and this must never read as one. Each section says when it could not measure something, so an empty one reads as "nobody looked" rather than as a clean bill of health.
--impact also carries a REVIEW section, which is a bookmark rather than a score. It reports the two things a reader cannot produce without reading: files that changed AFTER they were read, and files never opened, widest blast radius first. It reports no ratio and stays silent on a small change nobody has disturbed - a count with a target is a count that gets cleared instead of satisfied.
--prompt prints a review prompt for you to paste into whichever model you use, and magus stops there: it calls no model, holds no key, and sends nothing. It is the same refusal magus agent makes about your AGENTS.md - magus generates the text and a person carries it across, because a tool that crossed the boundary itself would leave bytes you did not write and cannot audit. It asks for findings rather than review prose; the words your colleague reads should be yours. Add --impact for the rationale behind each instruction.
A receipt covers a file at its CURRENT content, so editing it afterwards voids the receipt. Stepping a file through in the viewer earns one; --ack covers the changeset at once and takes an optional --reason kept with it. magus never infers a receipt from an editor or a session: a measure satisfied by scrolling would launder skimming into review. --ack refuses without a terminal, and agent hosts are denied it outright.
The count is never shown to anyone but the reader. There is no team view and no pull-request comment, because a read measure a second person can see is a performance metric, and a performance metric gets gamed rather than met.
Options
- --ack
- Record that you have read the changed files at their current content; --impact reports what carries no such record
- --generated
- Include declared target outputs, which are folded away by default
- --impact
- Append the blast radius of landing this: reach, ownership, an estimate from recorded run times, advisors, note anchors, and the evidence the authors consulted
- --no-tui
- Print the report instead of opening the interactive viewer
- --patch -
- Review a patch somebody handed you instead of the working tree; `-` reads stdin
- --prompt
- Print a review prompt to paste into your own LLM: the context magus has, never a drafted review. With --impact, also carries the rationale behind each instruction
- --reason string
- An optional note kept with an --ack, for the next reader of the report
- --rev string
- Review a committed range instead of the working tree, as base...head: a colleague's branch, or your agent's finished work
- --watch
- Re-read and re-render whenever the working tree changes
Exit status
- 0
- The changeset was read and rendered. This is the status whether or not anything changed: unlike git diff --exit-code, a non-empty changeset is not a failure, and no flag makes it one.
- 1
- The changeset could not be read - an unreadable patch file, or stdin, or a working tree the VCS would not report on.
- 2
- Misuse: more than one patch argument, or an argument that is neither a readable patch nor -. The viewer never causes this: where it cannot draw - no terminal, -o json, --watch, a patch argument, --impact - it stands aside and the report prints instead.
Examples
Read what you are about to commit
magus diff
Review a branch somebody else pushed
magus diff --rev main...feat/audience
Narrow it to one subtree
magus diff internal/ledger/
Include the generated files too
magus diff --generated
Everything to know before landing it
magus diff --impact
Print the report instead of opening the viewer
magus diff --no-tui
Build a review prompt for the model of your choice
magus diff --prompt
Machine-readable, for a script or a Buzz advisor
magus diff -o json
See Also
magus(1), magus-ls(1), magus-describe(1), magus-run(1), magus-x(1), magus-where(1), magus-affected(1), magus-graph(1), magus-query(1), magus-explain(1), magus-path(1), magus-refs(1), magus-watch(1), magus-events(1), magus-status(1), magus-clean(1), magus-vcs(1), magus-doctor(1), magus-config(1), magus-session(1), magus-memory(1), magus-notes(1), magus-server(1), magus-mcp(1), magus-buzz(1), magus-completion(1), magus-man(1), magus-init(1), magus-agent(1), magus-self(1), magus-version(1)