[2/5] Aitools: install writes state, interactive agent selection, idempotent install#4811
Merged
simonfaltum merged 8 commits intomainfrom Mar 25, 2026
Merged
Conversation
4 tasks
This was referenced Mar 22, 2026
Merged
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 5 changed files (4 scored). See CODEOWNERS for path-specific ownership rules. |
arsenyinfo
reviewed
Mar 23, 2026
arsenyinfo
approved these changes
Mar 24, 2026
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>
fde04db to
3cee3a7
Compare
…nstall Introduces the core InstallSkillsForAgents function that handles: - Fetching manifest via ManifestSource interface - Filtering experimental skills and enforcing min_cli_version - Idempotent install (skips already-installed skills at same version) - Legacy install detection (skills on disk without state file) - State persistence after successful install - Concise output (two lines: installing header + summary) Adds interactive agent selection in cmd/skills.go using huh multi-select when multiple agents are detected in an interactive terminal. Preserves InstallAllSkills signature (func(context.Context) error) for the cmd/apps/init.go callback. Co-authored-by: Isaac
… assertion - Fix --experimental -> --include-experimental in error message - Merge new skills into existing state instead of overwriting - Move FetchManifest log from Info to Debug for concise output - Handle singular/plural in Installed N skill(s) message - Assert min_cli_version skip warning appears in test output Co-authored-by: Isaac
Co-authored-by: Isaac
Co-authored-by: Isaac
…gacy guard, local copy - Make idempotency check agent-aware: verify every requested agent has the skill on disk before skipping, so adding a new agent triggers reinstall. - Add --experimental flag to skills install and top-level install commands (previously referenced in error message but missing from CLI). - Block targeted install (install <skill>) on legacy setups without state to prevent writing incomplete state that hides the legacy warning. - Remove redundant state reload: use single LoadState + in-place mutation. - Copy files locally from canonical dir instead of re-downloading for single-agent and symlink-fallback paths. - Add IncludeExperimental semantics comment on state field. - Fix misleading test comment and add NotContains assertion for unchanged skill. Co-authored-by: Isaac
Co-authored-by: Isaac
…ranch change Co-authored-by: Isaac
3cee3a7 to
5f87b4a
Compare
Collaborator
|
Commit: 3fbef89 |
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 25, 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** (this PR) 4. [4/5] List improvements + command restructuring + 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 - [x] Update: no state -> error, already up to date, version diff, check dry run, force, no-new, new skill auto-installed, removed skill warning - [x] Uninstall: removes dirs + symlinks, orphan cleanup, state deletion, no state -> error, missing dirs handled - [x] Version: installed/up-to-date, update available, not installed, offline graceful - [x] All lint checks pass
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-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 installdownloads everything, prints every file, has no state, no filtering, no agent selection.Now:
InstallSkillsForAgents(ctx, src, agents, opts)as the core install function.InstallAllSkillsbecomes a thin wrapper (signature preserved forcmd/apps/init.gocompat)..state.jsonafter successful install. Merges with existing state (doesn't overwrite).experimental: trueskills by default.min_cli_versionenforcement: skip incompatible skills with warning (hard error for single-skill install).charmbracelet/huhmulti-select. Skip prompt for 1 agent, all detected for non-interactive.Test plan
InstallAllSkillssignature preserved