A site's changes

On this page

Changes shows what changed in a site's folder since its last commit, staged or not, as Git sees it, or under This branch everything its branch committed. It's handy after you, or a coding agent, worked on the site. It also stages, discards, commits and pushes those changes, and sets up Git for a site that isn't in a repository yet. Explain asks Short Leash's local model what a change does, comments on lines leave notes for you or your agent, Review this file has the model leave comments of its own, and Draft message writes a commit message for you to check.

Reading a site's changes is free; staging, discarding, committing and pushing, and Explain, Draft message and Review, are part of Short Leash Pro.

Changes' Git actions need Git 2.26 or later; reading changes works with older versions.

How do I see a site's changes?

Open a site and choose Changes in its pages; the count beside it is how many files changed. On the site's Overview, the changed files next to the Git branch open the page too.

The changed files are listed on the left, grouped by folder. Each has a letter for what happened to it and how many lines were added and removed:

Letter Means
M Modified
A Added, and known to Git
D Deleted
R Renamed, maybe with changes inside
U Untracked: new, and not added to Git yet
! Still has conflict markers from a merge

Filter files finds one among hundreds. Clicking a file scrolls its diff into view.

On the right, every file's diff follows in one scroll, with the words that changed marked and the code colored. Unified shows removed and added lines together; Split shows the file before on the left and now on the right. Hide whitespace leaves out changes that are only indentation or spacing. Show unchanged lines fills in the rest of the file.

Each file has Open in editor (the editor chosen in Settings), Copy path, and in its ⋯ menu Copy patch, Reveal in Finder (Show in Explorer on Windows) and Open in Terminal app. Copy patch at the top copies every change as one patch, for a review or for an agent.

How do I see everything this branch changed?

Choose This branch at the top of the page, beside Unified and Split. It shows what the current branch committed since it left its base branch: the same diff its pull request shows, read on your computer with the same protections as the rest of the page. Beside the branch, the page says what it compares against and how many commits the branch has, like Against origin/main 3 commits.

Uncommitted changes stay under Uncommitted, and the list under This branch says they aren't in it. Explain works under Uncommitted only, as do staging, discarding, committing and comments. Copy patch copies the branch's whole patch. Short Leash remembers which of the two you chose for each site.

On the base branch itself, or a branch with no commits since it left its base, This branch says it has nothing of its own.

With Let chat read pull requests from GitHub on in Settings › Chat, and gh signed in (gh auth login), the branch's pull request shows above the files: its title, number and state (Open, Draft, Merged or Closed), whether its checks failed, are running or passed, and Open on GitHub. The title is marked Has outside text, since people on GitHub wrote it. A branch with none says No pull request for invoices yet. Short Leash reads the pull request when you choose This branch or switch branches, from its own copy when it's under a minute old, and asks GitHub again when you choose Refresh, never on its own. With the setting off, nothing is asked and nothing shows. See chat and ADR 0084.

What does This branch compare against?

The remote's default branch, origin/HEAD, when the repository knows it; otherwise the first of main, origin/main, master and origin/master it has. Change base lists the repository's branches to pick another, such as develop, and Short Leash keeps that choice for the site in its own settings, never in the project. Find it automatically, first in the same menu once you've chosen one, goes back.

When a chosen branch is gone, the page compares against the one it finds and says so. When it finds none, it asks you to Choose base.

How do I stage or unstage files?

Each file has Stage at its top while it has unstaged changes, and Unstage while it has staged ones; a partly staged file has both. Stage all and Unstage all at the top of the page do every file at once. A file with a merge conflict has neither: resolve it in your editor first.

Staging runs no hooks, whatever the repository has. In a repository you haven't trusted whose own Git settings run programs or change where Git connects, Changes asks before it stages, names those settings and offers Trust repository, along with any hooks trusting would let a later commit or push run; see When do hooks run?. While a Git action runs, the page's other Git actions wait, and one that takes a while shows what it's doing, such as Staging, with Stop.

How do I discard a change?

