Package the plugin for Codex from the same bundle
The Claude Code plugin moves to plugins/haiku-rag/ and gains a Codex manifest at .codex-plugin/plugin.json; both share one .mcp.json and one haiku-rag Agent Skill. .agents/plugins/marketplace.json serves Codex, the Claude marketplace points at the new path, and scripts/bump_version.py bumps both manifests. The skill declares its compatibility.
This commit is contained in:
parent
110adf23ee
commit
d7c131bc28
12 changed files with 131 additions and 35 deletions
20
.agents/plugins/marketplace.json
Normal file
20
.agents/plugins/marketplace.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "haiku-rag",
|
||||
"interface": {
|
||||
"displayName": "haiku.rag"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "haiku-rag",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./plugins/haiku-rag"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Productivity"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -7,8 +7,8 @@
|
|||
"plugins": [
|
||||
{
|
||||
"name": "haiku-rag",
|
||||
"source": "./claude-plugin",
|
||||
"description": "Search, read and question your haiku.rag knowledge base from Claude Code."
|
||||
"source": "./plugins/haiku-rag",
|
||||
"description": "Search, read and analyze your haiku.rag knowledge base from Claude Code."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@
|
|||
|
||||
### Added
|
||||
|
||||
- Claude Code plugin under `claude-plugin/`: the server configuration and the
|
||||
`haiku-rag` skill. `claude plugin marketplace add ggozad/haiku.rag`, then
|
||||
`claude plugin install haiku-rag`.
|
||||
- Claude Code and Codex plugin under `plugins/haiku-rag/`: two client manifests
|
||||
sharing the server configuration and the `haiku-rag` Agent Skill.
|
||||
- MCP tool `execute_code(code, filter, sources)`: runs a program in the
|
||||
analysis sandbox over the selected documents and returns what it printed;
|
||||
one sandbox per call.
|
||||
|
|
|
|||
11
README.md
11
README.md
|
|
@ -110,7 +110,7 @@ For direct agent composition, see the [capabilities documentation](https://ggoza
|
|||
|
||||
## MCP Server
|
||||
|
||||
Use with AI assistants like Claude Code and Claude Desktop:
|
||||
Use with AI assistants like Claude Code, Codex, and Claude Desktop:
|
||||
|
||||
```bash
|
||||
haiku-rag mcp --stdio
|
||||
|
|
@ -123,6 +123,13 @@ claude plugin marketplace add ggozad/haiku.rag
|
|||
claude plugin install haiku-rag
|
||||
```
|
||||
|
||||
In Codex, install the same plugin from its marketplace:
|
||||
|
||||
```bash
|
||||
codex plugin marketplace add ggozad/haiku.rag
|
||||
codex plugin add haiku-rag@haiku-rag
|
||||
```
|
||||
|
||||
Add to your Claude Desktop configuration:
|
||||
|
||||
```json
|
||||
|
|
@ -136,7 +143,7 @@ Add to your Claude Desktop configuration:
|
|||
}
|
||||
```
|
||||
|
||||
Provides search, document, QA, and analysis tools directly in your AI assistant.
|
||||
Provides search, document reading, and analysis tools directly in your AI assistant.
|
||||
|
||||
## Examples
|
||||
|
||||
|
|
|
|||
30
docs/mcp.md
30
docs/mcp.md
|
|
@ -57,10 +57,34 @@ plugin:
|
|||
claude mcp add haiku-rag -- haiku-rag mcp --stdio
|
||||
```
|
||||
|
||||
The skill works with that registration too: copy `claude-plugin/skills/haiku-rag`
|
||||
The skill works with that registration too: copy `plugins/haiku-rag/skills/haiku-rag`
|
||||
into `~/.claude/skills/` and change the tool prefix in its `allowed-tools` from
|
||||
`mcp__plugin_haiku-rag_haiku-rag__` to `mcp__haiku-rag__`.
|
||||
|
||||
## Codex
|
||||
|
||||
The repository's Codex plugin registers the server and installs the same Agent
|
||||
Skill:
|
||||
|
||||
```bash
|
||||
codex plugin marketplace add ggozad/haiku.rag
|
||||
codex plugin add haiku-rag@haiku-rag
|
||||
```
|
||||
|
||||
The plugin runs `haiku-rag mcp --stdio`, so `haiku-rag` must be on the PATH.
|
||||
Invoke the skill as `$haiku-rag`. Codex can also select it automatically from
|
||||
its description. To register the server without the plugin:
|
||||
|
||||
```bash
|
||||
codex mcp add haiku-rag -- haiku-rag mcp --stdio
|
||||
```
|
||||
|
||||
The skill works with that registration too: copy
|
||||
`plugins/haiku-rag/skills/haiku-rag` into `~/.agents/skills/`.
|
||||
The `allowed-tools` field supplies Claude Code's tool pre-approval and may be
|
||||
ignored by other Agent Skills clients. Codex configures MCP tool approvals
|
||||
separately in `config.toml`.
|
||||
|
||||
## Claude Desktop Integration
|
||||
|
||||
Add to your Claude Desktop configuration (`claude_desktop_config.json`):
|
||||
|
|
@ -168,8 +192,8 @@ traceback goes to the server log.
|
|||
|
||||
The server publishes `instructions` describing the knowledge base: what it
|
||||
holds, when to reach for it, the collection names when it covers several, and
|
||||
`prompts.domain_preamble` when set. Claude Code shows them to the model. Claude
|
||||
Desktop does not, so every tool description stands on its own.
|
||||
`prompts.domain_preamble` when set. Claude Code and Codex show them to the
|
||||
model. Claude Desktop does not, so every tool description stands on its own.
|
||||
|
||||
## Continuous ingestion
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "haiku-rag",
|
||||
"version": "0.82.1",
|
||||
"description": "Search, read and question your haiku.rag knowledge base from Claude Code.",
|
||||
"description": "Search, read and analyze your haiku.rag knowledge base from Claude Code.",
|
||||
"author": {
|
||||
"name": "Yiorgis Gozadinos",
|
||||
"email": "ggozadinos@gmail.com"
|
||||
26
plugins/haiku-rag/.codex-plugin/plugin.json
Normal file
26
plugins/haiku-rag/.codex-plugin/plugin.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "haiku-rag",
|
||||
"version": "0.82.1",
|
||||
"description": "Search, read and analyze your haiku.rag knowledge base from Codex.",
|
||||
"author": {
|
||||
"name": "Yiorgis Gozadinos",
|
||||
"email": "ggozadinos@gmail.com",
|
||||
"url": "https://github.com/ggozad"
|
||||
},
|
||||
"homepage": "https://ggozad.github.io/haiku.rag/mcp/",
|
||||
"repository": "https://github.com/ggozad/haiku.rag",
|
||||
"license": "MIT",
|
||||
"keywords": ["rag", "knowledge-base", "search", "documents", "mcp"],
|
||||
"skills": "./skills/",
|
||||
"mcpServers": "./.mcp.json",
|
||||
"interface": {
|
||||
"displayName": "haiku.rag",
|
||||
"shortDescription": "Search and analyze your haiku.rag knowledge base",
|
||||
"longDescription": "Search, read, and compute over documents in your local haiku.rag knowledge base through MCP tools.",
|
||||
"developerName": "Yiorgis Gozadinos",
|
||||
"category": "Productivity",
|
||||
"capabilities": ["Interactive", "Read"],
|
||||
"websiteURL": "https://ggozad.github.io/haiku.rag/",
|
||||
"defaultPrompt": "Search my haiku.rag knowledge base and cite the relevant documents."
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ description: Search, read and compute over the user's haiku.rag knowledge base
|
|||
from the user's ingested documents, when asked to find, look up, check or
|
||||
cite something in their documents or knowledge base, or when the question is
|
||||
about the user's own material rather than general knowledge.
|
||||
compatibility: Requires the haiku-rag MCP server to be registered in the client.
|
||||
allowed-tools:
|
||||
- mcp__plugin_haiku-rag_haiku-rag__search_documents
|
||||
- mcp__plugin_haiku-rag_haiku-rag__search_documents_by_image
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
"""
|
||||
Version bumping script for haiku.rag workspace.
|
||||
|
||||
Updates version in all pyproject.toml files, the Claude Code plugin manifest
|
||||
and CHANGELOG.md.
|
||||
Updates version in all pyproject.toml files, both plugin manifests, and
|
||||
CHANGELOG.md.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
|
@ -56,7 +56,7 @@ def update_example_dependencies(file_path: Path, new_version: str) -> None:
|
|||
|
||||
|
||||
def update_plugin_version(file_path: Path, new_version: str) -> None:
|
||||
"""Update the version in the Claude Code plugin manifest."""
|
||||
"""Update the version in a plugin manifest."""
|
||||
content = file_path.read_text()
|
||||
updated = re.sub(
|
||||
r'^(\s*"version": )"[^"]+"',
|
||||
|
|
@ -136,12 +136,15 @@ def main():
|
|||
root / "app" / "backend" / "pyproject.toml",
|
||||
]
|
||||
|
||||
plugin_file = root / "claude-plugin" / ".claude-plugin" / "plugin.json"
|
||||
plugin_files = [
|
||||
root / "plugins" / "haiku-rag" / ".claude-plugin" / "plugin.json",
|
||||
root / "plugins" / "haiku-rag" / ".codex-plugin" / "plugin.json",
|
||||
]
|
||||
changelog_file = root / "CHANGELOG.md"
|
||||
|
||||
# Check all files exist
|
||||
for file in (
|
||||
pyproject_files + example_pyproject_files + [plugin_file, changelog_file]
|
||||
pyproject_files + example_pyproject_files + plugin_files + [changelog_file]
|
||||
):
|
||||
if not file.exists():
|
||||
print(f"Error: {file} not found")
|
||||
|
|
@ -172,7 +175,8 @@ def main():
|
|||
for file in example_pyproject_files:
|
||||
update_example_dependencies(file, new_version)
|
||||
|
||||
update_plugin_version(plugin_file, new_version)
|
||||
for file in plugin_files:
|
||||
update_plugin_version(file, new_version)
|
||||
|
||||
# Update CHANGELOG.md
|
||||
update_changelog(changelog_file, new_version)
|
||||
|
|
|
|||
|
|
@ -27,12 +27,15 @@ def test_update_plugin_version_rewrites_only_the_version_field(tmp_path, monkeyp
|
|||
assert manifest.read_text().endswith("}\n")
|
||||
|
||||
|
||||
def test_the_shipped_plugin_manifest_carries_the_package_version():
|
||||
def test_the_shipped_plugin_manifests_carry_the_package_version():
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
plugin = json.loads(
|
||||
(root / "claude-plugin" / ".claude-plugin" / "plugin.json").read_text()
|
||||
)
|
||||
|
||||
assert plugin["version"] == bump_version.get_current_version(
|
||||
package_version = bump_version.get_current_version(
|
||||
root / "haiku_rag_slim" / "pyproject.toml"
|
||||
)
|
||||
for client in ("claude", "codex"):
|
||||
manifest = json.loads(
|
||||
(
|
||||
root / "plugins" / "haiku-rag" / f".{client}-plugin" / "plugin.json"
|
||||
).read_text()
|
||||
)
|
||||
assert manifest["version"] == package_version
|
||||
|
|
|
|||
|
|
@ -1158,27 +1158,39 @@ class TestMCPErrorContract:
|
|||
)
|
||||
|
||||
|
||||
class TestClaudeCodePlugin:
|
||||
"""The plugin under claude-plugin/ points at the server this module builds."""
|
||||
class TestAgentPlugins:
|
||||
"""The shared Claude Code and Codex plugin points at this MCP server."""
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
|
||||
def test_the_manifests_name_the_plugin_and_its_server(self):
|
||||
import json
|
||||
|
||||
plugin = json.loads(
|
||||
(self.root / "claude-plugin/.claude-plugin/plugin.json").read_text()
|
||||
claude_plugin = json.loads(
|
||||
(self.root / "plugins/haiku-rag/.claude-plugin/plugin.json").read_text()
|
||||
)
|
||||
marketplace = json.loads(
|
||||
codex_plugin = json.loads(
|
||||
(self.root / "plugins/haiku-rag/.codex-plugin/plugin.json").read_text()
|
||||
)
|
||||
claude_marketplace = json.loads(
|
||||
(self.root / ".claude-plugin/marketplace.json").read_text()
|
||||
)
|
||||
servers = json.loads((self.root / "claude-plugin/.mcp.json").read_text())
|
||||
codex_marketplace = json.loads(
|
||||
(self.root / ".agents/plugins/marketplace.json").read_text()
|
||||
)
|
||||
servers = json.loads((self.root / "plugins/haiku-rag/.mcp.json").read_text())
|
||||
|
||||
assert plugin["name"] == "haiku-rag"
|
||||
assert plugin["description"]
|
||||
[entry] = marketplace["plugins"]
|
||||
assert entry["name"] == plugin["name"]
|
||||
assert entry["source"] == "./claude-plugin"
|
||||
assert claude_plugin["name"] == codex_plugin["name"] == "haiku-rag"
|
||||
assert claude_plugin["description"]
|
||||
assert codex_plugin["description"]
|
||||
assert codex_plugin["skills"] == "./skills/"
|
||||
assert codex_plugin["mcpServers"] == "./.mcp.json"
|
||||
[claude_entry] = claude_marketplace["plugins"]
|
||||
assert claude_entry["name"] == claude_plugin["name"]
|
||||
assert claude_entry["source"] == "./plugins/haiku-rag"
|
||||
[codex_entry] = codex_marketplace["plugins"]
|
||||
assert codex_entry["name"] == codex_plugin["name"]
|
||||
assert codex_entry["source"]["path"] == "./plugins/haiku-rag"
|
||||
assert servers["mcpServers"]["haiku-rag"]["args"] == ["mcp", "--stdio"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -1187,7 +1199,7 @@ class TestClaudeCodePlugin:
|
|||
):
|
||||
import yaml
|
||||
|
||||
text = (self.root / "claude-plugin/skills/haiku-rag/SKILL.md").read_text()
|
||||
text = (self.root / "plugins/haiku-rag/skills/haiku-rag/SKILL.md").read_text()
|
||||
_, frontmatter, _ = text.split("---", 2)
|
||||
skill = yaml.safe_load(frontmatter)
|
||||
prefix = "mcp__plugin_haiku-rag_haiku-rag__"
|
||||
|
|
|
|||
Loading…
Reference in a new issue