Add user-local project icons#4401
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a substantial new feature (user-local project icons) with new UI components, settings schema, and server-side resolution logic. New features introducing new user-facing behavior and workflows warrant human review. You can customize Macroscope's approvability policy. Learn more. |
73ce479 to
2093b5b
Compare
81db661 to
8e65d17
Compare
804efc4 to
5c2c09c
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5c2c09c. Configure here.
| "remotes", | ||
| remoteEntries.sort(([left], [right]) => left.localeCompare(right)), | ||
| ]); | ||
| return `icons:${revisionSource.length}:${hashProjectFaviconRevision(revisionSource)}`; |
There was a problem hiding this comment.
Revision misses normalized workspace keys
Medium Severity
projectFaviconSettingsRevision only reads projectIcons[cwd], while asset issuance also checks the normalized workspace root and the raw request cwd. When the stored key differs from the UI cwd string, the server can serve a custom icon but the client omits revision, so cached favicon URLs may stay stale for minutes.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 5c2c09c. Configure here.
5c2c09c to
9759616
Compare


What Changed
projectIconsandprojectIconsByGitRemotemaps to the serversettings.json, keyed by workspace root or normalized repository identity.~/…), or project-relative. They overridet3.jsonand automatic favicon discovery without changing the repository.Why
Project icons are currently discovered from files committed to each repository. Personal project organization should not require adding app-specific assets or metadata to the project itself. Git-remote keys also make a dotfile-backed setting portable across devices and clone paths while retaining exact-path overrides for worktrees or exceptional clones.
UI Changes
Before — automatic folder icon:
After — right-clicking the Sidebar v2 thread icon exposes the action:
After — the dialog shows the configured external icon and the persistent settings file:
After — a second clone at a different path inherits the normalized git-remote icon:
Checklist
vp checkvp run typecheckvp test run packages/contracts/src/settings.test.ts packages/shared/src/serverSettings.test.ts apps/server/src/project/ProjectFaviconResolver.test.ts apps/server/src/assets/AssetAccess.test.ts apps/server/src/serverSettings.test.ts apps/web/src/components/ProjectIconSettings.test.tssettings.json, and a signed SVG asset outside the repository.github.com/pingdotgg/t3codeicon setting renders for two clones at different local paths.Note
Add user-local project icon configuration to the sidebar
projectIconsandprojectIconsByGitRemote.SidebarV2opens a context menu with 'Set/Change project icon...' that opens a dialog to enter a custom icon path (absolute, home-relative, or workspace-relative).ProjectFaviconResolvernow acceptscustomIconPathsand a newresolvemethod returns both the icon path and its source (custom-settingvsworkspace); home-relative paths (~) are expanded automatically.AssetAccess.issueAssetUrlfor project favicons now reads server settings and repository identity to issue v2project-iconclaims carrying an absolute path;resolveAssetvalidates the canonical path matches before serving the file.ProjectFaviconcomputes a revision token from settings and repository identity so cached URLs invalidate when icon settings change.project-faviconasset tokens continue to resolve via the old path, but new requests emit v2 tokens; mixed token versions may coexist during a transition period.Macroscope summarized 9759616.
Note
Medium Risk
Signed asset serving now allows explicit paths outside the workspace and uses a new claim version; implementation adds symlink/canonical-path guards but this is still security-sensitive file access tied to user settings.
Overview
Adds user-local project icons stored in server
settings.json(projectIconsby workspace root,projectIconsByGitRemoteby normalized git remote), with workspace overrides winning over remote keys and automatic repo discovery unchanged when no override applies.Server:
ProjectFaviconResolvergainscustomIconPathsand aresolveresult that tags icons ascustom-settingvsworkspace;AssetAccessloads settings and repository identity, signs v2project-icontokens with a canonical absolute path for configured icons outside the repo, and keeps v1project-faviconresolution for existing tokens. Resolve-time checks reject symlink escapes and post-sign path swaps.Contracts / shared: Settings schema,
projectIconUpdateatomic patches, andapplyProjectIconUpdate/applyServerSettingsPatchhandle scope switches and resets. Optionalrevisionon project-favicon asset requests andsettingsConfigPathon server config support cache busting and UI copy.Web:
ProjectFaviconhashes settings + repository key into a revision for asset URLs. New Project icon flows in classic sidebar context menu, Sidebar V2 project settings / favicon right-click, and a dialog or inline path field with “use for all clones” when a git remote is known.Reviewed by Cursor Bugbot for commit 9759616. Bugbot is set up for automated code reviews on this repo. Configure here.
Current combined-stack UI evidence (2026-07-24)
Captured from PR head
804efc44c5a8321667f51400b3c513af593cde82on upstream mainece05087a70e94efcd57441337fa1249559362ba, using combined integration4dd4cef40and package/nix/store/pf7fjqw8ykkdgayf3ywsbgxxp6wi1m42-t3code-0.0.29-patched-main-20260724.The settings capture shows an external SVG stored by normalized remote identity for every clone; the second capture shows the resulting custom tree icon in Sidebar V2 and the draft header. All names, remotes, paths, and assets are disposable seed data.