17/Documentation
Changes: see what an agent changed
The Files screen: a workspace's folder with its changes marked, the changed files and their diffs, and the last commit, from the pane or the dashboard's Files tab. Read-only git, nested repos, and the two settings that decide how far it looks
The Files screen shows a workspace's folder, with what changed in its git repos since the last commit marked on it. You read it on your phone while the agent works: the changed files, their added and removed lines, and each file's diff with syntax colour. When the agent has already committed, it shows the last commit. A control under the header switches between All files, the folder as a tree, and Changes, the list of changed files alone (below).
Note. Files only reads. It never stages, commits, edits or checks out a file (below).
Open it
There are two ways in.
- From a pane. Tap the Files button on the pane's actions belt, the tree icon left of the Switch mark. The screen covers the pane's whole workspace and marks the pane's own repo.
- From the dashboard. Tap Files in the dashboard's footer, after Dashboard (and Crew before it, when you run a crew). It lists one row per workspace with its changed-file count and the summed added and removed lines. A workspace with no changes stays in its place, dimmed. Tap a row to open that workspace's Files screen.
The dashboard counts refresh every 5 seconds, and only while the Files tab is on screen. The tab you pick is kept per device.
The list
The Changes segment shows a list that groups the changed files by git repo. Each file shows its status and its +added −removed line counts.
| Status | Meaning |
|---|---|
| Modified | A tracked file changed |
| Added | A new file, staged |
| Deleted | A tracked file is gone |
| Renamed | A file moved; its diff names the old path |
| Untracked | A new file git does not track yet |
- The base is the last commit. Staged and unstaged changes show together. A repo with no commits is compared against an empty tree.
- A new file shows as all added lines. A new folder is one entry: Collie says the folder is new and does not list the files inside it. That keeps a fresh
node_modulesout of the list. - A binary file is listed, but its lines are not shown.
- This pane. Opened from a pane, with more than one repo listed, the pane's own repo carries a This pane label. On the first read, the list scrolls to it.
- List or Tree. The Layout switch shows the files as one flat list per repo, or as a folder tree.
- Filter files. The filter button narrows the list by path text and by status. The list then says how many of its files are shown.
Read a diff
Tap a file to read its diff. Previous file and Next file step through the list without going back to it.
- The diff shows two line-number gutters, tinted added and removed rows, and lines that wrap.
- Common languages get syntax colour: TypeScript and JavaScript, JSON, CSS, HTML, Markdown, Python, Go, Rust, shell, YAML, TOML and more. A file in another language, or a diff over 2000 lines, stays plain.
- A very long diff stops at a limit and says so.
- If the agent reverts or commits the file while you read it, the diff stays on screen and its header says No longer changed. The view never jumps away.
The last commit
Agents often commit their own work, so the list can be empty right after the change you want to read. For a repo with no uncommitted changes, the view offers Show last commit.
The commit view shows the subject, the author, the time, the short hash and the commit's files, each with its own diff. It compares the commit with its first parent, so a merge shows what it brought in. It reads the newest commit only. There is no history browser.
- When the agent commits again, a quiet A newer commit exists waits for a tap. The files on screen do not change under you.
- When new uncommitted changes appear, New uncommitted changes takes you back to the list.
Comment on lines
Pick lines in a diff, write a note on them, and bring all your notes to the agent as one block of text.
- Open a changed file's Diff, from the list or from the last commit.
- Tap the lines you mean, and each picked line takes a tint.
- Tap Comment on selected (3), with the number of picked lines.
- Write your note under the quoted lines, and tap Add comment.
- Repeat on other lines and in other files, in any repo of the workspace.
- Tap Pending comments (2) · Bring to agent, with the number of notes.
- Tap Bring to claude draft (2), with the agent's name and the number of notes.
Collie puts the notes into the agent's draft in its pane and opens the pane. It does not send them. Read the draft and tap Send when you are ready.
- Picking lines. A tap picks a line and a second tap lets it go. The lines can be far apart, and the note keeps them in file order, for example
+2, +10. Context, added and removed lines can be picked. A hunk header cannot. Clear (3) drops the whole pick. A pick belongs to one file and to one version of its diff. It does not carry to another file, and it clears when the diff changes under you. - A note on screen. A saved note shows as a pill under its last line, with the line numbers and the start of the text. Tap the pill to edit the text with Save comment, or to Delete it. A note whose lines the diff no longer holds shows at the end of the file's diff.
- The list. The Pending comments bar shows when nothing is picked. It opens the list of all notes with their file, lines and text, and each has Delete.
- Which agent. Opened from a pane, the notes go to that pane's agent. Opened from the dashboard's Files tab on a workspace with several agents, the list shows Target agent in this workspace, and you tap the agent that gets them. On a crew, an agent on another machine counts as its own agent, even when two machines share a pane id.
- No agent, no comments. The lines take a tap only when the pane is an agent's pane, or when the workspace has an agent pane. On a shell pane they do nothing.
The draft receives one block for each note, in the order you wrote them. Each block quotes the file and the lines with their +, - or space, and then your text.
> `src/cart.ts` (+12–13)
> + if (items.length === 0) return 0;
> + return total(items);
Handle the empty cart before the loop.The notes go after the text that is already in that pane's draft, with a blank line between. The draft keeps its attachments.
The batch stays when you leave. Back out of Changes and open it again in the same tab, or reload the page, and your notes are still there. They are kept for one pane, or for one workspace when you opened Changes from the dashboard. They do not outlive the tab, and ending a pairing clears them. Bringing the notes to the agent clears them too. A batch of more than 200 notes is not kept when you leave.
It stays up to date
An open Changes screen reads git again every 5 seconds while the page is visible. On a diff, the open file is read again too. A re-read that finds nothing new moves nothing on screen: your scroll, your filter and your folded folders stay as they are.
- A hidden page stops reading, and reads once when it is visible again.
- The refresh button reads now.
- If two reads in a row fail, the header says Not updating, and the last good list stays. The next good read clears it.
Which folder, and which repos
The list covers the pane's workspace, not only the pane's own folder, so every pane in one workspace shows the same list. The header names the workspace, its folder and the branch the folder is on, when every pane in it agrees on one. Collie picks that folder in this order:
| Order | Folder |
|---|---|
| 1 | The workspace's own folder, when the multiplexer keeps one: Herdr's worktree, tmux's session folder |
| 2 | The deepest folder that holds every pane of the workspace |
| 3 | The pane's own folder, when the first two would be /, your home folder, or above it |
Collie then finds the repo that holds that folder. It also looks for repos in folders below it, even repos the parent repo ignores. That is how a workspace repo with its member repos ignored inside it still shows every member's changes.
Two per-device settings control that search. Both live in Settings → Device → Changes.
| Setting | Default | What it does |
|---|---|---|
| Look for repos inside this folder | on | Also lists repos in folders below the workspace folder, even ones the parent repo ignores |
| How deep to look | 2 | How many folder levels below the workspace folder the search goes, 1 to 4 |
The search never follows a symlink. It skips dot-folders and node_modules, dist, build, vendor and target. It stops at 20 repos or 5000 folder entries.
When the search stops at its depth and there are repos further down, the list ends with "Stopped at 2 levels, with repos further down." and a Look deeper in Settings link. When it hits the repo or entry limit, the list ends with "The list hit a limit" instead, because files may be missing.
A submodule or a nested repo that the search finds shows once, as its own repo. A submodule below the depth shows as one entry in its parent repo.
Files
Files opens on the folder it reads, one folder at a time, with the changes marked on them. The header says Files on every level, with the workspace and its folder under it. It needs no git repository, so it works for a shell pane in any folder too. Inside a repository it also knows which entries git ignores, and hides them for you.
- A changed file shows its status letter, and its icon changes shape and takes the same colour: a pen for a changed file, a plus for a new one, a minus for a deleted one. A new file that git does not track yet counts as changed, and shows in the same green as an added file.
- A folder with changes inside it shows a dot and the number of changed files.
- A deleted file stays in its folder, struck through, with a D. Tap it to see what was removed.
- A folder outside every repository has no marks.
Tap a folder to open it and a file to read it. The path above the rows is a breadcrumb, and each folder in it is a link. The back arrow goes up one level: from a file to its folder, from a folder to the one above, and from the top to wherever Files was opened from. On a phone the same Back also stands at the foot of the screen, on the side of your thumb, so you reach it with one hand: the right end, or the left end with the left-hand layout.
The All files | Changes control
A two-part control sits directly under the header, in every folder. It looks like the Diff | Source | Preview control on a file. All files shows the folder with the changes marked. Changes shows the list of changes alone, grouped by repository, and carries the number of changed files in a small badge on its corner. The badge is not drawn when nothing changed. Your choice stays on this device, and All files is on at first.
The list starts with a line that names the root folder on the left and the added and removed line totals on the right. The header has a Tree button, which draws the changed files as a folder tree, a Filter button, and a refresh button. Refresh reads the list and the folder again.
One file
A changed file opens on its Diff, with Source and, for some types, Preview one tap away. A file that did not change opens on its source or its preview. A deleted file has only its diff, and a new file shows as all added.
Source is numbered and coloured up to 2000 lines and plain above that. A picture is drawn (below). Any other binary file shows its size and nothing else. A file over the size limit shows its first part and says so. A symlink shows as a link row and opens like a file.
Markdown, JSON, HTML and SVG files open on a Preview when they did not change.
| File | Preview |
|---|---|
.md, .markdown | Formatted text. Raw HTML in the file stays as text. |
.json | A tree. The first two levels are open and a folded node shows its count. |
.html, .htm | The page in a sandboxed frame on a white ground. |
.svg | The picture, drawn so it runs no script and loads nothing. |
Note. An HTML preview runs no scripts, sends no forms and loads no remote files. A link in the page does not open. Pictures stored inside the file as data: addresses still draw.Links in a Markdown preview work. A relative link opens that file or folder, a #heading link scrolls to the heading, and a web link opens in a new tab. A link that leaves the folder reads as plain text.
A PNG, JPEG, GIF, WebP or AVIF file opens as the picture. It fits the screen, sits on a checkerboard that shows transparency, and has its size and type under it. A picture has no Source.
Collie reads the type from the file's bytes, not its name. A file that is not really a picture, or one over 16 MiB, shows its size and the reason instead.
A Markdown preview draws the pictures the file names by a relative path, the first 20 of them. A picture on the web, or outside the folder, shows its description text.
A JSON file that does not parse shows the error and its source. A tree is not drawn above 5000 values, and the source shows instead.
In Changes, a changed file whose type has a preview, and that is not deleted, shows a Preview button in the header of its diff. It opens the same file screen on Preview.
Paths the agent prints
A file path the agent prints in Chat or in the terminal mirror is a link to that file in Files. src/app.ts:42 opens the file on its Source at line 42, with that line marked. Chat draws the path as an underlined code chip, and the path on an Edit or a Read card works the same way.
A path is a link only when it leads inside the workspace's folder, the folder Files reads, and a file or a folder is there. A path outside it, a web address, and a path the terminal broke across two lines stay plain text.
Collie asks the bridge which printed paths exist, many in one request, and the bridge reads no file to answer. A path stays plain text until the answer comes, and for as long as the view is open when the answer is no. Offline, and on a crew member's pane, no path is a link.
A folder or a file is read when you open it, and again when you tap refresh. It never updates on a timer. The change marks follow the list of changes, which updates every 5 seconds while you look.
Ignored files and the filter
Files hides what git ignores, such as node_modules, build output and logs. A quiet line under the list says how many rows are hidden, with a Show action. That line is the switch: once the ignored rows are shown, it says how many are shown and offers Hide. Your choice stays on this device. The Filter button opens a row with a name field and a toggle with its state in words, Ignored hidden or Ignored shown, which makes the same choice. The name field narrows the current folder to the names that hold your text, in any case, and the button shows how many rows are left. The name filter clears when you open another folder. Ignored rows show in a dimmer ink and open like any other row.
- Collie asks git once for each folder it lists, and git's own rules decide. A tracked file is never ignored, even when an ignore rule matches its name.
- Everything inside an ignored folder is ignored too. A repository cloned inside the workspace folder answers by its own rules.
- With no repository, no git, or a git that does not answer within 2 seconds, nothing is hidden and the list still shows.
- This is a filter and not a lock. An ignored file still opens, and a request for it is answered like any other.
Who may use it
- Files needs an authorised device, the same check as typing into a pane. A device must be paired (Security), and with
COLLIE_DEVICE_HEADERset it must also be onCOLLIE_DEVICE_ALLOWLIST. - Every paired device can use Files. It can browse the workspace's folder and read any file in it,
.envfiles included. - Changes is open to any paired device, because it shows only what changed.
What it shows, and what it never shows
- Only files under the workspace's folder. A path that leads out of it, also through a symlink, is refused. A symlink is listed as a link and opens only when it points inside the folder.
- Never a
.gitfolder, and never Collie's own state folder or config folder, also when they sit inside the workspace's folder. They are left out of the list, and a request for them is refused. - Never a file named like a Collie state secret, such as
paired-devices.jsonorcrew-trust.json, wherever it sits. This hides the secrets of a second Collie on the same machine. - Dot-files such as
.envare shown. They are your own files. This includes the.envof a second Collie when the folder holds its config folder. - Credential files are shown. A workspace opened in
~/.claude,~/.codex,~/.config/ghor~/.sshshows the files there, keys and tokens included. - A hard link is not caught. A hard link inside the folder to a file outside it opens like any other file in the folder.
- A refused file gets the same answer as a missing one.
Limits
- 2000 entries per folder. A larger folder shows its first 2000 and says it was cut.
- 1 MiB per file. A larger file shows its first 1 MiB and says it was cut.
- 16 MiB per picture. A larger picture shows its size and says it is too large.
- Binary files show no text. A file with a NUL byte in its first 8000 bytes counts as binary, git's own rule.
- No folder, no files. A workspace whose folder is your home folder, a folder above it, or
/shows no folder. Files says so and offers Show changes when it still has a list of changes. A pane on zellij older than 0.44 has no Files button. A workspace folder that is a symlink to one of those counts as that folder.
The full rules are in ADR 0083.
Read-only and safe
Changes runs git to read, and nothing else.
- It never stages, commits, edits or checks out. It does not even refresh git's index cache.
- A repo's own hooks, filters, external diff programs and text conversions never run while Collie reads it. An agent may have cloned anything, and you only tapped Changes.
- It never touches the network, not even to fetch a missing file in a partial clone. That file then shows with zero counts and an empty diff.
- A diff is served only for a file git itself listed as changed, in a repo the search found.
The full rules are in ADR 0065.
Across a crew
In a crew, a pane or workspace on another machine is read on that machine. The lead forwards the request, and that machine's git answers. That machine must run Collie 1.13.0 or later. Files reads that machine's own disk, under that machine's own device rules, and needs Collie 1.17.0 or later there. A member that is older, or one whose git does not answer, sends no ignored marks, so Files hides nothing for it.
Limits
- zellij before 0.44 reports no pane folder. On those versions zellij panes have no Files button and show no branch. zellij 0.44 and later reports the folder, and tmux always does. A zellij workspace has no folder of its own on any version, so its dashboard row reads "No folder".
- Git must be installed on the machine that owns the pane.
- Git LFS files may show as modified. With filters off, Collie compares an LFS file with its pointer. It can only show too much, never hide a change.
- One workspace, one folder. A workspace whose panes sit in unrelated folders under your home folder reads the asking pane's own folder instead of a merged view.