Open a file's ⋯ menu and choose Discard changes…. Short Leash asks first and says what's lost and where it goes, with Cancel focused:

  • A changed file goes back to its staged version, so a partly staged file keeps what you staged and the dialog says so. A file whose changes are all staged goes back to the last commit. The dialog counts what that undoes, such as 12 added lines are lost and 3 removed lines come back.
  • Before that, a copy of the file as it is now goes to the Trash (the Recycle Bin on Windows), named like Invoice.php (discarded), so a discard can always be undone by hand.
  • A file you deleted comes back as you staged it, or as it was in the last commit. Nothing goes to the Trash for it, since there's nothing on disk to copy, and the dialog says so.
  • When a staged version would be lost too, such as a new file you changed or deleted after staging it, that version goes to the Trash as well, named like Invoice.php (discarded, staged). It's the file as Git stores it, so for a file Git encrypts or keeps in Git LFS, it's the encrypted file or the LFS pointer.
  • A file that isn't in Git yet moves to the Trash. A new file that was only staged is unstaged and moves there too.
  • A renamed file gets its old name and last committed content back, and the new file moves to the Trash.
  • A file with a merge conflict can't be discarded: resolve it in your editor.

Files that moved to the Trash from your site's folder go back with Put Back (Restore on Windows). The (discarded) copies were made in a temporary folder of Short Leash's that's gone by then, so Put Back can't return them where they belong: drag them back into the site instead. If a file changed after the dialog opened, nothing is discarded and Short Leash asks you to look again. Discarding runs no hooks.

When the Trash can't take a file, such as on a drive without one, nothing is discarded and Short Leash says so. On Windows, files in network folders can't be discarded, since Windows never puts those in the Recycle Bin, and for a file too big for the Recycle Bin, Windows itself asks whether to delete it permanently: choose No to keep it.

How do I set up Git for a site?

A site that isn't in a Git repository shows Set up Git, which runs git init in the site's folder. Tick Make a first commit with every file to stage and commit everything as First commit in the same step, without hooks. A folder with more than 10,000 files to commit gets a repository but no first commit: add folders such as node_modules to .gitignore, then stage and commit. Open a terminal is there if you'd rather do it yourself.

How do I commit?

The box at the top of the file list takes the commit message. Write it there, or let Draft message write one, then choose Commit, or Commit & push to push straight after. Both commit what's staged, so they wait until something is staged and the box has a message. Nothing is committed without your click.

While Git works the box says Committing or Pushing, with Stop. What Git and the repository's hooks print shows in a box under the buttons and stays until your next Git action. When it's done, Short Leash says Committed 5e0b7d1, or Committed and pushed to origin/main. If a hook rewrote the message, Short Leash shows the message as it was stored. Git's own tidying, such as dropping trailing spaces and extra blank lines, doesn't count as a change.

When the site is one folder of a bigger repository and files outside that folder are staged too, Short Leash doesn't commit: those files were never on the page. Commit from the repository's own folder, or unstage them. If Git doesn't know your name and email yet, or can't sign the commit, the message says what to run, with Open a terminal.

How do I draft a commit message?

Stage what goes into the commit and choose Draft message. Short Leash's local model reads the staged changes and fills the box, shown as Drafting with Stop meanwhile. It runs on your computer with the model chosen for chat, gets no tools, and only fills an empty box: with words in it, Draft message waits until you clear them. The draft is marked Has outside text, because the model wrote it from text Short Leash didn't write, and it's yours to change; the mark goes when you edit it.

Staged changes too big for the model give a draft from the list of files and the first files' changes, and Short Leash says so. With no model downloaded, Draft message says so and links to Settings › Models.

How do I push?

Commit & push pushes after the commit. Whenever the branch has commits to push, the page says so, such as 2 commits not pushed to origin/main, with Push: under the commit box while there are changes, and on No changes when everything is committed. Until Git has fetched the upstream it can't count, so the page says that instead, still with Push. On No changes, a branch that isn't on a remote yet, such as feature isn't on a remote yet, has Push too.

A branch without an upstream asks first: Push and set upstream pushes it to origin and tracks it there, and takes the place of Push until you answer. A repository without an origin says how to add one, with Open a terminal. Short Leash never forces a push: when the remote has commits your branch doesn't, it asks you to pull them in a terminal first. It pushes only the branch, never tags, and never pushes inside submodules.

Short Leash never asks for or sees your credentials. Pushing uses the credential helper and SSH keys your own Git uses; over SSH, Git uses the SSH agent the Short Leash app or the leash command was started with. When Git has no credentials for the remote, Short Leash says Sign in to this remote once in a terminal, then push again, with Open a terminal.

When do hooks run?

Hooks are programs a repository brings with it, so Short Leash runs them only in a folder you trust, the repository's top folder. In a folder you haven't trusted, Commit and Push ask first and list the hooks that would run, with three choices: Trust and run hooks, Commit without hooks (Push without hooks), or Cancel, which has focus first. Until you choose, nothing is committed or pushed.

