Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ Transport is selectable via the global `--transport {auto,http,uds,mcp}` flag (o
|---------|-------------|
| `agent-brain install-agent --agent claude` | Install for Claude Code |
| `agent-brain install-agent --agent opencode` | Install for OpenCode |
| `agent-brain install-agent --agent gemini` | Install for Gemini CLI |
| `agent-brain install-agent --agent codex` | Install for Codex (+ AGENTS.md) |
| `agent-brain install-agent --agent skill-runtime --dir <path>` | Install for any skill-based runtime |
| `agent-brain install-agent --agent <runtime> --dry-run` | Preview installation |
Expand Down
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The same auto-registration is extended to the other runtimes (each has its own M

- [x] [#224](https://github.com/SpillwaveSolutions/agent-brain/issues/224) — OpenCode (project-root `opencode.json` `mcp`) — shipped (#230)
- [x] [#226](https://github.com/SpillwaveSolutions/agent-brain/issues/226) — Codex (`~/.codex/config.toml` `[mcp_servers]`) — shipped
- [ ] [#231](https://github.com/SpillwaveSolutions/agent-brain/issues/231) — **Remove** the `gemini` runtime (Google deprecated the Gemini CLI; supersedes the closed #225)
- [x] [#231](https://github.com/SpillwaveSolutions/agent-brain/issues/231) — **Removed** the `gemini` runtime (Google deprecated the Gemini CLI; supersedes the closed #225) — shipped

> The native MCP server (formerly tracked here as #153/#167) shipped in the v10.1–v10.4 line
> and is no longer pending. The full MCP v1–v4 roadmap is complete as of v10.4.0.
22 changes: 4 additions & 18 deletions agent-brain-cli/agent_brain_cli/commands/install_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

from agent_brain_cli.runtime.claude_converter import ClaudeConverter
from agent_brain_cli.runtime.codex_converter import CodexConverter
from agent_brain_cli.runtime.gemini_converter import GeminiConverter
from agent_brain_cli.runtime.mcp_registration import (
McpRegistrationResult,
register_claude_mcp,
Expand All @@ -36,10 +35,6 @@
"project": ".opencode/plugins/agent-brain",
"global": "~/.config/opencode/plugins/agent-brain",
},
"gemini": {
"project": ".gemini/plugins/agent-brain",
"global": "~/.config/gemini/plugins/agent-brain",
},
"codex": {
"project": ".codex/skills/agent-brain",
"global": "~/.codex/skills/agent-brain",
Expand All @@ -50,17 +45,12 @@
DIR_REQUIRED_RUNTIMES = {"skill-runtime"}

ConverterType = type[
ClaudeConverter
| OpenCodeConverter
| GeminiConverter
| SkillRuntimeConverter
| CodexConverter
ClaudeConverter | OpenCodeConverter | SkillRuntimeConverter | CodexConverter
]

CONVERTERS: dict[str, ConverterType] = {
"claude": ClaudeConverter,
"opencode": OpenCodeConverter,
"gemini": GeminiConverter,
"skill-runtime": SkillRuntimeConverter,
"codex": CodexConverter,
}
Expand Down Expand Up @@ -102,7 +92,7 @@ def _resolve_target_dir(
return project_root / dir_template


RUNTIME_CHOICES = ["claude", "opencode", "gemini", "skill-runtime", "codex"]
RUNTIME_CHOICES = ["claude", "opencode", "skill-runtime", "codex"]

# Runtimes for which we can auto-register the MCP server today, mapped to the
# writer that knows that runtime's config schema. All writers share the
Expand Down Expand Up @@ -274,7 +264,7 @@ def install_agent_command(
Examples:
agent-brain install-agent --agent claude --project
agent-brain install-agent --agent opencode --global
agent-brain install-agent --agent gemini --dry-run
agent-brain install-agent --agent claude --dry-run
agent-brain install-agent --agent skill-runtime --dir ./my-skills
agent-brain install-agent --agent codex
"""
Expand Down Expand Up @@ -396,11 +386,7 @@ def install_agent_command(

def _handle_dry_run(
converter: (
ClaudeConverter
| OpenCodeConverter
| GeminiConverter
| SkillRuntimeConverter
| CodexConverter
ClaudeConverter | OpenCodeConverter | SkillRuntimeConverter | CodexConverter
),
bundle: Any,
target: Path,
Expand Down
2 changes: 0 additions & 2 deletions agent-brain-cli/agent_brain_cli/runtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
)
from agent_brain_cli.runtime.tool_maps import (
CLAUDE_TOOLS,
GEMINI_TOOLS,
OPENCODE_TOOLS,
map_tool_name,
map_tools,
Expand All @@ -33,7 +32,6 @@

__all__ = [
"CLAUDE_TOOLS",
"GEMINI_TOOLS",
"OPENCODE_TOOLS",
"PluginAgent",
"PluginBundle",
Expand Down
119 changes: 0 additions & 119 deletions agent-brain-cli/agent_brain_cli/runtime/gemini_converter.py

This file was deleted.

17 changes: 1 addition & 16 deletions agent-brain-cli/agent_brain_cli/runtime/tool_maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,10 @@
"TodoWrite": "todowrite",
}

# Gemini CLI — different tool name convention
GEMINI_TOOLS: dict[str, str] = {
"Bash": "run_shell_command",
"Read": "read_file",
"Write": "write_file",
"Edit": "replace",
"Glob": "glob",
"Grep": "grep",
"Agent": "agent",
"WebFetch": "web_fetch",
"WebSearch": "web_search",
"NotebookEdit": "notebook_edit",
}

# Mapping from RuntimeType to tool map
TOOL_MAPS: dict[str, dict[str, str]] = {
"claude": CLAUDE_TOOLS,
"opencode": OPENCODE_TOOLS,
"gemini": GEMINI_TOOLS,
}


Expand All @@ -67,7 +52,7 @@ def map_tool_name(tool: str, runtime: str) -> str:

Args:
tool: Canonical tool name (e.g., "Bash", "Write(.agent-brain/**)").
runtime: Target runtime ("claude", "opencode", "gemini").
runtime: Target runtime ("claude", "opencode").

Returns:
Mapped tool name, or the lowercased base name if no mapping exists.
Expand Down
1 change: 0 additions & 1 deletion agent-brain-cli/agent_brain_cli/runtime/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class RuntimeType(str, Enum):

CLAUDE = "claude"
OPENCODE = "opencode"
GEMINI = "gemini"
SKILL_RUNTIME = "skill-runtime"
CODEX = "codex"

Expand Down
18 changes: 0 additions & 18 deletions agent-brain-cli/tests/test_install_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,24 +98,6 @@ def test_opencode_project_install(
# OpenCode uses singular 'command/' directory (not 'commands/')
assert (target / "command" / "agent-brain-search.md").exists()

def test_gemini_project_install(
self, runner: CliRunner, plugin_dir: Path, tmp_path: Path
) -> None:
result = runner.invoke(
install_agent_command,
[
"--agent",
"gemini",
"--plugin-dir",
str(plugin_dir),
"--path",
str(tmp_path),
],
)
assert result.exit_code == 0
target = tmp_path / ".gemini" / "plugins" / "agent-brain"
assert (target / "commands" / "agent-brain-search.md").exists()

def test_dry_run(self, runner: CliRunner, plugin_dir: Path, tmp_path: Path) -> None:
result = runner.invoke(
install_agent_command,
Expand Down
4 changes: 3 additions & 1 deletion agent-brain-cli/tests/test_install_agent_mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,13 @@ def test_with_mcp_unsupported_runtime_warns_but_succeeds(
install_agent_command,
[
"--agent",
"gemini",
"skill-runtime",
"--plugin-dir",
str(plugin_dir),
"--path",
str(tmp_path),
"--dir",
str(tmp_path / "skills"),
"--with-mcp",
],
)
Expand Down
65 changes: 1 addition & 64 deletions agent-brain-cli/tests/test_runtime_converters.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Tests for runtime converters (Claude, OpenCode, Gemini)."""
"""Tests for runtime converters (Claude, OpenCode)."""

import json
from pathlib import Path
Expand All @@ -7,7 +7,6 @@
import yaml

from agent_brain_cli.runtime.claude_converter import ClaudeConverter
from agent_brain_cli.runtime.gemini_converter import GeminiConverter
from agent_brain_cli.runtime.opencode_converter import (
OpenCodeConverter,
_color_to_hex,
Expand Down Expand Up @@ -412,58 +411,6 @@ def test_tool_map_strips_path_scope(self) -> None:
assert map_tool_name("mcp__server__tool", "opencode") == "mcp__server__tool"


class TestGeminiConverter:
"""Tests for Gemini runtime converter."""

def test_runtime_type(self) -> None:
converter = GeminiConverter()
assert converter.runtime_type == RuntimeType.GEMINI

def test_convert_skill_maps_tools(self, sample_skill: PluginSkill) -> None:
converter = GeminiConverter()
result = converter.convert_skill(sample_skill)
_, fm_text = result.split("---\n", 1)
fm_text = fm_text.split("---\n", 1)[0]
parsed = yaml.safe_load(fm_text)
tools = parsed["allowed-tools"]
assert "run_shell_command" in tools # Bash -> run_shell_command
assert "read_file" in tools # Read -> read_file

def test_convert_skill_removes_color(self) -> None:
skill = PluginSkill(
name="test",
description="Test",
allowed_tools=["Bash"],
metadata={"version": "1.0", "color": "red"},
body="Content",
)
converter = GeminiConverter()
result = converter.convert_skill(skill)
_, fm_text = result.split("---\n", 1)
fm_text = fm_text.split("---\n", 1)[0]
parsed = yaml.safe_load(fm_text)
assert "color" not in parsed.get("metadata", {})

def test_convert_command_replaces_paths(
self, sample_command: PluginCommand
) -> None:
converter = GeminiConverter()
result = converter.convert_command(sample_command)
assert ".agent-brain" in result
assert ".claude/agent-brain" not in result

def test_install_creates_files(
self, tmp_path: Path, sample_bundle: PluginBundle
) -> None:
converter = GeminiConverter()
target = tmp_path / "output"
files = converter.install(sample_bundle, target, Scope.PROJECT)
assert len(files) > 0
assert (target / "commands" / "test-search.md").exists()
assert (target / "agents" / "search-helper.md").exists()
assert (target / "skills" / "using-agent-brain" / "SKILL.md").exists()


class TestRoundTrip:
"""Round-trip tests: parse canonical → convert → verify structure."""

Expand Down Expand Up @@ -491,13 +438,3 @@ def test_opencode_round_trip(self, real_plugin_dir: Path | None) -> None:
for skill in bundle.skills:
result = converter.convert_skill(skill)
assert "tools:" in result

def test_gemini_round_trip(self, real_plugin_dir: Path | None) -> None:
if real_plugin_dir is None:
pytest.skip("Real plugin dir not found")
bundle = parse_plugin_dir(real_plugin_dir)
converter = GeminiConverter()
for skill in bundle.skills:
result = converter.convert_skill(skill)
# Bash should become run_shell_command
assert "run_shell_command" in result
Loading
Loading