Repository navigation
feat: add Gemini CLI as a host via a published extension branch [DITTO-1798] - #20
Conversation
⏭ Ditto stopped reviewing
|
d4305b4 to
1844c7c
Compare
✅ Ditto reviewed
|
There was a problem hiding this comment.
Ditto Review
No blocking issues found · risk: medium · 7843a3e
File coverage: 1 fully reviewed, 0 reviewed briefly, 0 not reviewed.
Add Gemini CLI support with a dedicated published extension branch — Adds Gemini CLI as a Ditto host using a
gemini-extension.jsonmanifest and a dedicatedgemini-extensionbranch that publishesplugins/dittoat the repository root. The workflow verifies the package and tests before publishing; supporting changes update host guidance, manifests, validation, skill-version tracking, and tests. Review the publisher’s fast-forward behavior and the validator’s Gemini-specific restrictions closely.
Walkthrough (15 files)
| File | Change |
|---|---|
.github/workflows/gemini-extension.yml |
Adds a main-branch workflow that verifies the package and publishes the Ditto plugin to the Gemini extension branch. |
.kimi-plugin/plugin.json |
Bumps the root Kimi plugin version to 0.3.8. |
CONTRIBUTING.md |
Documents Gemini’s manifest, MCP entry, and dedicated-branch publishing approach. |
README.md |
Adds Gemini CLI installation, authentication, update, and validation guidance. |
RELEASING.md |
Adds Gemini CLI validation and notes that merging plugin changes republishes its branch. |
adapters/ditto-memory.md |
Adds Gemini CLI connection and authentication instructions. |
plugins/ditto/{.antigravity-plugin,.claude-plugin,.codex-plugin,.cursor-plugin,.github/plugin,.grok-plugin,.kimi-plugin}/plugin.json |
Bumps the Ditto plugin version to 0.3.8 across the host manifests. |
plugins/ditto/gemini-extension.json |
Declares Ditto’s Gemini extension metadata and hosted streamable-HTTP MCP server. |
plugins/ditto/shared-skills.lock.json |
Updates the shared-skill source commit and corresponding content hashes. |
plugins/ditto/skills/ditto-memory/SKILL.md |
Adds Gemini CLI connection and authentication guidance to the memory skill. |
scripts/publish_extension_ref.py |
Adds a publisher that places a plugin folder at a branch root using fast-forward commits. |
scripts/shared_skills.py |
Includes the Gemini manifest when tracking and bumping plugin host versions. |
scripts/validate_package.py |
Validates Gemini manifests and restricts Gemini MCP declarations to the approved hosted endpoint. |
tests/test_package.py |
Tests Gemini manifest validation and rejects unsupported MCP fields, endpoints, and extension directories. |
tests/test_publish_extension_ref.py |
Tests branch publication, no-op and dry-run behavior, missing-manifest rejection, and fast-forward updates. |
Review details
- Models: review
z-ai/glm-5.3-flash· verifyopenai/gpt-6-luna - Findings: 0 candidates → 0 verified → 0 posted
- Context index: 42 files · 24 changed symbols · 60 references
- Tokens: 67282 in / 4324 out · $0.01
- Incremental since
4c52018 - Run:
d2ec33ce-1a4e-45ee-be0c-376c8ed0c189· engine v2.0.0 · details - Ditto approves or requests changes in a separate review (blocking: 🟠 High and above). Inference is billed through your Ditto Router endpoint.
Open in Ditto · reply @ditto review to re-run · @ditto fix to push fixes
6c0de35 to
577dc3a
Compare
07559a7 to
6fcbbd4
Compare
|
Addressed all three Ditto Review findings in 6c0de35 (carried through the rebase onto main as 577dc3a, same patch-id and tree):
|
✅ Ditto reviewed
|
The base branch was changed.
…O-1798] Add plugins/ditto/gemini-extension.json: the hosted Ditto MCP server as httpUrl (Gemini reads `url` as SSE), OAuth left to Gemini's dynamic discovery on the server's 401. Gemini loads the bundled skills natively from skills/, so `gemini extensions validate ./plugins/ditto` passes and a local install lists 3 skills and the ditto server. Gemini CLI installs a GitHub repository only from its root and has no subdirectory option, and a root gemini-extension.json makes `agy plugin install <repo>` install the whole repository as a Gemini extension with no skills. So instead of a root manifest, scripts/publish_extension_ref.py commits the plugins/ditto tree unchanged as the next fast-forward commit of a dedicated branch, and .github/workflows/gemini-extension.yml runs it on main: gemini extensions install https://github.com/ditto-assistant/ditto-plugins --ref gemini-extension The validator adds the Gemini manifest (MCP-only, httpUrl only); the ditto-memory adapter gains a Gemini CLI section; the vendored generator comes from ditto-skills aab3efa, which versions gemini-extension.json. All manifests move to 0.3.8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restacked on the DITTO-1799 Ditto Review fixes; regenerated the lock from ditto-skills b406544. No skill bytes change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every other host reads url or serverUrl, so an httpUrl-only declaration there validated while installing with no working MCP server. Also bound the gemini-extension publish job to 15 minutes so a stalled run cannot hold the concurrency slot for hours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
577dc3a to
4c52018
Compare
✅ Ditto reviewed
|
…1798] A global commit.gpgsign or hooks path made the publish tests depend on the machine running them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
✅ Ditto reviewed
|
Summary
Gemini CLI is now a target host.
plugins/ditto/gemini-extension.jsondeclares the Ditto MCP server ashttpUrl: https://api.heyditto.ai/mcp. In Gemini that field means streamable HTTP;urlwould mean SSE.WWW-Authenticate: Bearer … resource_metadata=…/.well-known/oauth-protected-resource/mcp.skills/.gemini extensions validate ./plugins/dittopasses.Why a published branch and not a root
gemini-extension.jsonextensions installtakes--refbut no path. In 0.66.0,tryParseGithubUrlaccepts onlyowner/repo,cloneFromGitclones the root, and skills load only from<extension>/skills.gemini-extension.json,agy plugin install <repo>installs the repository root as a Gemini extension (source: gemini-cli) with 0 skills, where it used to installplugins/ditto.skills/symlink doesn't survive install (tested). Gemini'sfs.cprewrites the relative link to an absolute path into its temporary clone. Once that clone is deleted, 0 skills load.--reffor release channels. Soscripts/publish_extension_ref.pycommits theplugins/dittotree unchanged as the next fast-forward commit ofgemini-extension, and does nothing when the tree is unchanged..github/workflows/gemini-extension.ymlruns it onmainafter verify, unittest and validate. Nothing outsideplugins/dittoand that branch changes for other hosts.main.Other changes
name,version,descriptionandmcpServers, and each server onlyhttpUrlwith the hosted URL. Gemini'scommands/,hooks/,policies/andagents/stay rejected as release files. 15 package tests plus 4 publisher tests: 19 OK.validate_package.py: 20 files.adapters/ditto-memory.mdgains a Gemini CLI line (/mcp,/mcp auth ditto). The generatedditto-memoryskill was regenerated.scripts/shared_skills.pyand the lock come from ditto-assistant/ditto-skills#16 (headb406544), which versionsgemini-extension.json.verify --sourcepasses.Host results
Each CLI ran in its own throwaway HOME, with no host sign-in and no Ditto OAuth. Branch head
1844c7c, after restacking on #19's review fixes and a full re-run.latest, run via a scratchnpm install)extensions validate ./plugins/dittopasses (onmain: "Configuration file not found")--ref claude/ditto-1798-gemini-extension-ref. This is a test branch I published with the new script from this head. Its head28dd191hasplugins/dittoat1844c7cas its root tree (ca88338)curate-music,ditto-memory,handoffenabled; MCPditto(http)plugins/dittoextensions update dittoafter a scratch commit on the test branchvalidate --strictpasses/tree/<branch>source: antigravity/tree/<branch>, plus a local pathplugin-ditto:dittoneeds auth--strict+ marketplace pass#<branch>--ref.git#<branch>plugin validatepassesLimitations
gemini-extensionbranch doesn't exist yet. The workflow creates it on the firstmainpush that touchesplugins/ditto, or on a manualworkflow_dispatch. Until then the README command fails. The workflow itself hasn't run: I ran the same script locally against GitHub to createclaude/ditto-1798-gemini-extension-ref. It needscontents: writeforGITHUB_TOKEN; the repo's default workflow permissions arewrite. Delete the test branch after review.gemini mcp listhas no auth status, only Connected, Connecting, Blocked, Disabled or Disconnected, so the server shows "Disconnected". The interactive/mcpview needs a Gemini sign-in first, which I didn't do. Indirect evidence: the endpoint returns 401 with the OAuth resource metadata that Gemini's auto-discovery uses./mcp auth dittoisn't exercised.--refinstall, Gemini first requests a GitHub release by that tag, gets a 404, and asks to fall back togit clone. The README says to answer yes.Stack: based on #19 (DITTO-1799) → #18 (DITTO-1800). Related: ditto-assistant/ditto-skills#16.
🤖 Generated with Claude Code