diff --git a/src/semble/agents/semble-search.md b/src/semble/agents/claude.md similarity index 100% rename from src/semble/agents/semble-search.md rename to src/semble/agents/claude.md diff --git a/src/semble/agents/copilot.md b/src/semble/agents/copilot.md new file mode 100644 index 0000000..515d60e --- /dev/null +++ b/src/semble/agents/copilot.md @@ -0,0 +1,30 @@ +--- +name: semble-search +description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over Grep/Glob/Read for any semantic or exploratory question. +tools: Bash, Read +--- + +Use `semble search` to find code by describing what it does or naming a symbol/identifier, instead of grep: + +```bash +semble search "authentication flow" ./my-project +semble search "save_pretrained" ./my-project +semble search "save model to disk" ./my-project --top-k 10 +``` + +Use `semble find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result): + +```bash +semble find-related src/auth.py 42 ./my-project +``` + +`path` defaults to the current directory when omitted; git URLs are accepted. + +If `semble` is not on `$PATH`, use `uvx --from "semble[mcp]" semble` in its place. + +## Workflow + +1. Start with `semble search` to find relevant chunks. +2. Inspect full files only when the returned chunk is not enough context. +3. Optionally use `semble find-related` with a promising result's `file_path` and `line` to discover related implementations. +4. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string. diff --git a/src/semble/agents/cursor.md b/src/semble/agents/cursor.md new file mode 100644 index 0000000..160aac4 --- /dev/null +++ b/src/semble/agents/cursor.md @@ -0,0 +1,29 @@ +--- +name: semble-search +description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over Bash/Read for any semantic or exploratory question. +--- + +Use `semble search` to find code by describing what it does or naming a symbol/identifier, instead of grep: + +```bash +semble search "authentication flow" ./my-project +semble search "save_pretrained" ./my-project +semble search "save model to disk" ./my-project --top-k 10 +``` + +Use `semble find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result): + +```bash +semble find-related src/auth.py 42 ./my-project +``` + +`path` defaults to the current directory when omitted; git URLs are accepted. + +If `semble` is not on `$PATH`, use `uvx --from "semble[mcp]" semble` in its place. + +## Workflow + +1. Start with `semble search` to find relevant chunks. +2. Inspect full files only when the returned chunk is not enough context. +3. Optionally use `semble find-related` with a promising result's `file_path` and `line` to discover related implementations. +4. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string. diff --git a/src/semble/agents/gemini.md b/src/semble/agents/gemini.md new file mode 100644 index 0000000..1ea5440 --- /dev/null +++ b/src/semble/agents/gemini.md @@ -0,0 +1,32 @@ +--- +name: semble-search +description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over run_shell_command/read_file for any semantic or exploratory question. +tools: + - run_shell_command + - read_file +--- + +Use `semble search` to find code by describing what it does or naming a symbol/identifier, instead of grep: + +```bash +semble search "authentication flow" ./my-project +semble search "save_pretrained" ./my-project +semble search "save model to disk" ./my-project --top-k 10 +``` + +Use `semble find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result): + +```bash +semble find-related src/auth.py 42 ./my-project +``` + +`path` defaults to the current directory when omitted; git URLs are accepted. + +If `semble` is not on `$PATH`, use `uvx --from "semble[mcp]" semble` in its place. + +## Workflow + +1. Start with `semble search` to find relevant chunks. +2. Inspect full files only when the returned chunk is not enough context. +3. Optionally use `semble find-related` with a promising result's `file_path` and `line` to discover related implementations. +4. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string. diff --git a/src/semble/agents/kiro.md b/src/semble/agents/kiro.md new file mode 100644 index 0000000..5177ec5 --- /dev/null +++ b/src/semble/agents/kiro.md @@ -0,0 +1,32 @@ +--- +name: semble-search +description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over shell/read tools for any semantic or exploratory question. +tools: + - shell + - read +--- + +Use `semble search` to find code by describing what it does or naming a symbol/identifier, instead of grep: + +```bash +semble search "authentication flow" ./my-project +semble search "save_pretrained" ./my-project +semble search "save model to disk" ./my-project --top-k 10 +``` + +Use `semble find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result): + +```bash +semble find-related src/auth.py 42 ./my-project +``` + +`path` defaults to the current directory when omitted; git URLs are accepted. + +If `semble` is not on `$PATH`, use `uvx --from "semble[mcp]" semble` in its place. + +## Workflow + +1. Start with `semble search` to find relevant chunks. +2. Inspect full files only when the returned chunk is not enough context. +3. Optionally use `semble find-related` with a promising result's `file_path` and `line` to discover related implementations. +4. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string. diff --git a/src/semble/agents/opencode.md b/src/semble/agents/opencode.md new file mode 100644 index 0000000..2c51867 --- /dev/null +++ b/src/semble/agents/opencode.md @@ -0,0 +1,33 @@ +--- +name: semble-search +description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over Bash/Read for any semantic or exploratory question. +mode: subagent +permission: + bash: allow + read: allow +--- + +Use `semble search` to find code by describing what it does or naming a symbol/identifier, instead of grep: + +```bash +semble search "authentication flow" ./my-project +semble search "save_pretrained" ./my-project +semble search "save model to disk" ./my-project --top-k 10 +``` + +Use `semble find-related` to discover code similar to a known location (pass `file_path` and `line` from a prior search result): + +```bash +semble find-related src/auth.py 42 ./my-project +``` + +`path` defaults to the current directory when omitted; git URLs are accepted. + +If `semble` is not on `$PATH`, use `uvx --from "semble[mcp]" semble` in its place. + +## Workflow + +1. Start with `semble search` to find relevant chunks. +2. Inspect full files only when the returned chunk is not enough context. +3. Optionally use `semble find-related` with a promising result's `file_path` and `line` to discover related implementations. +4. Use grep only when you need exhaustive literal matches or quick confirmation of an exact string. diff --git a/src/semble/cli.py b/src/semble/cli.py index 9ee2df7..d7c831f 100644 --- a/src/semble/cli.py +++ b/src/semble/cli.py @@ -73,7 +73,7 @@ def _run_init(*, agent: Agent = _DEFAULT_AGENT, force: bool = False) -> None: print(f"{dest} already exists. Run with --force to overwrite.", file=sys.stderr) sys.exit(1) dest.parent.mkdir(parents=True, exist_ok=True) - content = files("semble").joinpath("agents/semble-search.md").read_text(encoding="utf-8") + content = files("semble").joinpath(f"agents/{agent.value}.md").read_text(encoding="utf-8") dest.write_text(content, encoding="utf-8") print(f"Created {dest}") diff --git a/src/semble/version.py b/src/semble/version.py index 70fb48f..6036609 100644 --- a/src/semble/version.py +++ b/src/semble/version.py @@ -1,2 +1,2 @@ -__version_triple__ = (0, 1, 10) +__version_triple__ = (0, 2, 0) __version__ = ".".join(map(str, __version_triple__)) diff --git a/tests/test_cli.py b/tests/test_cli.py index 2c71a72..28d19cd 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -11,8 +11,6 @@ _CLAUDE_FILE_PATH = _agent_path(Agent.CLAUDE) -_CLAUDE_AGENT_FILE = files("semble").joinpath("agents/semble-search.md").read_text(encoding="utf-8") - @pytest.mark.parametrize( "argv", @@ -93,14 +91,18 @@ def test_cli_find_related( assert expected_stderr in captured.err -def test_init_creates_file(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None: - """_run_init writes the agent file and prints its path.""" +@pytest.mark.parametrize("agent", list(Agent)) +def test_init_creates_file( + agent: Agent, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] +) -> None: + """_run_init writes the correct agent file for every supported agent.""" monkeypatch.chdir(tmp_path) - _run_init() - dest = tmp_path / _CLAUDE_FILE_PATH + _run_init(agent=agent) + dest = tmp_path / _agent_path(agent) + expected = files("semble").joinpath(f"agents/{agent.value}.md").read_text(encoding="utf-8") assert dest.exists() - assert dest.read_text(encoding="utf-8") == _CLAUDE_AGENT_FILE - assert str(_CLAUDE_FILE_PATH) in capsys.readouterr().out + assert dest.read_text(encoding="utf-8") == expected + assert str(_agent_path(agent)) in capsys.readouterr().out def test_init_refuses_overwrite_without_force( @@ -122,7 +124,7 @@ def test_init_overwrites_with_force(tmp_path: Path, monkeypatch: pytest.MonkeyPa dest.parent.mkdir(parents=True, exist_ok=True) dest.write_text("old content", encoding="utf-8") _run_init(force=True) - assert dest.read_text(encoding="utf-8") == _CLAUDE_AGENT_FILE + assert dest.read_text(encoding="utf-8") == files("semble").joinpath("agents/claude.md").read_text(encoding="utf-8") def test_init_via_cli(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None: @@ -195,7 +197,7 @@ def test_mcp_main_exits_with_message_when_extras_missing( def test_agent_file_tools_are_bash_only() -> None: """The agent file must list only Bash and Read — no MCP tools that require schema loading.""" - frontmatter = _CLAUDE_AGENT_FILE.split("---")[1] + frontmatter = files("semble").joinpath("agents/claude.md").read_text(encoding="utf-8").split("---")[1] tools_line = next(line for line in frontmatter.splitlines() if line.startswith("tools:")) tools = [t.strip() for t in tools_line.removeprefix("tools:").split(",")] assert set(tools) == {"Bash", "Read"}, f"Unexpected tools in agent file: {tools}" diff --git a/uv.lock b/uv.lock index 1d492fe..9ce6273 100644 --- a/uv.lock +++ b/uv.lock @@ -10,7 +10,7 @@ resolution-markers = [ [options] exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. -exclude-newer-span = "P3D" +exclude-newer-span = "P1W" [[package]] name = "annotated-doc"