feat: plugin scope management with multi-scope support#31
Merged
bojanrajkovic merged 20 commits intomainfrom Feb 15, 2026
Merged
feat: plugin scope management with multi-scope support#31bojanrajkovic merged 20 commits intomainfrom
bojanrajkovic merged 20 commits intomainfrom
Conversation
InstallPlugin() now shells out to 'claude plugin install' instead of 'enable' UninstallPlugin() now shells out to 'claude plugin uninstall' instead of 'disable' EnablePlugin() and DisablePlugin() remain unchanged with correct commands
Add GetAllEnabledPlugins and ScopeState type to read all three settings files (user, project, local) and accumulate scope sets per plugin ID. Missing settings files are handled gracefully. Each scope's bool value indicates enabled (true) or disabled-but-present (false).
Add comprehensive tests for GetAllEnabledPlugins covering all acceptance criteria: - AC2.1: User-scoped plugins from ~/.claude/settings.json - AC2.2: Project and local scopes from .claude/settings.json and .claude/settings.local.json - AC2.3: Missing files handled gracefully with empty result - AC2.4: Plugins appearing in multiple scopes return all scope entries - Additional test for disabled-but-present plugins All tests use temp directories and internal getAllEnabledPlugins for full coverage of all three scope paths.
Fix shadow variable warnings from golangci-lint by using assignment (err =) instead of short-form declaration (err :=) when reusing error variable in subsequent operations. This maintains the original error variable from the outer scope.
Change PluginState.InstalledScope to InstalledScopes map and Operation.Scope/OriginalScope to Scopes slice/OriginalScopes map. Add helper methods (IsInstalled, HasScope, IsSingleScope, SingleScope) to minimize churn at call sites. Update mergePlugins to use GetAllEnabledPlugins for settings-based scope detection. Remove dead GetProjectEnabledPlugins function. Add firstScope and copyMap helpers for scope map utilities. Verifies: - plugin-scope-mgmt.AC3.1: InstalledScopes maps accurately reflect all scopes - plugin-scope-mgmt.AC3.2: Helper methods work correctly for all scope configs - plugin-scope-mgmt.AC3.3: Operation.Scopes slice supports multi-scope operations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrate all test code to use new InstalledScopes map and Operation Scopes/OriginalScopes fields. Update assertions to use helper methods (IsInstalled, HasScope, SingleScope). Add new test TestPluginStateHelpers to verify all helper method combinations. Test coverage: - TestPluginStateHelpers: Verify IsInstalled, HasScope, IsSingleScope, SingleScope work for empty, single, and multi-scope cases - All existing tests updated and passing Verifies: - plugin-scope-mgmt.AC3.1: PluginStateFromInstalled/FromAvailable tests - plugin-scope-mgmt.AC3.2: New TestPluginStateHelpers test - plugin-scope-mgmt.AC3.3: Operation-related tests with new fields Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add scope formatting helpers: scopeOrder, scopeLabel, formatScopeSet for consistent formatting - Update getScopeIndicator to display multi-scope plugins (e.g., [USER, LOCAL]) - Update renderPendingIndicator to handle multi-scope operations with scope transitions - Handle OpScopeChange operation type in display functions - Update status text and pending change messages for multi-scope display - Update confirmation modal and progress display for multi-scope operations - Replace Unicode arrows with ASCII for consistency Verifies: plugin-scope-mgmt.AC4.1, plugin-scope-mgmt.AC4.2 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Modify WithDimensions() in styles.go to accommodate wider multi-scope indicators. The left pane now uses max(width/3-4, 25) to ensure a minimum width of 25 chars, which is sufficient for worst-case multi-scope displays like [USER, PROJECT, LOCAL]. Verifies plugin-scope-mgmt.AC4.3: Left pane width adjusts dynamically for longer scope indicators.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement Phase 5 of plugin scope management: - Add ModeScopeDialog mode constant for scope selection dialog - Add scopeDialogState struct to hold dialog UI state - Add openScopeDialog() helper to transition to scope dialog mode - Update selectForInstall() to branch on IsSingleScope() - Update selectForUninstall() to branch on IsSingleScope() - Update toggleEnablement() to branch on IsSingleScope() - Update toggleScope() (Tab key) to no-op on multi-scope plugins - Add minimal Update handler for ModeScopeDialog that allows Esc to exit Verifies AC5 acceptance criteria: - AC5.1: selectForInstall opens dialog for multi-scope, creates op for single-scope - AC5.2: selectForUninstall opens dialog for multi-scope, creates op for single-scope - AC5.3: toggleEnablement opens dialog for multi-scope, creates op for single-scope - AC5.4: toggleScope (Tab) is no-op for multi-scope, works for single-scope All tests pass (78 total, including 8 new multi-scope tests). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements Phase 6 scope dialog feature: - Task 1: Add S key binding for scope dialog (Shift+S) - Task 2: Implement full dialog input handler with up/down navigation, space toggle for checkboxes, Enter to apply delta, Esc to cancel - Task 3: Render dialog as centered overlay with scope names and settings file paths Changes: - Add Scope field to KeyBindings struct with S key binding - Add updateScopeDialog() to handle keyboard input in ModeScopeDialog mode - Add applyScopeDialogDelta() to compute delta and generate pending operations (OpInstall, OpUninstall, OpScopeChange) - Add renderScopeDialog() to display dialog with checkboxes, cursor, and file paths - Wire scope dialog into Update and View functions - Add openScopeDialogForSelected() helper method Verification: - AC6.1: S key opens dialog with pre-checked boxes for installed scopes - AC6.2: Space toggles checkbox, Enter applies changes, Esc cancels - AC6.3: Delta correctly produces OpInstall/OpUninstall/OpScopeChange - AC6.4: Dialog shows settings file paths for each scope - Comprehensive tests verify all functionality Test results: 15 new tests added, all passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement Phase 7 smart execution for multi-scope operations with settings-aware CLI command selection. Updates executeOperation() to loop over op.Scopes and choose the correct CLI command (install vs enable, uninstall vs disable) based on whether the plugin exists in the settings file. Changes: - executeOperation() now reads settings via GetAllEnabledPlugins() once at start - For OpInstall: calls EnablePlugin if plugin exists in settings, else InstallPlugin - For OpUninstall: calls UninstallPlugin if plugin exists, else DisablePlugin - All multi-scope operations loop over scopes and stop on first error - Error messages include the failing scope name for better debugging - OpScopeChange now integrated into operation sort order (after OpMigrate) - startExecution() sort order updated: Uninstall(0), Migrate(1), ScopeChange(2), Update(3), Install(4), Enable(5), Disable(6) Verifies plugin-scope-mgmt.AC7: - AC7.1: Smart install selection (enable vs install) - AC7.2: Smart uninstall selection (uninstall vs disable) - AC7.3: Multi-scope error handling with scope reporting - AC7.4: Operation ordering maintained with OpScopeChange Tests added: - TestExecuteOperationInstallWhenNotInSettings: AC7.1 - InstallPlugin path - TestExecuteOperationInstallWhenInSettings: AC7.1 - EnablePlugin path - TestExecuteOperationUninstallWhenInSettings: AC7.2 - UninstallPlugin path - TestExecuteOperationMultiScopeStopsOnFirstError: AC7.3 - Error handling - TestStartExecutionOperationOrdering: AC7.4 - Operation sort order Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reuse the allScopes/pluginScopes variables already read at the top of executeOperation instead of reading settings again. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update CLAUDE.md files to reflect multi-scope plugin support: - TUI now uses InstalledScopes map instead of single InstalledScope - Operation.Scopes replaces Operation.Scope for multi-scope targets - New OpScopeChange operation type and ModeScopeDialog mode - Dependency on GetAllEnabledPlugins (replaces GetProjectEnabledPlugins) - S key binding for scope dialog documented Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cator, and minimum left pane width Add comprehensive tests for three acceptance criteria: - AC4.1: formatScopeSet tests - TestFormatScopeSet_SingleScope: Verifies single scope output (e.g., "USER") - TestFormatScopeSet_MultiScope: Verifies multi-scope output (e.g., "USER, LOCAL") - TestFormatScopeSet_Ordering: Verifies canonical ordering (USER, PROJECT, LOCAL) - AC4.2: renderPendingIndicator tests - TestRenderPendingIndicator_PartialUninstall: Verifies partial uninstall transition display - TestRenderPendingIndicator_ScopeChange: Verifies scope change transition display - TestRenderPendingIndicator_MultiScopeInstall: Verifies multi-scope install display - AC4.3: Minimum left pane width test - TestWithDimensions_MinimumLeftPaneWidth: Verifies left pane width >= 25 on narrow terminals All tests verify actual behavior using text fragment matching for styled strings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
Author
Test Plan
Full human test plan: |
Extract helpers to reduce cyclomatic complexity in executeOperation, renderPendingIndicator, appendPendingChange, and renderProgress. Fix struct field alignment, unused test parameters, and if-else chain. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reorder Model struct fields for optimal GC pointer bitmap layout, reducing pointer bytes from 11040 to 11008. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract runPluginCommand() helper in client.go, reducing 4 identical CLI methods to one-liners delegating to a shared implementation - Add OperationType.meta() method centralizing display metadata (verb, noun, pending prefix) and simplify 4 switch statements in view.go - Add testModel() test helper reducing 4-line setup boilerplate across 19 test functions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
InstallPlugin/UninstallPluginto use correct CLI commands (install/uninstallinstead ofenable/disable)GetAllEnabledPlugins()to read all three settings files (user, project, local) for authoritative multi-scope detectionPluginStateandOperationstructs to support multiple scopes (InstalledScopesmap,Scopesslice)[USER, LOCAL]), details pane, and confirmation modall/p/u/e/Tabkeys context-aware: single-scope plugins get existing behavior, multi-scope opens scope dialogSkey scope dialog modal with checkbox UI for user/project/local, delta computation generatingOpInstall/OpUninstall/OpScopeChangeinstallvsenableanduninstallvsdisablebased on settings file state🤖 Generated with Claude Code