Skip to content

Commit 57d8f5b

Browse files
authored
feat: Support more subagents via semble init, add more installation docs (#118)
1 parent a5a2334 commit 57d8f5b

5 files changed

Lines changed: 186 additions & 27 deletions

File tree

README.md

Lines changed: 148 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Add Semble to Claude Code (requires [uv](https://docs.astral.sh/uv/getting-start
3838
claude mcp add semble -s user -- uvx --from "semble[mcp]" semble
3939
```
4040

41-
Using Codex, OpenCode, or Cursor? See [MCP Server](#mcp-server) for setup instructions.
41+
Using another agent harness? See [MCP Server](#mcp-server) below for per-agent setup.
4242

4343
### Bash / AGENTS.md
4444

@@ -83,7 +83,7 @@ If `semble` is not on `$PATH`, use `uvx --from "semble[mcp]" semble` in its plac
8383

8484
</details>
8585

86-
Once installed, run `semble savings` to see how many tokens Semble has saved you. Note that for sub-agent support in Claude Code or Codex, you need the full [Bash / AGENTS.md](#bash-agentsmd) setup below.
86+
Note that sub-agents cannot call MCP tools directly, see [Bash / AGENTS.md](#bash-agentsmd) and [sub-agent setup](#sub-agent-setup) below for details.
8787

8888
<details>
8989
<summary>Updating Semble</summary>
@@ -102,7 +102,7 @@ uv cache clean semble # for MCP users (restart your MCP client after)
102102
- **Accurate**: NDCG@10 of 0.854 on our [benchmarks](#benchmarks), on par with code-specialized transformer models, at a fraction of the size and cost.
103103
- **Token-efficient**: returns only the relevant chunks, using [~98% fewer tokens than grep+read](#benchmarks).
104104
- **Zero setup**: runs on CPU with no API keys, GPU, or external services required.
105-
- **MCP server**: works with Claude Code, Cursor, Codex, OpenCode, and any other MCP-compatible agent.
105+
- **MCP server**: works with Claude Code, Cursor, Codex, OpenCode, VS Code, and any other MCP-compatible agent.
106106
- **Local and remote**: pass a local path or a git URL.
107107

108108
## MCP Server
@@ -113,21 +113,51 @@ Semble can run as an MCP server so agents can search any codebase directly. Repo
113113

114114
> Requires [uv](https://docs.astral.sh/uv/getting-started/installation/) to be installed.
115115
116-
#### Claude Code
116+
<details>
117+
<summary>Claude Code</summary>
118+
117119
```bash
118120
claude mcp add semble -s user -- uvx --from "semble[mcp]" semble
119121
```
120122

121-
#### Codex
123+
</details>
124+
125+
<details>
126+
<summary>Cursor</summary>
127+
128+
Add to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in your project):
129+
130+
```json
131+
{
132+
"mcpServers": {
133+
"semble": {
134+
"command": "uvx",
135+
"args": ["--from", "semble[mcp]", "semble"]
136+
}
137+
}
138+
}
139+
```
140+
141+
</details>
142+
143+
<details>
144+
<summary>Codex</summary>
145+
122146
Add to `~/.codex/config.toml`:
147+
123148
```toml
124149
[mcp_servers.semble]
125150
command = "uvx"
126151
args = ["--from", "semble[mcp]", "semble"]
127152
```
128153

129-
#### OpenCode
154+
</details>
155+
156+
<details>
157+
<summary>OpenCode</summary>
158+
130159
Add to `~/.opencode/config.json`:
160+
131161
```json
132162
{
133163
"mcp": {
@@ -139,8 +169,31 @@ Add to `~/.opencode/config.json`:
139169
}
140170
```
141171

142-
#### Cursor
143-
Add to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in your project):
172+
</details>
173+
174+
<details>
175+
<summary>VS Code</summary>
176+
177+
Add to `.vscode/mcp.json` in your project (or your user profile's `mcp.json`):
178+
179+
```json
180+
{
181+
"servers": {
182+
"semble": {
183+
"command": "uvx",
184+
"args": ["--from", "semble[mcp]", "semble"]
185+
}
186+
}
187+
}
188+
```
189+
190+
</details>
191+
192+
<details>
193+
<summary>GitHub Copilot CLI</summary>
194+
195+
Add to `~/.copilot/mcp-config.json`:
196+
144197
```json
145198
{
146199
"mcpServers": {
@@ -152,6 +205,81 @@ Add to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in your project):
152205
}
153206
```
154207

208+
</details>
209+
210+
<details>
211+
<summary>Windsurf</summary>
212+
213+
Add to `~/.codeium/windsurf/mcp_config.json`:
214+
215+
```json
216+
{
217+
"mcpServers": {
218+
"semble": {
219+
"command": "uvx",
220+
"args": ["--from", "semble[mcp]", "semble"]
221+
}
222+
}
223+
}
224+
```
225+
226+
</details>
227+
228+
<details>
229+
<summary>Gemini CLI</summary>
230+
231+
Add to `~/.gemini/settings.json`:
232+
233+
```json
234+
{
235+
"mcpServers": {
236+
"semble": {
237+
"command": "uvx",
238+
"args": ["--from", "semble[mcp]", "semble"]
239+
}
240+
}
241+
}
242+
```
243+
244+
</details>
245+
246+
<details>
247+
<summary>Kiro</summary>
248+
249+
Add to `~/.kiro/settings/mcp.json` (or `.kiro/settings/mcp.json` in your project):
250+
251+
```json
252+
{
253+
"mcpServers": {
254+
"semble": {
255+
"command": "uvx",
256+
"args": ["--from", "semble[mcp]", "semble"]
257+
}
258+
}
259+
}
260+
```
261+
262+
</details>
263+
264+
<details>
265+
<summary>Zed</summary>
266+
267+
Add to `~/.config/zed/settings.json` (or `.zed/settings.json` in your project):
268+
269+
```json
270+
{
271+
"context_servers": {
272+
"semble": {
273+
"command": "uvx",
274+
"args": ["--from", "semble[mcp]", "semble"]
275+
}
276+
}
277+
}
278+
```
279+
280+
</details>
281+
282+
155283
### Tools
156284

157285
| Tool | Description |
@@ -164,9 +292,9 @@ Add to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in your project):
164292

165293
## Bash / AGENTS.md
166294

167-
An alternative to MCP is to invoke Semble via Bash. For Claude Code and Codex CLI, this is the only option for sub-agents, which cannot call MCP tools directly, though it can also be used alongside MCP for the top-level agent.
295+
An alternative to MCP is to invoke Semble via Bash. Sub-agents cannot call MCP tools directly, so this is the only option for sub-agent support; it can also be used alongside MCP for the top-level agent.
168296

169-
To add Bash support, append the following to your `AGENTS.md` or `CLAUDE.md`:
297+
To add Bash support, append the following to your `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, or equivalent:
170298

171299
```markdown
172300
## Code Search
@@ -197,15 +325,20 @@ If `semble` is not on `$PATH`, use `uvx --from "semble[mcp]" semble` in its plac
197325
4. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string.
198326
```
199327

200-
**Claude Code sub-agent**: Claude Code also supports a dedicated sub-agent. Run this once in your project root:
328+
### Sub-agent setup
329+
330+
Claude Code, Gemini CLI, Cursor, OpenCode, GitHub Copilot CLI, and Kiro all support a dedicated semble search sub-agent. Run `semble init` once in your project root:
201331

202332
```bash
203-
semble init
204-
# or, if semble is not on $PATH:
205-
uvx --from "semble[mcp]" semble init
333+
semble init # Claude Code → .claude/agents/semble-search.md
334+
semble init --agent gemini # Gemini CLI → .gemini/agents/semble-search.md
335+
semble init --agent cursor # Cursor → .cursor/agents/semble-search.md
336+
semble init --agent opencode # OpenCode → .opencode/agents/semble-search.md
337+
semble init --agent copilot # Copilot CLI → .github/agents/semble-search.md
338+
semble init --agent kiro # Kiro → .kiro/agents/semble-search.md
206339
```
207340

208-
This writes [`.claude/agents/semble-search.md`](src/semble/agents/semble-search.md).
341+
If semble is not on `$PATH`, prefix the command with `uvx --from "semble[mcp]"`.
209342

210343
## CLI
211344

src/semble/cli.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import argparse
22
import asyncio
33
import sys
4+
from enum import Enum
45
from importlib.resources import files
56
from importlib.util import find_spec
67
from pathlib import Path
@@ -11,10 +12,26 @@
1112
from semble.stats import format_savings_report
1213
from semble.utils import _format_results, _is_git_url, _resolve_chunk
1314

14-
_CLAUDE_FILE_PATH = Path(".claude") / "agents" / "semble-search.md"
15+
16+
class Agent(str, Enum):
17+
CLAUDE = "claude"
18+
COPILOT = "copilot"
19+
CURSOR = "cursor"
20+
GEMINI = "gemini"
21+
KIRO = "kiro"
22+
OPENCODE = "opencode"
23+
24+
25+
_DEFAULT_AGENT = Agent.CLAUDE
1526
_CLI_DISPATCH_ARGS = frozenset({"search", "find-related", "init", "savings", "-h", "--help"})
1627

1728

29+
def _agent_path(agent: Agent) -> Path:
30+
"""Return the project-relative path where the semble sub-agent file should be written."""
31+
base_dir = ".github" if agent is Agent.COPILOT else f".{agent.value}"
32+
return Path(base_dir) / "agents" / "semble-search.md"
33+
34+
1835
def main() -> None:
1936
"""Entry point for the semble command-line tool."""
2037
if len(sys.argv) > 1 and sys.argv[1] in _CLI_DISPATCH_ARGS:
@@ -49,9 +66,9 @@ def _mcp_main() -> None:
4966
asyncio.run(serve(args.path, ref=args.ref, include_text_files=args.include_text_files))
5067

5168

52-
def _run_init(*, force: bool = False) -> None:
53-
"""Write the Claude Code sub-agent file into the current project."""
54-
dest = _CLAUDE_FILE_PATH
69+
def _run_init(*, agent: Agent = _DEFAULT_AGENT, force: bool = False) -> None:
70+
"""Write the semble sub-agent file for the given coding agent into the current project."""
71+
dest = _agent_path(agent)
5572
if dest.exists() and not force:
5673
print(f"{dest} already exists. Run with --force to overwrite.", file=sys.stderr)
5774
sys.exit(1)
@@ -89,7 +106,14 @@ def _cli_main() -> None:
89106
help="Also index non-code text files (.md, .yaml, .json, etc.).",
90107
)
91108

92-
init_p = sub.add_parser("init", help="Write .claude/agents/semble-search.md for Claude Code sub-agent support.")
109+
init_p = sub.add_parser("init", help="Write a semble sub-agent file for your coding agent.")
110+
init_p.add_argument(
111+
"--agent",
112+
"-a",
113+
default=_DEFAULT_AGENT.value,
114+
choices=[a.value for a in Agent],
115+
help=f"Coding agent to set up (default: {_DEFAULT_AGENT.value}).",
116+
)
93117
init_p.add_argument("--force", action="store_true", help="Overwrite if the file already exists.")
94118

95119
savings_p = sub.add_parser("savings", help="Show token savings and usage stats.")
@@ -98,7 +122,7 @@ def _cli_main() -> None:
98122
args = parser.parse_args()
99123

100124
if args.command == "init":
101-
_run_init(force=args.force)
125+
_run_init(agent=Agent(args.agent), force=args.force)
102126
return
103127

104128
if args.command == "savings":

src/semble/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version_triple__ = (0, 1, 9)
1+
__version_triple__ = (0, 1, 10)
22
__version__ = ".".join(map(str, __version_triple__))

tests/test_cli.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55

66
import pytest
77

8-
from semble.cli import _CLAUDE_FILE_PATH, _cli_main, _run_init, main
8+
from semble.cli import Agent, _agent_path, _cli_main, _run_init, main
99
from semble.types import SearchMode, SearchResult
1010
from tests.conftest import make_chunk
1111

12+
_CLAUDE_FILE_PATH = _agent_path(Agent.CLAUDE)
13+
1214
_CLAUDE_AGENT_FILE = files("semble").joinpath("agents/semble-search.md").read_text(encoding="utf-8")
1315

1416

uv.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)