You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(mods): add mods/ and the git-aware-file-explorer Claude Code mod - #109
Adds a new top-level mods/ area for client interface mods, its first mod, and a Mods section on the docs site.
The mod, git-aware-file-explorer, is a Claude Code Files pane that knows about git. It combines the workspace browser and the list of changes in one pane:
Branch bar: the current branch, lines added and deleted across all changes, and a changed-files count that toggles a changed-only view.
Tree: file icons, a status letter on each changed file, and a mark on every folder that holds a change. Ignored files are dimmed and deleted files struck through. A filter box narrows the tree by name.
Diff panel: shows the selected file's diff against HEAD with tinted added and deleted lines and per-file counts, or a preview for an unchanged file.
Scrolling: the branch bar, filter, tree and file panel share one native scrollbar and move together. A fixed header with independently scrolling tree and diff isn't possible yet: the desktop sends no pointer with wheel events, and a mod can't make a scrollable sub-region. That platform limit is tracked in Mod panes on desktop: support fixed, independently scrolling and resizable regions anthropics/claude-code#99449, and the docs page says so.
The pane rescans every few seconds and after each tool call that can change files.
Type of change
New agent definition
New or updated skill
MCP server configuration
Documentation improvement
Tool/configuration update
Behavioral baseline change
Bug fix / correction
Other: new mods/ artifact area with its first Claude Code mod
Changes made
mods/claude/git-aware-file-explorer/: the mod.
.claude-plugin/plugin.json: the manifest.
hooks/hooks.json and hooks/register.tsx: the hooks module.
types/index.d.ts: the state contract.
tsconfig.json: type-checking config.
tests/: pane and diff tests.
docs/mods/index.md: what a mod is, the Claude Code catalog, and how to load a mod folder.
docs/mods/git-aware-file-explorer.md: a lightweight overview page with install steps.
mkdocs.yml: a Mods nav section after Skills.
docs/harness/claudecode/index.md: a Mods section linking to the mod.
docs/index.md, README.md: Mods entries.
AGENTS.md:
mods/ added to the repository structure.
mods/ covered by documentation synchronization and the pre-commit validators.
A new "Adding a new mod" checklist.
There's no marketplace yet, so the mod loads with --plugin-dir or CLAUDE_CODE_PLUGIN_DIRS. Installing mods and skills through a Claude Code plugin marketplace is tracked in #108.
Checklist
mkdocs build --strict passes with no warnings
All fenced code blocks have a language specifier
All links resolve correctly
No hardcoded secrets or tokens
New pages added to mkdocs.yml nav
New skills follow the SKILL.md / README.md / QUICKREF.md structure (n/a: no skills changed)
Related docs updated in this same PR
Tested with
Claude Code 2.1.300, in the desktop app on macOS: drawing, selection, filter, the changed-only toggle, and diff tinting. Native scrolling of the tree and of changed-file diffs is smooth; the reworked unchanged-file preview still needs a desktop check.
claude plugin validate and claude plugin test (48 tests, terminal and desktop surfaces).
tsc with noUncheckedIndexedAccess.
python scripts/validate_artifact_sync.py, mkdocs build --clean --strict, and markdownlint on the changed docs.
A Files pane for the Claude desktop app that marries the file tree with git
status: changed files and the folders holding them are highlighted, a filter
and a changed-only view narrow the tree, and the selected file opens beside
the tree as a diff (or a preview when unchanged) that scrolls on its own.
Adds mods/claude/ as the home for Claude Code interface mods and records it
in the AGENTS.md repository structure.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-aware-file-explorer
- Full-width branch bar: branch on the left, +added/-deleted line totals and
the changed-files toggle on the right; refresh and collapse sit beside the filter.
- File panel header shows the file's own +/- counts.
- Diff drawn as tinted rows (light green/red with dark text), hunks separated.
- The wheel scrolls the diff while a file is open and the tree otherwise; the
branch bar and filter stay fixed. Line-by-line up/down buttons in the header.
- The desktop raises no wheel event for a window that cannot move, so the pane
keeps one row of room only where the tree or diff can still scroll.
- Idle rescans no longer redraw the pane.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…orer page
- docs/mods/index.md: what a mod is, the Claude Code catalog, and how to load
a mod folder (--plugin-dir or CLAUDE_CODE_PLUGIN_DIRS); no marketplace yet.
- docs/mods/git-aware-file-explorer.md: lightweight overview and install.
- Nav entry after Skills, a Mods section on the Claude Code harness page, and
entries on the home page and README.
- AGENTS.md: mods/ is now published and covered by documentation
synchronization, with an "Adding a new mod" checklist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…plorer
Outside a repository a filter drew candidates from the (always empty) change
list, so any filter showed no files. Walk the disk instead, breadth first and
bounded, skipping the same hidden entries as the tree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A filter listed files with ls-files --exclude-standard, which drops ignored
paths the plain tree shows dimmed. Add the scan's ignored entries to the
candidates; an ignored directory matches by its own path and is drawn closed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… capped
New files beyond the first 200, or over 512 KB, were skipped silently, so the
branch bar's added total read as exact when it was not. Record that in the
scan and draw the total with a trailing + (as in 99+), and say so on the docs page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The panel's scroll limit allowed half a viewport past the end, leaving blank
rows. Compute the furthest start that still shows the last line, counting the
separator rows between hunks, and use it for the wheel, the line buttons and
the spare row. The diff drawing now never overruns the panel's rows either.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AGENTS.md runs the sync validator for mods/ changes, but the script checked
only topologies, specialists and skills. It now checks that every mod's
manifest name matches its folder and that the mod has an overview page in the
nav, a row in docs/mods/index.md and an entry on its client's harness page.
Tests cover the three coverage failures; AGENTS.md's new-mod steps say to run it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 1: all seven inline threads were fixed (94b4592, b42a57e, a6d046d, a7e4024, 148505c), replied to, and resolved. Codex's security review found nothing.
Copilot's summary table also mentions two single-vote notes that were never posted as findings. No change for either:
Rename path handling:parseStatus reads the source path of a staged rename or copy from porcelain v1 -z output, and diffFor passes both paths to git diff -M HEAD, so a renamed file's diff includes the rename.
Tree scroll bounds: the tree moves down only by the rows ui.scroll reports as hidden below the window (contentRows - bodyRows, less the spacer rows), and never above row 0. It cannot scroll past either end.
Scans can overlap: the 5-second timer and every writer tool call invoke rescan without awaiting the previous scan, and lineTotals can take substantial time for up to 200 untracked files. Because there is no generation check or serialization, an older scan that finishes later can overwrite a newer filesystem state and leave the pane stale until another scan. Serialize/coalesce scans or discard results from superseded runs.
Clamp panel offset to panelLast after diff shrinkage
panelOffset is only clamped to the final diff line, not to panelLast, which is the actual furthest start that fits the viewport (including hunk separators). If the selected file shrinks during a rescan, the old offset can exceed panelLast; rendering then leaves blank rows below the diff. Clamp this to panelLast as the scroll handlers do.
This issue also appears on line 674 of the same file.
…alk limit
Outside a git repository the filter searches a breadth-first walk capped at
20000 files. A file past the cap was reported as "No matching files." with no
hint the search was partial. The walk now reports when it stopped early and
the tree says so.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…file-explorer
With no commits yet, the line totals added the staged and unstaged numstat
together, counting a line twice when it was staged and then edited again, and
the diff panel showed two diffs for one file. Both now compare the working
tree against the empty tree, which yields one diff, as HEAD does once a commit
exists.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The timer, tool calls and the refresh button each started a scan, and scans
could overlap; an older one finishing last overwrote newer results until the
next scan. A scan asked for while one runs now waits, and all such requests
fold into one scan after it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The diff and preview clamped their first line to the file's last line, not to
the last window that fills the panel. After the pane grew or the file shrank, a
scrolled panel showed a short tail with empty space below until the next
scroll. Both now clamp to that last full window.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 2 findings raised only in Copilot's review summary (no thread to reply on):
Overlapping scans (rescan): fixed in 558d0ed. Scans no longer overlap; a scan asked for while one runs is folded into a single scan after it. Covered by a pane test.
Panel offset clamped to the last line, not the last full window: fixed in e527df7. The diff and the preview now clamp their first line to panelLast. Covered by a pane test that grows the pane after scrolling.
Every render with a changed file open reruns git diff and reparses the entire output. The wheel and line buttons update panelOffset, which causes another render, so scrolling a large diff repeatedly invokes Git and can make the panel unresponsive. Load/cache the diff when the selected file or scan status changes and reuse it for scrolling.
The tsconfig extends .claude-plugin/types/tsconfig.json, which Claude Code
writes, git-ignored, when it loads the mod. On a clean checkout tsc failed with
no hint why. The config now says to load the mod once before running tsc.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… counts
A scan that found the same git status and line totals wrote nothing, so the
pane did not redraw: an edit from `bar` to `baz` (still +1 -1), or any change
outside a git repository, left the open diff, preview or tree stale. The scan
now carries the modification time and size of the open file, the open folders
and the changed files, so such an edit changes the scan and redraws the pane.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pull or checkout that left the status clean could add or remove tracked files in a closed
folder without changing the scan, so a filtered tree stayed stale. The scan now records the
commit HEAD names.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A preview read that failed was cached until the scan changed, and a file that became readable
again with the same time and size never did. While the open file's preview can't be read,
each scan's stamp now differs, so the pane redraws and reads it again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…explorer
git status names the original path after any rename or copy, including an unstaged one
(an intent-to-add file, ` R new\0old`). Only the staged column was checked, so the original
path was read as a record of its own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A file named with pathspec magic, such as `:(exclude)foo`, was read as a pathspec, so its
diff showed nothing or other files' changes. Every git call now runs with
--literal-pathspecs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ile-explorer
git reports a modified submodule's root as a changed path, but the disk lists it as a folder,
so pressing it only ever expanded it. For a folder that is itself a change, the name now
opens its diff and the chevron expands it; other folders are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
Diff recreated rename sources against HEAD
When git mv old new is followed by recreating and modifying old, porcelain reports a rename plus a separate untracked old record, as permitted by the Git status format. This path counts old wholly as added while the base numstat records only the rename: for a two-line source with one changed line, the pane reports +2 −0 instead of the filesystem's net +3 −1, and opening old likewise shows an addition rather than its diff against HEAD. Detect untracked paths that equal a rename's from path and compute the source modification and destination addition as a pair.
…plorer
git status output cut at 4 MiB and trimmed to its last NUL can end between a rename's target
and original path. The target was kept with an empty original and opened as an addition;
the incomplete record is now dropped, as the status is already marked a floor.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lorer
A failed listing of an open folder was cached with the tree until the scan changed, so a
folder that became listable again with the same time and size stayed "(unreadable)". While
the tree holds such a folder, each scan's stamp differs, so the pane redraws and lists it
again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When virtual is set for the changed-only view or a filter, buildRows does not inspect the filesystem and infers the entry type from whether the path contains /. A changed submodule is reported by Git as a single path such as src, so it is rendered as a file in these views; its chevron cannot expand it and pressing the name selects it rather than treating it as the changed folder supported by the normal tree. Preserve the directory/submodule kind for virtual rows (and add a regression test for changed-only/filter views).
…plorer
An untracked file that .gitattributes marks `binary` or `-diff` had its lines counted as
additions, though git counts none for it. One `git check-attr` call per scan now finds them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ile-explorer
A failed listing of the workspace root was discarded, so the tree looked empty and the
failure stayed cached across rescans. The tree now says "Can't read this folder." and
retries it on each scan, as it does for an open folder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A failed diff of the open file was cached until the scan changed, so one that would work again
with the file's status, time and size unchanged kept showing git's error. While it fails,
each scan's stamp now differs, so the pane redraws and runs it again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Unresolved moderate issues remain around catalog registration, generated-file ignoring, tree scrolling offsets, and submodule rendering.
No open issues 🎉
Review effort: Lite
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds a new top-level
mods/area for client interface mods, its first mod, and a Mods section on the docs site.The mod,
git-aware-file-explorer, is a Claude Code Files pane that knows about git. It combines the workspace browser and the list of changes in one pane:HEADwith tinted added and deleted lines and per-file counts, or a preview for an unchanged file.The pane rescans every few seconds and after each tool call that can change files.
Type of change
mods/artifact area with its first Claude Code modChanges made
mods/claude/git-aware-file-explorer/: the mod..claude-plugin/plugin.json: the manifest.hooks/hooks.jsonandhooks/register.tsx: the hooks module.types/index.d.ts: the state contract.tsconfig.json: type-checking config.tests/: pane and diff tests.docs/mods/index.md: what a mod is, the Claude Code catalog, and how to load a mod folder.docs/mods/git-aware-file-explorer.md: a lightweight overview page with install steps.mkdocs.yml: a Mods nav section after Skills.docs/harness/claudecode/index.md: a Mods section linking to the mod.docs/index.md,README.md: Mods entries.AGENTS.md:mods/added to the repository structure.mods/covered by documentation synchronization and the pre-commit validators.There's no marketplace yet, so the mod loads with
--plugin-dirorCLAUDE_CODE_PLUGIN_DIRS. Installing mods and skills through a Claude Code plugin marketplace is tracked in #108.Checklist
mkdocs build --strictpasses with no warningsmkdocs.ymlnavSKILL.md / README.md / QUICKREF.mdstructure (n/a: no skills changed)Tested with
claude plugin validateandclaude plugin test(48 tests, terminal and desktop surfaces).tscwithnoUncheckedIndexedAccess.python scripts/validate_artifact_sync.py,mkdocs build --clean --strict, and markdownlint on the changed docs.🤖 Generated with Claude Code