From 1744e1ef0e32e397840b7bfa24b388eafe049280 Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Tue, 31 Mar 2026 15:13:20 -0700 Subject: [PATCH] feat: add gemini install target --- .gemini/GEMINI.md | 48 +++++++++++++++++++ README.md | 3 ++ manifests/install-modules.json | 2 + schemas/ecc-install-config.schema.json | 1 + scripts/lib/install-manifests.js | 2 +- scripts/lib/install-targets/gemini-project.js | 10 ++++ scripts/lib/install-targets/registry.js | 2 + tests/lib/install-targets.test.js | 14 ++++++ 8 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 .gemini/GEMINI.md create mode 100644 scripts/lib/install-targets/gemini-project.js diff --git a/.gemini/GEMINI.md b/.gemini/GEMINI.md new file mode 100644 index 00000000..7b9b2d67 --- /dev/null +++ b/.gemini/GEMINI.md @@ -0,0 +1,48 @@ +# ECC for Gemini CLI + +This file provides Gemini CLI with the baseline ECC workflow, review standards, and security checks for repositories that install the Gemini target. + +## Overview + +Everything Claude Code (ECC) is a cross-harness coding system with 36 specialized agents, 142 skills, and 68 commands. + +Gemini support is currently focused on a strong project-local instruction layer via `.gemini/GEMINI.md`, plus the shared MCP catalog and package-manager setup assets shipped by the installer. + +## Core Workflow + +1. Plan before editing large features. +2. Prefer test-first changes for bug fixes and new functionality. +3. Review for security before shipping. +4. Keep changes self-contained, readable, and easy to revert. + +## Coding Standards + +- Prefer immutable updates over in-place mutation. +- Keep functions small and files focused. +- Validate user input at boundaries. +- Never hardcode secrets. +- Fail loudly with clear error messages instead of silently swallowing problems. + +## Security Checklist + +Before any commit: + +- No hardcoded API keys, passwords, or tokens +- All external input validated +- Parameterized queries for database writes +- Sanitized HTML output where applicable +- Authz/authn checked for sensitive paths +- Error messages scrubbed of sensitive internals + +## Delivery Standards + +- Use conventional commits: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `ci` +- Run targeted verification for touched areas before shipping +- Prefer contained local implementations over adding new third-party runtime dependencies + +## ECC Areas To Reuse + +- `AGENTS.md` for repo-wide operating rules +- `skills/` for deep workflow guidance +- `commands/` for slash-command patterns worth adapting into prompts/macros +- `mcp-configs/` for shared connector baselines diff --git a/README.md b/README.md index b1235671..1b2a057f 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,7 @@ npm install # or: pnpm install | yarn install | bun install # ./install.sh typescript python golang swift php # ./install.sh --target cursor typescript # ./install.sh --target antigravity typescript +# ./install.sh --target gemini --profile full ``` ```powershell @@ -200,6 +201,7 @@ npm install # or: pnpm install | yarn install | bun install # .\install.ps1 typescript python golang swift php # .\install.ps1 --target cursor typescript # .\install.ps1 --target antigravity typescript +# .\install.ps1 --target gemini --profile full # npm-installed compatibility entrypoint also works cross-platform npx ecc-install typescript @@ -885,6 +887,7 @@ Each component is fully independent. Yes. ECC is cross-platform: - **Cursor**: Pre-translated configs in `.cursor/`. See [Cursor IDE Support](#cursor-ide-support). +- **Gemini CLI**: Experimental project-local support via `.gemini/GEMINI.md` and shared installer plumbing. - **OpenCode**: Full plugin support in `.opencode/`. See [OpenCode Support](#-opencode-support). - **Codex**: First-class support for both macOS app and CLI, with adapter drift guards and SessionStart fallback. See PR [#257](https://github.com/affaan-m/everything-claude-code/pull/257). - **Antigravity**: Tightly integrated setup for workflows, skills, and flattened rules in `.agent/`. See [Antigravity Guide](docs/ANTIGRAVITY-GUIDE.md). diff --git a/manifests/install-modules.json b/manifests/install-modules.json index 8854ea79..b2fd0554 100644 --- a/manifests/install-modules.json +++ b/manifests/install-modules.json @@ -88,6 +88,7 @@ ".claude-plugin", ".codex", ".cursor", + ".gemini", ".opencode", "mcp-configs", "scripts/setup-package-manager.js" @@ -97,6 +98,7 @@ "cursor", "antigravity", "codex", + "gemini", "opencode", "codebuddy" ], diff --git a/schemas/ecc-install-config.schema.json b/schemas/ecc-install-config.schema.json index 13f826d3..cb866aa3 100644 --- a/schemas/ecc-install-config.schema.json +++ b/schemas/ecc-install-config.schema.json @@ -22,6 +22,7 @@ "cursor", "antigravity", "codex", + "gemini", "opencode", "codebuddy" ] diff --git a/scripts/lib/install-manifests.js b/scripts/lib/install-manifests.js index 582e81f6..0a7ecf45 100644 --- a/scripts/lib/install-manifests.js +++ b/scripts/lib/install-manifests.js @@ -4,7 +4,7 @@ const path = require('path'); const { planInstallTargetScaffold } = require('./install-targets/registry'); const DEFAULT_REPO_ROOT = path.join(__dirname, '../..'); -const SUPPORTED_INSTALL_TARGETS = ['claude', 'cursor', 'antigravity', 'codex', 'opencode', 'codebuddy']; +const SUPPORTED_INSTALL_TARGETS = ['claude', 'cursor', 'antigravity', 'codex', 'gemini', 'opencode', 'codebuddy']; const COMPONENT_FAMILY_PREFIXES = { baseline: 'baseline:', language: 'lang:', diff --git a/scripts/lib/install-targets/gemini-project.js b/scripts/lib/install-targets/gemini-project.js new file mode 100644 index 00000000..f87f8539 --- /dev/null +++ b/scripts/lib/install-targets/gemini-project.js @@ -0,0 +1,10 @@ +const { createInstallTargetAdapter } = require('./helpers'); + +module.exports = createInstallTargetAdapter({ + id: 'gemini-project', + target: 'gemini', + kind: 'project', + rootSegments: ['.gemini'], + installStatePathSegments: ['ecc-install-state.json'], + nativeRootRelativePath: '.gemini', +}); diff --git a/scripts/lib/install-targets/registry.js b/scripts/lib/install-targets/registry.js index 64c14f32..64838608 100644 --- a/scripts/lib/install-targets/registry.js +++ b/scripts/lib/install-targets/registry.js @@ -3,6 +3,7 @@ const claudeHome = require('./claude-home'); const codebuddyProject = require('./codebuddy-project'); const codexHome = require('./codex-home'); const cursorProject = require('./cursor-project'); +const geminiProject = require('./gemini-project'); const opencodeHome = require('./opencode-home'); const ADAPTERS = Object.freeze([ @@ -10,6 +11,7 @@ const ADAPTERS = Object.freeze([ cursorProject, antigravityProject, codexHome, + geminiProject, opencodeHome, codebuddyProject, ]); diff --git a/tests/lib/install-targets.test.js b/tests/lib/install-targets.test.js index 2a299e73..35c22765 100644 --- a/tests/lib/install-targets.test.js +++ b/tests/lib/install-targets.test.js @@ -40,6 +40,7 @@ function runTests() { assert.ok(targets.includes('cursor'), 'Should include cursor target'); assert.ok(targets.includes('antigravity'), 'Should include antigravity target'); assert.ok(targets.includes('codex'), 'Should include codex target'); + assert.ok(targets.includes('gemini'), 'Should include gemini target'); assert.ok(targets.includes('opencode'), 'Should include opencode target'); assert.ok(targets.includes('codebuddy'), 'Should include codebuddy target'); })) passed++; else failed++; @@ -230,6 +231,19 @@ function runTests() { assert.strictEqual(statePath, path.join(projectRoot, '.codebuddy', 'ecc-install-state.json')); })) passed++; else failed++; + if (test('resolves gemini adapter root and install-state path from project root', () => { + const adapter = getInstallTargetAdapter('gemini'); + const projectRoot = '/workspace/app'; + const root = adapter.resolveRoot({ projectRoot }); + const statePath = adapter.getInstallStatePath({ projectRoot }); + + assert.strictEqual(adapter.id, 'gemini-project'); + assert.strictEqual(adapter.target, 'gemini'); + assert.strictEqual(adapter.kind, 'project'); + assert.strictEqual(root, path.join(projectRoot, '.gemini')); + assert.strictEqual(statePath, path.join(projectRoot, '.gemini', 'ecc-install-state.json')); + })) passed++; else failed++; + if (test('codebuddy adapter supports lookup by target and adapter id', () => { const byTarget = getInstallTargetAdapter('codebuddy'); const byId = getInstallTargetAdapter('codebuddy-project');