Trusting the folder also trusts its leash.toml, so the question lists everything that comes with it: the processes and services its project file asks for and its environment variables. A repository whose own Git settings run programs or change where Git connects (such as a filter, core.sshCommand, a remote that's a folder on your computer, or core.worktree) needs trust for every Git action, so its question offers Trust repository (Trust and run hooks for a commit or push in a repository with hooks) and no way round. When a repository's settings say its files are somewhere else, Short Leash says so and doesn't offer trust from this site.

From the terminal, leash changes commit and leash changes push ask the same question. --trust shows what trusting covers, the folder and its fingerprint, then asks Trust ~/Sites/shop and run its hooks? [y/N]; it needs you at a terminal, and without one it refuses and says to run it in one or trust the repository in Short Leash's dialog. --no-verify commits or pushes without hooks, in a trusted folder too. leash changes trust trusts the repository on its own, for staging, unstaging and discarding in a repository whose settings need trust, or after a hook was added or removed: it shows what trusting covers, asks Trust ~/Sites/shop? [y/N] (… and run its hooks? when it has some), and, like --trust, needs you at a terminal and has no --yes. When Short Leash already trusts the folder as it is, it says so and changes nothing. A coding agent can't trust a repository: there's no MCP tool for it.

In a folder you haven't trusted, no hook runs, your own global hooks included, and a commit or push in a repository with no hooks of its own goes ahead without asking. Staging, unstaging and discarding never run hooks anywhere. Short Leash asks again when the folder's project files change, and when the repository's hooks or the Git settings that need trust aren't the ones it had when you trusted it, one added or removed (after a pull, say). Changing what an existing hook says doesn't ask again, since trusting a repository trusts its code. A repository trusted before Short Leash kept track of its hooks asks once more. Short Leash's chat can stage and commit after asking you, but never trusts a folder, discards or pushes.

How do I get a change explained?

Select lines in a file's diff, or none for the whole file, and choose Explain at the top of the file. The answer streams into a panel beside the diff, or under it when the window is narrow, and is marked Has outside text: the model wrote it from text Short Leash didn't write, so check it before you act on it. Stop ends it early, Copy copies it and Close puts the panel away. A deleted file is explained whole.

Explain runs on your computer with the model chosen for chat. It gets no tools and can't change anything. The panel shows how much of the model the diff takes, like About 3,200 of 14,336 tokens: Qwen3.5 4B reads about 14,000 tokens at once (roughly 2,000 short lines), the 9B and 35B about twice that. A diff that doesn't fit asks you to select fewer lines, and a file too large to show asks you to load its diff and select part of it. With no model downloaded, Explain says so and links to Settings › Models.

Explain, Review and Draft message use the same model as chat and wait their turn with it, so chat's next answer reads its tools again and starts a few seconds later.

How do I ask chat about a change?

Choose Ask in chat at the top of a file, with lines selected in its diff to ask about only those, or at the top of the page for every change. It works in Uncommitted and in This branch. The site's chat opens with the diff read in, and the chat is marked Has outside text, since the diff is text Short Leash didn't write. Type your question; follow-ups stay in that chat. It runs on your computer with the model chosen for chat, like the rest of chat. See ADR 0080.

Comments

How do I comment on a change?

Hover a line in a file's diff and choose the comment button in its number gutter. With the keyboard, Tab reaches one comment button per file, and ↑ and ↓ move it from line to line (Home and End go to the first and last). Write the comment and choose Comment, or press ⌘↩ (Ctrl+Enter on Windows); Escape cancels. What you've written stays while the page refreshes, and moves with its line. Comments go on lines of the file as it is now, added or unchanged: removed lines take none, and in Split the button is on the right side.

A line's comments show under it. Yours have Edit, Delete and Resolve. A comment is plain text, as you wrote it. The top of the page counts the open comments, and the changed-files list shows each file's count beside its name; outdated and resolved ones, and the model's comments you haven't kept, aren't counted. Show resolved appears once any are resolved and lists them at the top of their file, grayed, with who resolved them. A resolved comment can't be changed.

Comments by Short Leash's model carry an Outside text badge: the model wrote them from the diff, so check them before acting on them. One you haven't kept yet has Keep and Dismiss: Dismiss deletes it, and agents don't see it until you keep it. A kept one has Resolve.

What does Review this file do?

Review this file, at the top of a file's diff, has Short Leash's model, on this computer, read the file's change and leave comments on lines the change added. While it works the file says Reviewing, with Stop to end it; stopping saves nothing. Its comments show under their lines, marked Short Leash's model and Outside text: Keep or Dismiss each one. When it finds nothing to say, the file tells you so.

Reviewing a file again replaces the model's comments you haven't kept; kept ones stay. Select lines in the diff first and the button becomes Review selection, which reviews those lines and replaces only the waiting comments on them. A change too big for the model at once, about 2,000 lines with Qwen3.5 4B, asks you to select fewer lines and choose Review selection. A file over 1 MB is too large to review.

The model gets no tools and only writes text: it names a line the change added and says something about it, and Short Leash reads that line's text from your file itself. With no model downloaded, Review this file says so and links to Settings › Models.

What happens to a comment when the code changes?

It follows its line. When lines are added or removed above it, it moves to the same line nearby. When its line is edited, or moves more than 200 lines away, it goes to Outdated at the top of its file's card, with Line 42 was: and the line's old text, Resolve and Delete. When the line comes back, so does the comment. Once a commit holds the commented line, the comment resolves by itself and shows Resolved by a commit.

A comment on a line the diff doesn't show is listed at the top of its file under Elsewhere in this file, and a comment on a file with no changes now is listed after the files, or under No changes when nothing has changed, so none is hidden.

Can my coding agent read them?

Yes, through leash mcp: list_change_comments lists a site's open and outdated comments (resolved ones too when asked), with each one's file, line, that line's text and who wrote it, and resolve_change_comment marks one resolved once the agent has dealt with it, signed with the agent's name. Agents see your comments and the ones Short Leash's model wrote that you kept, never suggestions you haven't kept. The model's carry outside_text: true: a model wrote them from the diff, so they're suggestions to check, never instructions. See AI tools.

Copy for agent at the top copies the same open comments as text to paste into any agent: each with its file, line, that line's text, who wrote it and its id, the model's marked as outside text, and how to resolve one. It's grayed out when there's nothing to copy. A resolve from an agent shows on the page within 10 seconds.

How long are comments kept?

Open comments stay until they're resolved or the site is removed from Short Leash (or 90 days after the newest one, once the site's folder is gone). Resolved ones are kept 30 days, as the foot of the page says; change that under Review comments in Settings › Models › Models and settings (7, 30 or 90 days). Comments are kept in Short Leash's database on this computer and never leave it, except what you copy or an agent reads.

