feat(plugin): per-provider bundles under plugins/databricks/<provider>/#165
Merged
Conversation
Replace the whole-repo "./" plugin source with generated, committed,
drift-checked per-provider bundles: plugins/databricks/{claude,codex,copilot,
cursor}/. Each folder is self-contained and holds only what that provider uses:
its plugin.json, a copy of skills/, its hook wiring as hooks/hooks.json plus the
scripts it references (and _routing_data.json only where the router is wired),
and, where applicable, commands/ (Claude, Cursor), rules/ (Cursor), assets/
(Codex). The four root marketplace.json catalogs (Cursor's is new) each point a
scoped source at their own provider subfolder, so an install fetches only that
provider's payload.
Why: a self-contained folder per provider is easy to see and debug, fixes the
Copilot fsmonitor crash and the Codex root-source bug, and makes each install a
cheap scoped fetch.
Changes:
- skillsgen/bundle.py: assemble + byte-exact drift-check each provider folder
(a missing, stale, hand-edited, or extra file all fail CI)
- uniform hooks/hooks.json per provider: each folder ships its dialect's wiring
as hooks/hooks.json (auto-discovered from the plugin root), so no plugin.json
declares a "hooks" path. The per-dialect names (codex-hooks.json, ...) stay
only at the repo root so generation doesn't collide; the bundle renames each.
- skillsgen/commands.py + templated commands/*.md: one source per command with a
{{claude-or-codex|cursor}} alternation, rendered per provider; commands-cursor/
removed
- plugins.py: catalogs scoped per provider via meta.marketplace.source; ref
"main" for now (a mechanical follow-up flips to v{version} tag-pinning)
- CLI files-channel unchanged: the stable repo_dir stays "skills" (root skills/),
so manifest.json and the released CLI are untouched
- .gitattributes marks plugins/** linguist-generated; release.yml stages
plugins/databricks; validate-manifest.yml triggers on plugins/**
- docs (CLAUDE/AGENTS/CONTRIBUTING/READMEs/metaplugin) + tests updated
Validation is clean and all 110 unit tests pass. Verified empirically against a
throwaway repo: scoped install + tag-freeze on Claude/Codex/Copilot, plugin load
on Cursor, the Copilot fsmonitor fix (the whole-repo control crashes, the scoped
install does not), the CLI files-channel path, and the "./" -> scoped migration
on a version bump. Codex still needs its policy block + a live router-fire check
(an open question in the proposal).
Co-authored-by: Isaac
Signed-off-by: simon <simon.faltum@databricks.com>
renaudhartert-db
approved these changes
Jun 19, 2026
…atabricks-bundle Signed-off-by: simon <simon.faltum@databricks.com>
PR #164 edited four databricks-apps / databricks-dabs source files after this branch was cut, so the committed per-provider bundle copies drifted (CI validate caught it on the merge checkout). Merge main and regenerate so all four providers' skill copies match the updated source. Also remove the now-dead `.codex-plugin/**` trigger from validate-manifest.yml: this PR moved Codex's plugin.json into plugins/databricks/codex/.codex-plugin/ (already covered by `plugins/**`), so root `.codex-plugin/` no longer exists. Co-authored-by: Isaac Signed-off-by: simon <simon.faltum@databricks.com>
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.
Why
The plugin shipped from a single whole-repo source (
marketplace.jsonsource: "./"), which caused real problems. Copilot crashed copying the repo's.git/fsmonitor--daemon.ipcsocket (upstream #3842), Codex mis-resolved hook paths from the repo root, and every install cloned the entire repo even though each agent only uses its own dialect's files. There was also no easy way to see, per provider, exactly what ships.Changes
Before: one
source: "./"per catalog; all four agents cloned the whole repo;commands/andcommands-cursor/were maintained as two near-duplicate trees.Now: each agent fetches a generated, self-contained
plugins/databricks/<provider>/folder (claude,codex,copilot,cursor) holding only what it uses: itsplugin.json, a copy ofskills/, its hook wiring ashooks/hooks.jsonplus the scripts it references, and where applicablecommands/,rules/,assets/. The four rootmarketplace.jsoncatalogs (Cursor's is new) each point a scoped source at their own subfolder, so an install fetches only that provider's payload.Implementation:
skillsgen/bundle.py: assembles each provider folder and byte-exact drift-checks it (a missing, stale, hand-edited, or extra file all fail CI).hooks/hooks.jsonper provider, auto-discovered from the plugin root, so noplugin.jsondeclares a"hooks"path. The per-dialect names (codex-hooks.json, ...) remain only at the repo root so the single generation step does not collide; the bundle renames each into its folder.skillsgen/commands.py+ templatedcommands/*.md: one source per command with a{{claude-or-codex | cursor}}alternation, rendered per provider.commands-cursor/removed.plugins.py: catalogs scoped per provider viametaplugin/plugin.meta.jsonmarketplace.source;ref: mainfor now (a mechanical follow-up flips it tov{version}tag-pinning).repo_dirstaysskills(rootskills/), somanifest.jsonand the released CLI are untouched..gitattributesmarksplugins/**linguist-generated;release.ymlstagesplugins/databricks;validate-manifest.ymltriggers onplugins/**.Everything under
plugins/is generated, committed, and drift-checked (not gitignored), so a reviewer sees the exact bytes each agent fetches.Test plan
python3 scripts/skills.py validatecleanpython3 -m unittest discover -s tests -p '*_test.py')cursor-agent --plugin-dir); the Copilot fsmonitor fix (the whole-repo control crashes, the scoped install does not); the CLI files-channel path; and the./-> scoped migration on a version bump.Follow-up (separate, mechanical PR): flip
ref_templatefrommaintov{version}so the ref-capable tools (Claude, Codex, Copilot) serve frozen release tags instead of main HEAD. Cursor cannot pin a ref and always tracks the default branch.This pull request and its description were written by Isaac.