Skip to content

[3/5] Aitools: update, uninstall, and version commands#4812

Merged
simonfaltum merged 7 commits intomainfrom
simonfaltum/aitools-pr3-lifecycle
Mar 25, 2026
Merged

[3/5] Aitools: update, uninstall, and version commands#4812
simonfaltum merged 7 commits intomainfrom
simonfaltum/aitools-pr3-lifecycle

Conversation

@simonfaltum
Copy link
Copy Markdown
Member

@simonfaltum simonfaltum commented Mar 22, 2026

PR Stack

  1. [1/5] State + release discovery + directory rename ([1/5] Aitools: state tracking, manifest source, directory rename #4810)
  2. [2/5] Install writes state + interactive agent selection ([2/5] Aitools: install writes state, interactive agent selection, idempotent install #4811)
  3. [3/5] Update + uninstall + version commands (this PR)
  4. [4/5] List improvements + command restructuring + flags ([4/5] Aitools: list command, flat structure, --skills/--agents/--include-experimental flags #4813)
  5. [5/5] Project scope (--project/--global) (pending)

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.json on success.

aitools version: Shows installed version, skill count, last updated date. Best-effort staleness check against latest release. Graceful offline degradation. Suppresses staleness check when DATABRICKS_SKILLS_REF is set.

Test plan

  • Update: no state -> error, already up to date, version diff, check dry run, force, no-new, new skill auto-installed, removed skill warning
  • Uninstall: removes dirs + symlinks, orphan cleanup, state deletion, no state -> error, missing dirs handled
  • Version: installed/up-to-date, update available, not installed, offline graceful
  • All lint checks pass

@github-actions
Copy link
Copy Markdown

Suggested reviewers

Based on git history of the changed files, these people are best suited to review:

  • @arsenyinfo -- recent work in experimental/aitools/lib/installer/, experimental/aitools/cmd/

Confidence: high

Eligible reviewers

Based 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.

@simonfaltum simonfaltum force-pushed the simonfaltum/aitools-pr3-lifecycle branch from 2dd4a43 to 7cc1b0c Compare March 23, 2026 14:02
@simonfaltum simonfaltum force-pushed the simonfaltum/aitools-pr3-lifecycle branch from 7cc1b0c to c917624 Compare March 24, 2026 11:52
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>
@simonfaltum simonfaltum force-pushed the simonfaltum/aitools-pr2-install branch 2 times, most recently from 3cee3a7 to 5f87b4a Compare March 25, 2026 22:45
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
Base automatically changed from simonfaltum/aitools-pr2-install to main March 25, 2026 22:54
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
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
@simonfaltum simonfaltum force-pushed the simonfaltum/aitools-pr3-lifecycle branch from c917624 to 0023f1b Compare March 25, 2026 23:11
@simonfaltum simonfaltum enabled auto-merge March 25, 2026 23:12
@simonfaltum simonfaltum added this pull request to the merge queue Mar 25, 2026
Merged via the queue into main with commit 57711c5 Mar 25, 2026
15 checks passed
@simonfaltum simonfaltum deleted the simonfaltum/aitools-pr3-lifecycle branch March 25, 2026 23:22
@eng-dev-ecosystem-bot
Copy link
Copy Markdown
Collaborator

Commit: 57711c5

Run: 23569251655

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
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.

3 participants