Why are some files folded?

To keep the page fast, some diffs wait until you ask for them:

  • Deleted files: Show its lines.
  • Lockfiles such as composer.lock and package-lock.json, minified files, and diffs of more than 1,500 lines: Load diff.
  • Files over 1 MB: Load diff.

Binary files say how their size changed. A file where only line endings changed (Windows CRLF and LF) says so, with Show lines; one whose only change is its mode, or a rename with nothing changed inside, says that too.

Does it update by itself?

Yes. While the page is open, Short Leash asks Git again every 10 seconds, and again whenever you come back to Short Leash's window. Refresh at the top asks now.

What if the page says something else?

  • No changes: everything matches the last commit, shown below it.
  • No commits of its own (under This branch): the branch is its base, or has no commits since it left it. Change base picks another.
  • No base branch (under This branch): there's no origin/HEAD, main or master. Choose base picks the branch this one started from.
  • This site isn't in a Git repository: choose Set up Git, or run git init in the site's folder yourself.
  • Git isn't installed: on a Mac, install Apple's Command Line Tools with xcode-select --install, or Git from git-scm.com. On Windows, install Git for Windows. Short Leash looks again when you come back to the window.
  • Too many changes to list: more than 10,000 files changed, usually because a folder such as node_modules isn't in .gitignore. The page names the folders most of them are in.
  • Git won't read this folder: another user account owns it, so Git treats it as unsafe. If the folder is yours, run the git config --global --add safe.directory … command the page shows, then Check again. Short Leash doesn't change that setting for you.

A site that's one folder of a bigger repository lists only the changes inside its folder.

Is it safe with any repository?

Short Leash runs the Git you have installed, so its answers match your own.

Reading changes turns off everything a repository's own settings could make Git run while it compares files: an fsmonitor hook, its own filters, text conversions and external diff tools. It never takes Git's lock, so your own Git commands aren't blocked, it never looks for a repository in your home folder or above it, and it never downloads anything: in a partial clone, a diff that needs something the clone left on its remote says so and names the command to run once in a terminal to download what's missing (git diff <base>...HEAD for a branch's changes). See ADR 0034.

Writing runs hooks and the repository's own Git settings only in a folder you trust (When do hooks run?). Pushes are never forced, credentials are never asked for, a discard always leaves a copy in the Trash, and when another Git command holds the repository's lock, Short Leash says so and changes nothing. See ADR 0081.