Imported from DevDengChao/git-worktrees-4-idea (
AGENTS.md). Install upstream withnpx skills add DevDengChao/git-worktrees-4-idea. Copyright stays with the author.
Project Notes for Agents
- Follow
~/AGENTS.mdbefore working in this repository. - Check for
.mcp.jsonbefore starting; this repository currently has no project-level MCP config. - For Git Worktrees panel selection changes, keep single-target data keys (
CURRENT_REPOSITORY,SELECTED_WORKTREE) available only for exactly one selected row. UseSELECTED_WORKTREESwhen actions need to handle multiple selected worktree rows, and ignore repository header rows for bulk operations. - For Git Worktrees panel list context menus, resolve
GitWorktrees.ToolWindow.Popupto anActionGroupduring panel setup and install it with the directActionGroupPopupHandler.installPopupMenuoverload; the string-id overload can resolve tonullwhen the menu is invoked in the 2025.2 runtime. - The Git Worktrees panel now uses a table, not
JBList: UI robot tests should locateJBTable/JTable, and popup installation tests should install against a table-likeJComponent. - For the table panel, keep repository rows as grouping context only.
WorktreedisplaysWorktreeInfo.name;BranchdisplaysbranchName ?: "detached"; sort and filter are applied within each repository group. - Repository/root table rows can be collapsed or expanded only within the current
GitWorktreesPanelinstance. Double-click root rows to toggle them, single-click only the left chevron hit area to toggle them, keep single-click root text selecting only, keep double-click worktree rows opening that worktree, and keep the popup toggle action visible only for exactly one selected root row. - For Git Worktrees table Speed Search, install
TableSpeedSearchon theJBTable, return search text only for worktree rows, and use aColoredTableCellRendererplusSpeedSearchUtil.appendFragmentsForSpeedSearchfor visible match highlighting. Tests that assert the supply is installed before the popup is active should callSpeedSearchSupply.getSupply(table, true). - When adding interactive controls to the Git Worktrees table header, keep them inside a custom
JTableHeaderand set that same header as the scroll pane column header view. Do not null out the table header renderer; Swing'sBasicTableHeaderUIstill reads it for sizing. - When wrapping the Git Worktrees panel toolbar in another component to add right-side content, explicitly call
ActionToolbar.setOrientation(SwingConstants.HORIZONTAL)beforesetToolbar(...);SimpleToolWindowPanelonly auto-adjusts orientation when the toolbar component itself is the directActionToolbar. - For bulk worktree deletion, do not refresh the repository or synchronously clean leftover directories after every individual worktree/branch command. Batch Git operations first, refresh each affected repository once, and defer physical leftover cleanup when possible because Windows directory cleanup can dominate the perceived delete time.
- Deferred leftover directory cleanup after bulk deletion should not create another visible
Deleting WorktreeTask.Backgroundable; keep the user-visible delete task scoped to Git unregister/branch deletion, and run leftover file cleanup as best-effort pooled work with de-duplicated paths. - For single Git Log branch deletion that first removes a linked worktree, also run branch deletion before leftover directory cleanup. If
git worktree remove --forcereportsDirectory not emptyorFilename too longafter unregistering the worktree, defer the physical cleanup outside the visible delete task so the branch menu action does not appear stuck on Windows. Cleanup should use Windows long-path-safe IO for local absolute paths. - To open the Worktrees panel from the Git/Version Control tool window, register the entry action under
Vcs.Log.ToolWindow.TabActions.DropDownand have it create or select a closableContentinToolWindowId.VCS; keep the standaloneGit Worktreestool window only as a fallback. Keep the standaloneGitWorktreesToolWindowFactoryimplementation minimal and Java-based on the 2025.2 baseline; Kotlin implementations can emit verifier-sensitive default-method bridges such asisApplicable,isDoNotActivateOnStart,getAnchor,getIcon, andmanage. - For right-side helper text in IntelliJ action popup menus, set
ActionUtil.SECONDARY_TEXTon the actionPresentation; do not append spacing or suffixes into the main action text. - For checkout candidates in the Git Worktrees popup, keep actions visible when exactly one worktree row is selected. If checkout is not currently possible, disable the action, put the reason in
Presentation.description, and copy that reason onto the disabled menu item's Swing tooltip when the popup opens. - Do not register a separate
Checkout Hereaction in the Git Worktrees panel popup; keep the popup focused on repository expand/collapse plus the singleCheckoutcandidate, Open, Delete, and Refresh. - Checkout actions should stay available for a selected non-current worktree even when its branch name already matches the repository's current branch; Git can still surface useful status/errors with
checkout --ignore-other-worktrees, while hiding the action makes duplicate same-branch worktrees look unresponsive. - Checkout actions must queue checkout work in a background task through
GitWorktreesOperationsService.checkout*Async; do not rungit checkoutorGitRepository.update()synchronously from action handlers/EDT. If local changes require confirmation, show only the confirmation dialog on EDT, then run the force checkout in the background task. - For Git Log branch checkout/delete worktree-conflict handling on the 2025.2 baseline, install
ActionManager.replaceAction(...)wrappers forGit.CheckoutGroup,Git.BranchOperationGroup, and the single-refGit.Branchgroup at app startup and keep Git4Idea-native children as fallback. Do not subclassGitSingleCommitActionGroup/GitCheckoutActionGroup; they are Kotlininternalin this runtime. - Register
AppLifecycleListenerentries as a root-level<applicationListeners>block inplugin.xml, not inside<extensions defaultExtensionNs="com.intellij">. If it is nested under extensions, sandbox logs report an unresolvedcom.intellij.applicationListenersextension and startup action replacement will never run. - For
Git.Branchreplacement children, keep checkout/delete replacements asgit4idea.actions.ref.GitSingleRefActionsubclasses. Git4Idea wraps onlyGitSingleRefActionchildren withGitBranchActionWrapper, which is what providesGit.Selected.Ref,Git.Selected.Repository, andGit.Repositoriesin the Git Log branch-label menu. - For Git Log branch actions, do not match worktree-conflict branches only by visible menu text. Git4Idea may truncate or wrap branch labels, especially names with
/; prefer wrapped actionDataSnapshotProviderkeys (Git.Selected.Ref,Git.Selected.Repository,Git.Repositories) for branch operation actions, and native action fields such ashashOrRefNameas checkout fallback. - In the table, the left checkmark marks the current repository/worktree location by path. After checking out a linked worktree branch into the current repository location, the checkmark should remain on that current location row while its Branch column updates to the selected branch.
- Plugin logo files should live at
src/main/resources/META-INF/pluginIcon.svgand, when needed,pluginIcon_dark.svg; JetBrains expects 40x40 SVG icons there. Promotional variants and previews can live underdesign/plugin-icons/. - Marketing screenshots and bilingual promotional copy should live under
design/marketing/. Keep screenshots text-clean when possible, and put English + Chinese copy in the same Markdown file so README and Marketplace material stay reusable. - For Marketplace description screenshots that use
raw.githubusercontent.com, point URLs at the repository's actual default branch (masterin this repository), not an assumedmainbranch. Before release, validate each raw image URL with HTTP HEAD and expect200plusContent-Type: image/png. - Keep README and
design/marketing/promotional copy organized as a full English section first, then a full Chinese section. In README, keep the<!-- Plugin description -->block around the public user-facing description only, so Marketplace metadata includes the bilingual intro but not development commands. - For Marketplace releases, keep
gradle.propertiespluginVersion,CHANGELOG.md, the Git tag, and the GitHub Release title aligned as the same plain SemVer value, for example1.0.0without avprefix. Publish through the GitHub Release workflow using repository secrets; if JetBrains Marketplace rejects the first automated upload because the plugin is new, use the signed ZIP for the initial manual Marketplace upload. - Date-style release versions such as
2026.0509.0need the customchangelog.headerParserRegexinbuild.gradle.kts; the Gradle Changelog Plugin default SemVer parser rejects the zero-padded0509segment. - This machine may not expose
CERTIFICATE_CHAIN,PRIVATE_KEY, andPRIVATE_KEY_PASSWORDin the local shell. When those environment variables are absent, produce the signed ZIP through the GitHub Release workflow, which reads the repository secrets and uploadsbuild/distributions/*back to the GitHub Release. - If
verifyPluginappears stuck with low CPU while resolving verifier dependencies or remote repositories, stop the Gradle daemon and rerun it with Gradle offline mode after the IDE artifacts are cached: setJAVA_HOMEtoC:\Users\Admin\.jdks\jbr-21.0.10-1, setGRADLE_OPTS='-Xmx768m -Dorg.gradle.jvmargs=-Xmx768m', then run./gradlew.bat --offline --no-daemon verifyPlugin --console=plain. Do not pass--args="-offline"to this Gradle task on the current plugin setup; it can shift Plugin Verifier arguments so the plugin ZIP is parsed as an IDE directory. - On the first Marketplace upload, keep the signed ZIP available even if
publishPluginreturnsCannot find plugin; let the release workflow uploadbuild/distributions/*with--clobber, then fail the job so the GitHub Release asset can be used for the manual Marketplace "Add new plugin" flow. - When current
masterhas moved past the latest release tag and the task is a follow-up marketing/release refresh, compare current HEAD with the latest tag first, update README plusdesign/marketing/around user-visible plugin behavior, then bumpgradle.propertiesandCHANGELOG.mdto the next unused release version before building and verifying. - In
.github/workflows/build.yml, keepreleaseDraft.needslimited to jobs that actually exist, and skip draft creation whengh release view "$VERSION"already finds a release. Otherwise push checks can fail before any job logs exist, or fail after an already-published release tries to create a duplicate draft. - For Git branch menu actions across 2025.2/2025.3+ IDEs, do not statically reference the
GitSingleRefActionsholder class from one package. Use stableDataKey.create(...)names forGit.Selected.Ref,Git.Selected.Repository, andGit.Repositoriesinstead, and keep tests pinning those key names. - With IntelliJ Platform Gradle Plugin 2.16.0 / Plugin Verifier 1.403, delegated Git action wrappers must not call
ActionGroup.getChildren(e)directly; the verifier reportsOVERRIDE_ONLY_API_USAGES. Use the event update session, for examplee.updateSession.children(group), and give lightweightTestActionEventhelpers a minimalUpdateSessionimplementation when tests need to expand native groups. - Avoid Kotlin stdlib helpers that may compile to newer runtime overloads inside IntelliJ test actions, especially
sequenceOf(singleValue). Linux CI can load the IDE-bundled Kotlin stdlib before Gradle's test dependency and fail withNoSuchMethodError; prefer simple lists, arrays, or loops in action code that runs under the platform test harness. - For IntelliJ action data exposed by Swing panels, prefer
UiDataProvider.uiDataSnapshot(DataSink)over legacyDataProvider.getData(String); keep tests using a smallDataSinkhelper so production code does not reintroduce deprecatedUiCompatibleDataProvider.getData(String)usage. - For panel/action/service changes, run the targeted suite with:
./gradlew.bat test --tests dev.dengchao.idea.plugin.git.worktrees.GitWorktreesPanelTest --tests dev.dengchao.idea.plugin.git.worktrees.GitWorktreesActionsTest --tests dev.dengchao.idea.plugin.git.worktrees.GitWorktreesOperationsServiceTest - Before merging feature work, run
./gradlew.bat test.