Skip to content

Add smart scope detection for aitools update and uninstall#4923

Open
simonfaltum wants to merge 7 commits intomainfrom
simonfaltum/aitools-scope-detection
Open

Add smart scope detection for aitools update and uninstall#4923
simonfaltum wants to merge 7 commits intomainfrom
simonfaltum/aitools-scope-detection

Conversation

@simonfaltum
Copy link
Copy Markdown
Member

Why

When running aitools update or uninstall without --project/--global, the CLI defaults to global scope regardless of what's actually installed. If a user only has project-scoped skills, update says "no skills installed" instead of detecting and updating the project install. There's no detection of what's present on disk.

Changes

Before: update and uninstall always defaulted to global scope when no flag was passed. --project --global together was an error.

Now: both commands auto-detect which scopes have installations and behave accordingly:

  • No flags, one scope installed: auto-selects that scope
  • No flags, both scopes installed, interactive: prompts the user to choose
  • No flags, both scopes installed, non-interactive: errors with guidance on which flags to use
  • --project --global on update: updates both installed scopes (ignores uninstalled ones)
  • --project --global on uninstall: always errors (safety, prevents accidental full removal)
  • Explicit flag pointing to non-existent install: detailed error with CWD guidance (project) or install hint (global), plus cross-scope hints when the other scope is installed

The implementation adds detectInstalledScopes, resolveScopeForUpdate, and resolveScopeForUninstall to scope.go. The existing resolveScope/resolveScopeWithPrompt used by install are untouched. Legacy installs (skills on disk without .state.json) still get the installer layer's migration guidance.

Test plan

  • Added 35 tests in scope_test.go covering all branches of scope detection and resolution
  • Tests cover: all 4 scope detection combinations, both-flags behavior, single-flag with/without state, no-flags auto-detection, interactive vs non-interactive, cross-scope error hints, legacy fallthrough
  • go test ./experimental/aitools/cmd/... -count=1 passes
  • make checks passes

update and uninstall previously defaulted to global scope when no flag
was passed, causing confusing "no skills installed" errors for users
with project-only installations. Now both commands auto-detect which
scopes have installations and behave accordingly:

- Single scope installed: auto-select it
- Both scopes + interactive: prompt the user (update offers 3 options
  including "both", uninstall offers 2)
- Both scopes + non-interactive: error with flag guidance
- Explicit flag pointing to empty scope: helpful error with CWD guidance

update also supports --global --project together to update both scopes
in one invocation.

Co-authored-by: Isaac
Address code review findings for the aitools scope detection feature:

- Both flags (--project --global) on update now check installed scopes
  instead of blindly returning both, matching the design truth table
- No-flags default case falls through to global scope so the installer
  layer can detect legacy installs and provide migration guidance
- Expanded project-scope error with expected path and CWD guidance
- Added cross-scope hints (e.g. "Global skills are installed" when
  user passes --project but only global exists)
- Removed stale "(default)" from --global flag help text
- Handle os.Getwd error properly in scope error paths

Co-authored-by: Isaac
@simonfaltum simonfaltum requested review from a team and lennartkats-db as code owners April 9, 2026 09:36
Global scope with explicit --global flag now always passes through to
the installer layer, preserving legacy install detection and migration
guidance. Only project scope uses withExplicitScopeCheck (where CWD
guidance is useful). crossScopeHint now takes a verb parameter so
uninstall hints say "uninstall" instead of "update".

Co-authored-by: Isaac
Move directory resolution to the Cobra RunE boundary in update.go and
uninstall.go. Internal functions (detectInstalledScopes, crossScopeHint,
scopeNotInstalledError, withExplicitScopeCheck, resolveScopeForUpdate,
resolveScopeForUninstall) now take plain string/bool parameters instead
of reaching through context, env vars, or os.Getwd().

Tests no longer manipulate global state (t.Setenv, t.Chdir). They pass
directory paths directly. detectInstalledScopes, withExplicitScopeCheck,
and crossScopeHint tests are now table-driven.

Co-authored-by: Isaac
Fix scopeNotInstalledError building a doubled path by using projectDir
directly (it already points to the skills directory). Fix
resolveScopeForUpdate with both flags to only include scopes that are
actually installed, falling through to global only when neither is
installed (for legacy detection).

Co-authored-by: Isaac
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 9, 2026

Waiting for approval

Based on git history, these people are best suited to review:

  • @pietern -- recent work in experimental/aitools/cmd/

Eligible reviewers: @databricks/eng-apps-devex, @lennartkats-db

Suggestions based on git history. See OWNERS for ownership rules.

@simonfaltum simonfaltum requested review from MarioCadenas and removed request for a team and lennartkats-db April 9, 2026 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant