[3/5] Aitools: update, uninstall, and version commands#4812
Merged
simonfaltum merged 7 commits intomainfrom Mar 25, 2026
Merged
[3/5] Aitools: update, uninstall, and version commands#4812simonfaltum merged 7 commits intomainfrom
simonfaltum merged 7 commits intomainfrom
Conversation
This was referenced Mar 22, 2026
Merged
9 tasks
8d6f603 to
14680ad
Compare
14680ad to
2dd4a43
Compare
Suggested reviewersBased on git history of the changed files, these people are best suited to review:
Confidence: high Eligible reviewersBased on CODEOWNERS, these people or teams could also review: @databricks/eng-apps-devex, @lennartkats-db Suggestions based on git history of 11 changed files (3 scored). See CODEOWNERS for path-specific ownership rules. |
arsenyinfo
approved these changes
Mar 23, 2026
2dd4a43 to
7cc1b0c
Compare
7cc1b0c to
c917624
Compare
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 25, 2026
## PR Stack This is part of the aitools feature-complete initiative. PRs should be reviewed and merged in order. 1. **[1/5] State + release discovery + directory rename** (this PR) 2. [2/5] Install writes state + interactive agent selection (#4811) 3. [3/5] Update + uninstall + version commands (#4812) 4. [4/5] List improvements + command restructuring + flags (#4813) 5. [5/5] Project scope (--project/--global) (pending) Manifest v2 PR: (pending in databricks-agent-skills) ## Why The aitools skills installer has no state tracking. There's no record of what was installed, at what version, or when. This blocks every lifecycle command (update, uninstall, version). The manifest fetching logic is also hardcoded with no abstraction for testing. ## Changes Before: Skills install to `~/.databricks/agent-skills/` with no state file. `FetchManifest` is inlined in `installer.go` with a hardcoded ref and no way to mock it in tests. Now: - `InstallState` type with `LoadState`/`SaveState` (atomic write via temp+rename) for tracking installed skills, release ref, and timestamps - `ManifestSource` interface with `GitHubManifestSource`, separating manifest fetching from install logic. Enables test mocking. - `FetchLatestRelease` to discover newest release from GitHub API. Falls back to pinned ref on network failure. - v2 fields on `SkillMeta` (`Experimental`, `Description`, `MinCLIVer`) with omitempty for backward compat with v1 manifests - Canonical directory renamed from `.databricks/agent-skills` to `.databricks/aitools/skills` - Backward-compat check in `HasDatabricksSkillsInstalled` for the old path No behavior changes to existing commands except the directory path. ## Test plan - [x] `LoadState` returns nil, nil for nonexistent file - [x] `SaveState` + `LoadState` roundtrip preserves all fields including optional ones - [x] `SaveState` creates nested directories, writes trailing newline - [x] `LoadState` returns error for corrupt JSON - [x] `GlobalSkillsDir` resolves correctly - [x] `ProjectSkillsDir` returns ErrNotImplemented - [x] `HasDatabricksSkillsInstalled` detects legacy path - [x] All existing aitools tests still pass --------- Co-authored-by: Arseny Kravchenko <arsenyinfo@users.noreply.github.com>
3cee3a7 to
5f87b4a
Compare
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 25, 2026
…mpotent install (#4811) ## PR Stack 1. [1/5] State + release discovery + directory rename (#4810) 2. **[2/5] Install writes state + interactive agent selection** (this PR) 3. [3/5] Update + uninstall + version commands (#4812) 4. [4/5] List improvements + command restructuring + flags (#4813) 5. [5/5] Project scope (--project/--global) (pending) **Base**: `simonfaltum/aitools-pr1-state` (PR 1) ## Why Install currently has no state tracking, no filtering, and outputs every file download to the console. Users can't tell what version they have, and there's no way to install for specific agents. ## Changes Before: `skills install` downloads everything, prints every file, has no state, no filtering, no agent selection. Now: - `InstallSkillsForAgents(ctx, src, agents, opts)` as the core install function. `InstallAllSkills` becomes a thin wrapper (signature preserved for `cmd/apps/init.go` compat). - State written to `.state.json` after successful install. Merges with existing state (doesn't overwrite). - Idempotent: second install skips already-present skills with matching versions. - Experimental filtering: skip `experimental: true` skills by default. - `min_cli_version` enforcement: skip incompatible skills with warning (hard error for single-skill install). - Interactive agent selection via `charmbracelet/huh` multi-select. Skip prompt for 1 agent, all detected for non-interactive. - Legacy install detection: prints "reinstall" message when old install found without state. - Concise default output (2 lines). Per-file detail only at debug level. ## Test plan - [x] State created after install-all and install-single - [x] Experimental filtering (skip by default, include with flag) - [x] min_cli_version: warning for all, hard error for single - [x] Idempotent: skip same version, update changed - [x] Legacy detection with helpful message - [x] Interactive prompt for 2+ agents, skip for 1 - [x] Non-interactive: all detected, no prompt - [x] `InstallAllSkills` signature preserved - [x] Concise output, per-file at debug level
Adds three new commands to the aitools skill management: - `update`: Updates installed skills to latest release with --check (dry run), --force, and --no-new flags. Auto-adds new manifest skills by default. - `uninstall`: Removes all installed skills, symlinks from all registry agents, cleans orphaned symlinks, and deletes state file. - `version`: Shows installed version, skill count, staleness check against latest release. Co-authored-by: Isaac
…fety, output format - FetchLatestRelease returns (string, bool, error) so callers can distinguish real API responses from fallback defaults. Update and version commands use the authoritative flag to gate staleness checks. - Update now filters experimental and min_cli_version skills using the same logic as install. Warns when a skill is removed from the manifest. - Uninstall only removes symlinks pointing into the canonical skills dir, preserving user-managed directories and external symlinks. - FormatUpdateResult accepts a check flag to use "Would update" wording. - Version output matches the spec format (Databricks AI Tools header, skill count, staleness status on the same line). - Consistent "no install" messaging across update, uninstall, and version. - Added tests for removed-skill warning, experimental/min_cli_version filtering in update, check-mode output, and symlink-only uninstall. Co-authored-by: Isaac
Co-authored-by: Isaac
Co-authored-by: Isaac
After squash-merge of PR2, FetchLatestRelease was replaced with getSkillsRef. Export it as GetSkillsRef and update all PR3 code (update.go, version.go, tests) to use the config-based ref instead of the removed GitHub API release lookup. Co-authored-by: Isaac
c917624 to
0023f1b
Compare
Collaborator
|
Commit: 57711c5 |
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 26, 2026
…ude-experimental flags (#4813) ## PR Stack 1. [1/5] State + release discovery + directory rename (#4810) 2. [2/5] Install writes state + interactive agent selection (#4811) 3. [3/5] Update + uninstall + version commands (#4812) 4. **[4/5] List improvements + command restructuring + flags** (this PR) 5. [5/5] Project scope (--project/--global) (#4814) Manifest v2 PR: databricks/databricks-agent-skills#35 **Base**: `simonfaltum/aitools-pr3-lifecycle` (PR 3) ## Why Commands are nested under `skills` which burns namespace for future component types (hooks, etc.). There's no way to install specific skills, target specific agents from the CLI, or see installed status in the list output. ## Changes **New `list` command**: Table output with skill names, versions, installed status, `[experimental]` tags. Sorted alphabetically. Uses `tabwriter` for alignment. **Flat command structure**: `aitools install/update/uninstall/list/version` at the top level. Hidden `skills install` and `skills list` aliases for backward compat. **Flags**: - `--skills` (string, comma-separated) on install, update, uninstall: operate on specific skills - `--skills` (bool) on list, version: show detailed skills view - `--agents` (string, comma-separated) on install: target specific agents, validates against registry, skips interactive prompt - `--include-experimental` on install: include experimental skills **Selective uninstall**: `--skills` on uninstall removes only named skills, preserves state file with remaining. ## Test plan - [x] `install --skills`, `--agents`, `--include-experimental` flags work - [x] `--agents` validates against registry, errors on unknown - [x] `uninstall --skills` selective removal, state preserved - [x] `update --skills` selective update - [x] `list` shows detailed table - [x] `skills install` and `skills list` hidden aliases work (Execute path tested) - [x] `cmd/apps/init.go` integration preserved - [x] All lint checks pass
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 26, 2026
## PR Stack 1. [1/5] State + release discovery + directory rename (#4810) 2. [2/5] Install writes state + interactive agent selection (#4811) 3. [3/5] Update + uninstall + version commands (#4812) 4. [4/5] List improvements + command restructuring + flags (#4813) 5. **[5/5] Project scope (--project/--global)** (this PR) Manifest v2 PR: databricks/databricks-agent-skills#35 **Base**: `simonfaltum/aitools-pr4-restructure` (PR 4) ## Why Skills are currently global-only. Teams working on the same project can't share a curated set of skills via their repo. Project-scoped installation puts skills alongside the code, so they can be committed to git and shared. ## Changes Before: All skills install to `~/.databricks/aitools/skills/` (global only). Now: - `--project` flag on install, update, uninstall: operates on `<cwd>/.databricks/aitools/skills/` - `--global` flag: explicit global scope (default behavior) - `--global` + `--project` -> error - Interactive scope prompt on install (default: global). Uses `huh.NewSelect` in cmd layer. - Non-interactive defaults to global. - `SupportsProjectScope` field on `Agent` struct. Only Claude Code and Cursor support project scope. - Incompatible agents get a warning, not an error: "Skipped <agent>: does not support project-scoped skills." - Version shows both scopes when both exist. - State includes `scope: "project"` field for project installs. ## Test plan - [x] `--project` installs to cwd-relative directory - [x] `--global` + `--project` -> error - [x] No flag, interactive -> scope prompt shown, default is global - [x] No flag, non-interactive -> global (no prompt) - [x] Incompatible agents warned, not errored - [x] Symlinks only created for capable agents in project scope - [x] Version shows both scopes when both exist - [x] `SupportsProjectScope` set correctly for all 6 agents - [x] All lint checks pass
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.
PR Stack
Base:
simonfaltum/aitools-pr2-install(PR 2)Why
Users can install skills but can't update, uninstall, or check what version they have. These are core lifecycle gaps.
Changes
Three new commands, each small but grouped because they share patterns.
aitools update: Compares installed release against latest. Downloads changed skills. Flags:--check(dry run),--force(re-download),--no-new(don't auto-add new manifest skills). Authoritative release detection (distinguishes real API response from fallback). Applies experimental and min_cli_version filtering. Warns on skills removed from manifest.aitools uninstall: Removes skill directories from canonical location. Removes symlinks from ALL agent directories (full registry scan, not just detected). Cleans orphaned symlinks. Only removes symlinks pointing to canonical dir (safe for third-party skills). Deletes.state.jsonon success.aitools version: Shows installed version, skill count, last updated date. Best-effort staleness check against latest release. Graceful offline degradation. Suppresses staleness check whenDATABRICKS_SKILLS_REFis set.Test plan