aitools: report plugin state in list and version#5741
Merged
Conversation
This was referenced Jun 26, 2026
4c63508 to
97b3066
Compare
73479ff to
09d6577
Compare
bradleyjamrozik-origindigital
pushed a commit
to bradleyjamrozik-origindigital/databricks-cli
that referenced
this pull request
Jun 26, 2026
…atabricks#5734) <!-- aitools-stack --> ### Stack Part of the `aitools` plugin-first redesign. Merge bottom to top: - **databricks#5734 Detection & registry (plugin metadata + capability detection) ← this PR** - databricks#5736 State schema v2 (plugin + file provenance records) - databricks#5737 Plugin engine, checksums, `--path` dump (library) - databricks#5738 Plugin-first install command - databricks#5739 Update + prune of vanished skills - databricks#5740 Uninstall teardown + legacy skills cleanup - databricks#5741 list + version plugin state <!-- /aitools-stack --> ## Why `databricks aitools` is being redesigned from a raw-skills installer into a plugin-first installer. The first thing that redesign needs is better agent detection: today an agent is "detected" only if its config dir exists on disk, which misses Codex and Copilot (often used through an IDE, or installed-but-not-yet-run), and the registry has no notion of which agents have a plugin or what their CLI binary is. This PR lays that foundation. It is deliberately behavior-neutral: no command output changes, and `DetectInstalled` still uses the same config-dir signal it does today. The picker and install rewrites that consume this come in later PRs in the stack. ## Changes Before: the agent registry only knew each agent's config dir; detection was a single `os.Stat` on that dir. Now: the registry also describes each agent's plugin and CLI binary, and there's a capability detector that can tell the difference between "binary on PATH" and "config dir exists." - `Agent.Binary` — the CLI binary name on PATH (`claude`, `codex`, `copilot`, `cursor-agent`, `opencode`; empty for IDE-only Antigravity). Cursor's binary is `cursor-agent`, not `cursor` (the latter is an IDE shim that isn't on PATH). - `Agent.Plugin *PluginSpec` — describes the databricks plugin. `Plugin != nil` means the agent has a plugin (Claude, Codex, Copilot, Cursor); `nil` means raw skills are the only delivery (OpenCode, Antigravity). `ManualOnly` marks Cursor (plugin exists, but no headless install path). - OpenCode config dir is now per-OS: `%APPDATA%\opencode` on Windows, and honors `XDG_CONFIG_HOME` otherwise (defaulting to `~/.config/opencode`). The previous hardcoded path made OpenCode undetectable on Windows and ignored `XDG_CONFIG_HOME` on Linux. - New `detect.go`: `HasBinary` (via `exec.LookPath`), `DisplayState` (a 5-state enum for the picker, computed from the two cheap signals without running the agent), `Preselect`, and `ProbePlugin` (runs `<agent> plugin --help` with a 5s timeout through `libs/process`; refuses a cwd-relative binary via `exec.ErrDot` so a malicious `./claude` is never executed). ## Test plan - [x] Unit tests (`detect_test.go`): `HasBinary`, `DisplayState` across all five states, `Preselect` rules, `ProbePlugin` (supported / CLI reports unsupported / binary not on PATH / refuses dot-relative binary with zero executions), and `openCodeConfigDir` (XDG honored / `~/.config` default; Windows APPDATA branch on Windows hosts). - [x] `go test ./libs/aitools/... ./cmd/aitools/...` passes (no behavior change to existing commands). - [x] `./task fmt-q`, `./task lint-q` (0 issues), `./task checks` (no dead code) all clean. This pull request and its description were written by Isaac.
97b3066 to
07b7afa
Compare
09d6577 to
821ac03
Compare
07b7afa to
e656bad
Compare
821ac03 to
2ac9769
Compare
Merged
4 tasks
…install - uninstall now tears down plugins: for each agent in state.Plugins (full uninstall only), it removes the plugin through the agent's own CLI and de-registers the marketplace, but only when this CLI registered it and --keep-marketplace wasn't passed. Skills teardown is unchanged for file agents; the state file is removed only when no skills and no plugins remain. - install now cleans up legacy raw skills on a plugin agent (RemoveLegacyRawSkills): after installing the plugin we remove skill dirs we previously dropped there (a symlink into our canonical dir, or a copy whose files all match recorded checksums), so the plugin and leftover files don't surface the same skills twice. User-modified or third-party dirs, and copies with no recorded provenance, are left untouched. Co-authored-by: Isaac
The merge of the install-command review fix (which removed log from selectAgents) crossed with this branch's cleanup log.Debugf usage; re-add the import. Co-authored-by: Isaac
…s, marketplace) Address cursor review of uninstall + cleanup: - RemoveLegacyRawSkills now reuses the exact-match exposureRemovable/ dirMatchesRecords helpers from update, so a copied skill dir with an extra user-added file is no longer deleted (and the duplicated checksum logic is removed). Test covers the extra-file keep case. - Uninstall no longer drops the state record for an unknown agent without tearing it down; it warns and keeps the record (and the state file). - UninstallPluginForAgent now only returns an error when the plugin itself can't be removed. A marketplace de-register failure after a successful plugin uninstall is warned about (not fatal), so the plugin record is cleared and a retry isn't stuck repeating the plugin uninstall. Co-authored-by: Isaac
e656bad to
7014345
Compare
- list --output json gains an additive agents[] array: each plugin agent with a recorded install (version + up_to_date/update_available status, managed=true) plus Cursor as manual_add_plugin (managed=false) when present. The existing release/skills/summary keys and shapes are byte-identical. The text view adds an AGENT/STATUS block only when there are agent entries, leaving the skills table and summary line unchanged. - version prints a "Plugin (<Agent>): vX" line per recorded plugin and only prints the skills line when skills are installed, so a plugin-only install no longer reports "0 skills". Existing skills output is unchanged. Co-authored-by: Isaac
Address cursor review: buildAgentEntries returned the first scope's record, so a stale project-scoped plugin could be hidden behind an up-to-date global one. Now status aggregates across scopes (any out-of-date scope reports update_available) and version reflects the record that set the status. Test covers the dual-scope case. Co-authored-by: Isaac
2ac9769 to
837a7ad
Compare
3 tasks
bradleyjamrozik-origindigital
pushed a commit
to bradleyjamrozik-origindigital/databricks-cli
that referenced
this pull request
Jun 27, 2026
…ks#5736) <!-- aitools-stack --> ### Stack Part of the `aitools` plugin-first redesign. Merge bottom to top: - databricks#5734 Detection & registry (plugin metadata + capability detection) - **databricks#5736 State schema v2 (plugin + file provenance records) ← this PR** - databricks#5737 Plugin engine, checksums, `--path` dump (library) - databricks#5738 Plugin-first install command - databricks#5739 Update + prune of vanished skills - databricks#5740 Uninstall teardown + legacy skills cleanup - databricks#5741 list + version plugin state <!-- /aitools-stack --> ## Why The plugin-first `aitools` redesign needs `.state.json` to record two new things: which plugins we installed through each agent's own CLI (so `update`/`uninstall`/`list` act on exactly where we installed), and provenance for the skill files we wrote (so a later `update` can prune a skill that vanished from the release only when the user hasn't modified it). This PR adds that schema, additively, ahead of the install/update/uninstall changes that consume it. Stacked on databricks#5734 (detection foundation). ## Changes Before: `InstallState` tracked only `skills`/`repo_dirs` (schema v1). Now: schema v2 adds two optional maps, and existing state migrates forward transparently. - `PluginRecord` (in `InstallState.Plugins`, keyed by agent name): marketplace, plugin id, agent-native scope, last-seen version, and `installed_marketplace` (whether this CLI registered the marketplace, so uninstall knows if it may de-register it). - `FileRecord` (in `InstallState.Files`, keyed by canonical-relative path like `databricks/SKILL.md`): per-file `sha256` + `origin` ref. - Both maps are `json:",omitempty"`, so a files-only install serializes byte-identically to today. - `LoadState` runs `migrateState`: forward-only and idempotent. v1 → v2 needs no data transformation (the maps are additive and optional), so it only stamps the version; writers lazily initialize the maps the same way `RepoDirs` is handled. - The fresh-install writer now stamps v2 so the on-disk and in-memory versions agree. ## Test plan - [x] Unit tests: v1→v2 migration is additive (existing skills untouched, new maps nil), migration is idempotent, and a state with populated `Plugins`/`Files` round-trips through save/load. Existing round-trip fixtures updated to v2. - [x] `go test ./libs/aitools/... ./cmd/aitools/...` passes. - [x] `go test ./acceptance -run TestAccept/experimental/aitools` passes (`.state.json` is in `Ignore`, so the version bump doesn't touch goldens). - [x] `./task fmt-q`, `./task lint-q` (0 issues), `./task checks` (no dead code) clean. This pull request and its description were written by Isaac.
bradleyjamrozik-origindigital
pushed a commit
to bradleyjamrozik-origindigital/databricks-cli
that referenced
this pull request
Jun 27, 2026
…tabricks#5737) <!-- aitools-stack --> ### Stack Part of the `aitools` plugin-first redesign. Merge bottom to top: - databricks#5734 Detection & registry (plugin metadata + capability detection) - databricks#5736 State schema v2 (plugin + file provenance records) - **databricks#5737 Plugin engine, checksums, `--path` dump (library) ← this PR** - databricks#5738 Plugin-first install command - databricks#5739 Update + prune of vanished skills - databricks#5740 Uninstall teardown + legacy skills cleanup - databricks#5741 list + version plugin state <!-- /aitools-stack --> ## Why The plugin-first redesign installs the databricks plugin by driving each agent's own plugin CLI (`claude plugin install`, etc.), and on `update` it needs to be able to prune a skill that vanished from a release without clobbering files the user edited. This PR adds the library layer for both, with no command wiring yet, so the engine can be reviewed and unit-tested on its own. The install/update/uninstall commands call into it in later PRs. Stacked on databricks#5736 (state schema v2). ## Changes - `plugin.go` — the plugin engine. It drives each agent's CLI through `libs/process` (so tests mock it with `process.WithStub`): - `InstallPluginForAgent` registers the marketplace and installs the plugin, recording whether *we* added the marketplace. - `UpdatePluginForAgent` runs the per-agent update (Codex's two-step `marketplace upgrade` then `plugin add` is encoded). - `UninstallPluginForAgent` removes the plugin and de-registers the marketplace **only** when this CLI registered it and `--keep-marketplace` wasn't set — never a marketplace another plugin may share. - Argv is built per agent (Codex uses `plugin add`; Claude is the only `--scope` agent) and run by absolute path; a cwd-relative binary (`exec.ErrDot`) is refused, never executed. - A blocked operation returns a typed `*BlockedError` (`CLINotOnPath` / `InstallFailed` / `ManualOnly`), so the command layer can report it and decide skip-vs-fail — it never silently falls back to skills. The agent's own stderr is surfaced via `errors.AsType`, never string-matched. - `installer.go` — `installSkillToDir` now records a sha256 `FileRecord` per file it writes (origin = ref); `InstallSkillsForAgents` and `UpdateSkills` persist these to `state.Files` for the prune safeguard. The symlink-vs-copy rules are unchanged. - `dump.go` — `DumpSkillsToPath`, a dumb `--path` dump (no agents, no `.state.json`, no lifecycle) that reuses the existing manifest/resolve/fetch path. ## Test plan - [x] `plugin_test.go` via `process.WithStub` + injected `lookPath`: Claude success (marketplace add + `--scope user` install), Codex uses `plugin add` with no `--scope`, manual-only (Cursor) → `ManualOnly`, CLI-not-on-path → `CLINotOnPath` with zero executions, install failure → `InstallFailed` surfacing stderr verbatim, marketplace-already-present leaves `InstalledMarketplace=false`, Codex two-step update, marketplace de-register only when we installed it and `--keep-marketplace` honored. - [x] `dump_test.go`: writes files, writes no state, honors `--skills` cherry-pick. - [x] `installer_test.go`: install captures file checksums into `state.Files`. - [x] `go test ./libs/aitools/... ./cmd/aitools/...` and `go test ./acceptance -run TestAccept/experimental/aitools` pass. - [x] `./task fmt-q`, `./task lint-q` (0 issues), `./task checks` (no dead code — engine funcs are reachable via tests until the command layer lands) clean. This pull request and its description were written by Isaac.
bradleyjamrozik-origindigital
pushed a commit
to bradleyjamrozik-origindigital/databricks-cli
that referenced
this pull request
Jun 27, 2026
…-only) (databricks#5738) <!-- aitools-stack --> ### Stack Part of the `aitools` plugin-first redesign. Merge bottom to top: - databricks#5734 Detection & registry (plugin metadata + capability detection) - databricks#5736 State schema v2 (plugin + file provenance records) - databricks#5737 Plugin engine, checksums, `--path` dump (library) - **databricks#5738 Plugin-first install command ← this PR** - databricks#5739 Update + prune of vanished skills - databricks#5740 Uninstall teardown + legacy skills cleanup - databricks#5741 list + version plugin state <!-- /aitools-stack --> ## Why This is the user-visible flip of the `aitools` redesign: `databricks aitools install` now installs the Databricks plugin through each coding agent's own CLI instead of copying raw skill files into every agent. Raw skills alongside a plugin produce duplicate, hard-to-update content; the plugin is how those agents expect third-party content to arrive. Stacked on databricks#5737 (plugin engine). ## Changes Before: install copied skill files into each detected agent's skills dir. Now: install is plugin-first, with explicit escape hatches. - **Delivery per agent:** plugin agents (Claude Code, Codex, Copilot) get the databricks plugin; agents with no plugin (OpenCode, Antigravity) get skill files; Cursor (plugin, but no headless install) prints the `/add-plugin databricks` step and copies nothing. - **Escape hatches:** `--skills-only` forces raw skill files for every agent; `--path <dir>` is a dumb dump (no agents, no state). `--skills-only` + `--path` is rejected. - **Scope mapping** (`mapAgentScope`): CLI `global` → agent user scope; CLI `project` → agent project scope only where supported (Claude), otherwise the agent is skipped with a reason. No silent fallback to user scope. - **No silent fallback:** a blocked plugin install (CLI not on PATH, install failure) is reported and skipped (exit 0), never swapped for skills. It errors only when the agent was explicitly named via `--agents`. - **Interactive picker** lists every known agent with a detection-state label (detected ones pre-checked), then shows a plan summary and a single confirm. - **Detection:** non-interactive selection now also detects plugin agents by their CLI binary on PATH (fixing the Codex/Copilot config-dir miss); `--skills-only` selection stays config-dir based and PATH-independent. - The legacy `experimental skills install` alias pins `--skills-only` to preserve its behavior. ## Test plan - [x] Unit tests: `buildPlan` deliveries (plugin/skills/manual/skip) and `--skills-only` forcing skills; `mapAgentScope` matrix; `executePlan` skip-with-warning vs error-on-explicit; plugin-first default (with a controlled PATH), `--agents` for an undetected agent, no-agents no-op, `--skills-only`/`--path` conflict, scope flags, interactive picker + confirm. - [x] Acceptance: the 3 existing `experimental aitools install` goldens switch to `--skills-only` and keep their behavior strings byte-identical (only the `>>>` echo gains the flag); a new `path-dump` test covers `--path`. - [x] `go test ./libs/aitools/... ./cmd/aitools/... ./acceptance -run TestAccept/experimental/aitools` passes. - [x] `./task fmt-q`, `./task lint-q` (0 issues), `./task checks` (no dead code) clean. This pull request and its description were written by Isaac.
bradleyjamrozik-origindigital
pushed a commit
to bradleyjamrozik-origindigital/databricks-cli
that referenced
this pull request
Jun 27, 2026
) <!-- aitools-stack --> ### Stack Part of the `aitools` plugin-first redesign. Merge bottom to top: - databricks#5734 Detection & registry (plugin metadata + capability detection) - databricks#5736 State schema v2 (plugin + file provenance records) - databricks#5737 Plugin engine, checksums, `--path` dump (library) - databricks#5738 Plugin-first install command - **databricks#5739 Update + prune of vanished skills ← this PR** - databricks#5740 Uninstall teardown + legacy skills cleanup - databricks#5741 list + version plugin state <!-- /aitools-stack --> ## Why With install now plugin-first, `update` has to know about both worlds: update the plugin for plugin agents, and reconcile raw skills for the rest. This PR also makes the one intended behavior change from the redesign: a skill that disappears from a release is now removed, not warned-about-and-kept, so users don't accumulate dead skills forever. Stacked on databricks#5738 (install command). ## Changes Before: `update` only reconciled skill files, and a skill that vanished from the manifest was kept with a warning. Now: - **Plugin agents:** every agent recorded in `state.Plugins` is updated through its own plugin CLI (`UpdateInstalledPlugins`). The plugin's own update handles content the release dropped, so plugin agents have no per-skill prune. - **Prune vanished skills:** a skill that disappeared from the manifest is pruned, but **only** when the CLI installed it and the on-disk files still match the recorded sha256. A user-modified skill, or one with no recorded provenance (legacy v1 state), is kept with a warning. `--no-prune` keeps vanished skills; `--check` previews the removals without deleting. - **No duplicate skills:** the file-skills reconcile excludes agents managed as plugins in this scope (so a plugin agent never gets duplicate raw skill files), and is skipped entirely for a pure-plugin install. - `FormatUpdateResult` gains "removed" lines and a "Removed N skills." summary; the existing updated/added lines and summary are byte-identical. ## Test plan - [x] Unit tests: prune of a vanished unmodified skill (state + canonical dir cleaned), `--no-prune` keeps it, a user-modified vanished skill is kept, `--check` shows the prune without deleting, `UpdateInstalledPlugins` runs the plugin update and bumps the recorded version, and the `--no-prune` flag wiring. - [x] Acceptance: new `update-prune` test installs two skills then updates against a release missing one — alpha updates, beta is pruned ("Removed 1 skill."). - [x] `go test ./libs/aitools/... ./cmd/aitools/... ./acceptance -run TestAccept/experimental/aitools` passes. - [x] `./task fmt-q`, `./task lint-q` (0 issues), `./task checks` (no dead code) clean. This pull request and its description were written by Isaac.
Address review on #5741: - agentEntry now mirrors skillEntry: Installed maps scope -> {version} with a top-level Managed flag. buildAgentEntries records each scope's version as-is and the text renderer collapses them, surfacing a stale scope over an up-to-date one. Up-to-date-ness is derived from version vs release like the skills view, so the cross-scope merge is gone. - buildAgentEntries takes a scope->state map containing only non-nil states; nil filtering moved to the call site. - agents.Registry is now []*Agent, dropping the &Registry[i] idiom in list/install/update/uninstall and simplifying ByName/DetectInstalled.
renaudhartert-db
approved these changes
Jun 29, 2026
bradleyjamrozik-origindigital
pushed a commit
to bradleyjamrozik-origindigital/databricks-cli
that referenced
this pull request
Jun 29, 2026
…all (databricks#5740) <!-- aitools-stack --> ### Stack Part of the `aitools` plugin-first redesign. Open PRs, merge bottom to top: - **databricks#5740 Uninstall teardown + legacy skills cleanup ← this PR** - databricks#5741 list + version plugin state - databricks#5745 Bug bash (wording, latest-by-default skills, project-scope plan, version reporting) - databricks#5746 Bug bash round 2 (uninstall confirm, picker, Cursor, official marketplace, version scope) Merged: databricks#5734, databricks#5736, databricks#5737, databricks#5738, databricks#5739. <!-- /aitools-stack --> ## Why To finish the lifecycle: `uninstall` has to remove the plugin we installed (not just skills), and `install` has to clean up any raw skills a user had from the old skills-everywhere model, so a plugin agent doesn't end up with the plugin *and* leftover loose skill files showing the same skills twice. Stacked on databricks#5739 (update). ## Changes - **Uninstall tears down plugins.** On a full uninstall (no `--skills` filter), each agent recorded in `state.Plugins` has its plugin removed through the agent's own CLI, and the marketplace is de-registered, but only when this CLI registered it and `--keep-marketplace` wasn't passed, so we never remove a marketplace another plugin may share. Skills teardown is unchanged for file agents; the state file is removed only when no skills and no plugins remain in the scope. - **Install cleans up legacy raw skills.** After installing the plugin for an agent, `RemoveLegacyRawSkills` removes skill dirs the CLI previously dropped there: a symlink pointing into our canonical dir, or a copy whose files all match the recorded checksums. User-modified dirs, third-party dirs, and copies with no recorded provenance are left untouched. - New `--keep-marketplace` flag on `uninstall`. ## Test plan - [x] Unit tests: uninstall tears down the plugin and de-registers the marketplace, removing the state file when nothing remains; `--keep-marketplace` skips the de-register; `RemoveLegacyRawSkills` removes our symlink and a checksum-matched copy while keeping a user-modified copy and a third-party dir. - [x] Existing skills-uninstall tests still pass byte-for-byte ("Uninstalled N skills.", selective removal, orphan cleanup, "no skills installed"). - [x] `go test ./libs/aitools/... ./cmd/aitools/...` passes. - [x] `./task fmt-q`, `./task lint-q` (0 issues), `./task checks` (no dead code) clean. This pull request and its description were written by Isaac.
bradleyjamrozik-origindigital
pushed a commit
to bradleyjamrozik-origindigital/databricks-cli
that referenced
this pull request
Jun 29, 2026
…lan, version reporting) (databricks#5745) <!-- aitools-stack --> ### Stack Part of the `aitools` plugin-first redesign. Open PRs, merge bottom to top: - databricks#5740 Uninstall teardown + legacy skills cleanup - databricks#5741 list + version plugin state - **databricks#5745 Bug bash (wording, latest-by-default skills, project-scope plan, version reporting) ← this PR** - databricks#5746 Bug bash round 2 (uninstall confirm, picker, Cursor, official marketplace, version scope) Merged: databricks#5734, databricks#5736, databricks#5737, databricks#5738, databricks#5739. <!-- /aitools-stack --> ## Why Testing the built CLI surfaced several issues in `databricks aitools`: 1. Inconsistent, plugin-blind copy ("AI Tools" / "AI skills") even though most agents now get a plugin. 2. Skills pinned to a cli-compat version (e.g. `0.2.5`) while plugin agents installed latest (e.g. `0.2.7`). Two different versions for the same content, and list/version misreported the plugin version. 3. Project-scope install offered files-only agents (OpenCode, Antigravity) that can't do project scope, then failed after the fact without installing anything. ## Changes **Wording.** Everything under `databricks aitools` now reads "skills and plugins" (help, version output, install log); empty-state errors say "no skills or plugins installed". The legacy skills alias and `experimental aitools` are untouched. **Skills track latest by default.** Plugin agents' CLIs have no version flag, so they only ever install the marketplace's latest. Skills now match that: - `GetSkillsRef` precedence: `DATABRICKS_SKILLS_REF` (exact ref, for evals), then cli-compat.json, then default latest (`main`). - cli-compat.json is the remote safety valve: its `skills` field is now `"latest"` (track latest), but it can be edited to a concrete version to pin older CLIs after a breaking change, with no CLI release needed. AppKit version resolution is unchanged (cli-compat still pins it via its own field). - Plugins (and unpinned skills) report `latest` instead of a stale concrete version, so list/version are honest. - `update` reconciles against latest when unpinned instead of falsely reporting "already up to date". **Project-scope plan is honest.** `buildPlan` skips files-only agents that don't support project scope (the way plugin agents already were), and the picker is scope-aware, so incompatible agents are labeled and not pre-checked. No more "offer then fail with nothing installed". ## Test plan - [x] Unit: `GetSkillsRef` (default latest / env pin / cli-compat pin), `DisplaySkillsVersion`, `buildPlan` project-scope skip for files-only agents; clicompat allows the `latest` sentinel. - [x] Acceptance `experimental/aitools` unchanged (tests pin the ref via env). - [x] `go test ./libs/aitools/... ./cmd/aitools/... ./libs/clicompat/...` passes. - [x] `./task fmt-q`, `./task lint-q` (0 issues), `./task checks` (no dead code) clean. This pull request and its description were written by Isaac.
bradleyjamrozik-origindigital
pushed a commit
to bradleyjamrozik-origindigital/databricks-cli
that referenced
this pull request
Jun 29, 2026
… marketplace) (databricks#5746) <!-- aitools-stack --> ### Stack Part of the `aitools` plugin-first redesign. Open PRs, merge bottom to top: - databricks#5740 Uninstall teardown + legacy skills cleanup - databricks#5741 list + version plugin state - databricks#5745 Bug bash (wording, latest-by-default skills, project-scope plan, version reporting) - **databricks#5746 Bug bash round 2 (uninstall confirm, picker, Cursor, official marketplace, version scope) ← this PR** Merged: databricks#5734, databricks#5736, databricks#5737, databricks#5738, databricks#5739. <!-- /aitools-stack --> ## Why A second round of testing the plugin-first `databricks aitools` CLI. Findings are tracked in `documents/proposals/aitools-bugbash-findings.md`. ## Changes - **uninstall confirms in interactive mode.** It removed skills and de-registered plugins immediately; now (on a TTY) it summarizes what will be removed and asks "Proceed?". Non-interactive runs are unaffected. - **version labels the scope.** Skills and plugins are now always labeled global/project (e.g. `Plugin (Claude Code, global): latest`). - **Claude installs from the official marketplace.** The databricks plugin is in Claude's built-in `claude-plugins-official` marketplace, so Claude installs `databricks@claude-plugins-official`. A built-in marketplace (empty PluginSpec.Source) is never added or de-registered. Codex/Copilot keep our own marketplace. - **Picker only offers actionable agents.** Every detected agent still shows in the detection list with its state/reason, but only agents that will do something (plugin or skills) are selectable; agents skipped in the scope are no longer checkboxes. - **Cursor is a plain skills agent.** Cursor was a confusing "manual, run /add-plugin" option that did nothing. Since the Cursor plugin can't be installed or interacted with headlessly, all references to it are removed: Cursor now installs raw skills like OpenCode/Antigravity, labeled simply "skills". This removed the whole manual-only concept (PluginSpec.ManualOnly/ManualInstructions, StateManualOnly, ReasonManualOnly, the manual_add_plugin list status, and the deliveryManualCursor path). - **Help links the source repo.** `databricks aitools` help points at https://github.com/databricks/databricks-agent-skills so users know where skills and plugins come from. ## Test plan - [x] Unit: uninstall confirm; version scope labels; built-in marketplace install (no `marketplace add`) and uninstall (no de-register); picker offers only actionable agents; Cursor plan = skills; no-plugin install guard. - [x] `go test ./libs/aitools/... ./cmd/aitools/...` and acceptance `experimental/aitools` pass. - [x] `./task fmt-q`, `./task lint-q` (0 issues), `./task checks` (no dead code) clean. This pull request and its description were written by Isaac.
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.
Stack
Part of the
aitoolsplugin-first redesign. Open PRs, merge bottom to top:Merged: #5734, #5736, #5737, #5738, #5739.
Why
listandversiononly knew about raw skills. Now that the CLI installs plugins, they should report the real per-agent plugin state so users (and the plugin's SessionStart nudge) can see what's installed and whether it's current.Stacked on #5740 (uninstall).
Changes
list --output jsongains an additiveagents[]array: each plugin agent with a recorded install (itsversionand anup_to_date/update_availablestatus,managed: true), plus Cursor asmanual_add_plugin(managed: false) when it's present. The existingrelease/skills/summarykeys and shapes are byte-identical (additiveomitemptyfield). The text view adds anAGENT / STATUSblock only when there are agent entries, leaving the skills table and summary line unchanged.versionprints aPlugin (<Agent>): vXline per recorded plugin, and only prints the skills line when skills are actually installed, so a plugin-only install no longer reports "0 skills". Existing skills output is unchanged.Test plan
listJSON includesagents[]with the right statuses/managed flags while keepingrelease/skills/summaryintact;buildAgentEntriesmaps recorded plugins to up_to_date/update_available and surfaces Cursor as manual;versionprints the plugin line for a plugin-only install.list/versiontests pass unchanged (JSON round-trip, both-scopes skills output).go test ./libs/aitools/... ./cmd/aitools/...passes../task fmt-q,./task lint-q(0 issues),./task checks(no dead code) clean.This pull request and its description were written by Isaac.