chore: remove hello-world demo plugin
No longer needed — kyberforge plugin-create provides a bundled template that serves as the canonical scaffold reference. Remove hello-world from marketplace manifests and update docs accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "hello-world",
|
||||
"displayName": "Hello World",
|
||||
"description": "A complete scaffold demonstrating every cross-compatible plugin feature for the holocron marketplace.",
|
||||
"author": { "name": "Your Name", "url": "https://github.com/your-org/ai-development" },
|
||||
"homepage": "https://github.com/your-org/ai-development",
|
||||
"license": "MIT",
|
||||
"keywords": ["scaffold", "example", "holocron"]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"hello-world": {
|
||||
"type": "stdio",
|
||||
"command": "node",
|
||||
"args": ["${CLAUDE_PLUGIN_ROOT}/bin/mcp-server.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
# hello-world
|
||||
|
||||
Complete scaffold plugin for the **holocron** marketplace. Every cross-compatible component
|
||||
is included with a working stub. Copy this directory, rename it, and replace the stubs with
|
||||
your actual content.
|
||||
|
||||
## Directory layout
|
||||
|
||||
```
|
||||
hello-world/
|
||||
├── plugin.json # Copilot CLI manifest — declares component paths
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Claude Code manifest — no component paths (uses defaults)
|
||||
├── skills/
|
||||
│ └── hello-world/
|
||||
│ └── SKILL.md # ✅ identical for both tools
|
||||
├── agents/
|
||||
│ ├── hello-world.md # Claude Code agent (no frontmatter)
|
||||
│ └── hello-world.agent.md # Copilot CLI agent (YAML frontmatter + tools:)
|
||||
├── hooks/
|
||||
│ └── hooks.json # Claude Code hooks (PostToolUse / PreToolUse events)
|
||||
├── hooks.json # Copilot CLI hooks (session_start / session_end events)
|
||||
├── .mcp.json # ✅ MCP server config — identical for both tools
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Cross-compatibility notes
|
||||
|
||||
| Component | Claude Code path | Copilot CLI path | Portable? |
|
||||
|---|---|---|---|
|
||||
| Plugin manifest | `.claude-plugin/plugin.json` | `plugin.json` at root | Ship both |
|
||||
| Skills | `skills/<name>/SKILL.md` | `skills/<name>/SKILL.md` | ✅ Identical |
|
||||
| Agents | `agents/<name>.md` | `agents/<name>.agent.md` | Ship both |
|
||||
| Hooks | `hooks/hooks.json` | `hooks.json` at root | Ship both |
|
||||
| MCP servers | `.mcp.json` at root | `.mcp.json` at root | ✅ Identical |
|
||||
|
||||
## Install via marketplace
|
||||
|
||||
```bash
|
||||
# Claude Code
|
||||
claude plugin marketplace add <owner>/ai-development
|
||||
claude plugin install hello-world@holocron
|
||||
|
||||
# GitHub Copilot CLI
|
||||
copilot plugin marketplace add <owner>/ai-development
|
||||
copilot plugin install hello-world
|
||||
```
|
||||
|
||||
## Local dev install
|
||||
|
||||
```bash
|
||||
# Claude Code
|
||||
claude --plugin-dir ./plugins/hello-world
|
||||
|
||||
# GitHub Copilot CLI
|
||||
copilot plugin install ./plugins/hello-world
|
||||
```
|
||||
|
||||
## Validate (Claude Code)
|
||||
|
||||
```bash
|
||||
claude plugin validate ./plugins/hello-world
|
||||
```
|
||||
|
||||
Copilot CLI has no validate command — run `copilot plugin install ./plugins/hello-world`
|
||||
and check that `/skills list` and `/agent` surface the expected entries.
|
||||
|
||||
## Creating a new plugin from this scaffold
|
||||
|
||||
1. Copy `plugins/hello-world/` → `plugins/<your-plugin-name>/`
|
||||
2. Update `name` in both `plugin.json` files
|
||||
3. Replace `skills/hello-world/SKILL.md` with your skill(s)
|
||||
4. Replace or remove `agents/` files — only include if your plugin ships an agent
|
||||
5. Replace or remove `hooks/` files — only include if your plugin reacts to events
|
||||
6. Replace or remove `.mcp.json` — only include if your plugin ships an MCP server
|
||||
7. Add the new plugin to `.claude-plugin/marketplace.json`
|
||||
8. Run `claude plugin validate ./plugins/<your-plugin-name>`
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
name: hello-world
|
||||
description: A demonstration agent for the holocron marketplace scaffold. Confirms agent loading works in GitHub Copilot CLI.
|
||||
tools:
|
||||
- read_file
|
||||
- list_directory
|
||||
---
|
||||
|
||||
You are a demonstration agent included in the `hello-world` scaffold plugin for the **holocron** marketplace.
|
||||
|
||||
When invoked, greet the user, confirm the agent is loaded, and list the components available in this plugin: skills (`skills/`), agents (`agents/`), hooks (`hooks.json`), and MCP servers (`.mcp.json`).
|
||||
|
||||
Replace this file with your agent's actual system prompt and instructions.
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
name: hello-world
|
||||
description: A demonstration agent for the holocron marketplace scaffold. Confirms agent loading works in Claude Code.
|
||||
---
|
||||
|
||||
You are a demonstration agent included in the `hello-world` scaffold plugin for the **holocron** marketplace.
|
||||
|
||||
When invoked, greet the user, confirm the agent is loaded, and list the components available in this plugin: skills (`skills/`), agents (`agents/`), hooks (`hooks/hooks.json`), and MCP servers (`.mcp.json`).
|
||||
|
||||
Replace this file with your agent's actual system prompt and instructions.
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
// Minimal MCP server — JSON-RPC 2.0 over stdio, no external dependencies.
|
||||
// Exposes one tool: `say_hello`. Replace with your actual tools.
|
||||
|
||||
const readline = require('readline');
|
||||
|
||||
const rl = readline.createInterface({ input: process.stdin, terminal: false });
|
||||
|
||||
function send(obj) {
|
||||
process.stdout.write(JSON.stringify(obj) + '\n');
|
||||
}
|
||||
|
||||
const TOOLS = [
|
||||
{
|
||||
name: 'say_hello',
|
||||
description: 'Say hello from the holocron marketplace hello-world plugin.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Name to greet (optional)' }
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
rl.on('line', (line) => {
|
||||
let msg;
|
||||
try { msg = JSON.parse(line); } catch { return; }
|
||||
|
||||
const { method, id, params } = msg;
|
||||
|
||||
if (method === 'initialize') {
|
||||
send({
|
||||
jsonrpc: '2.0', id,
|
||||
result: {
|
||||
protocolVersion: '2024-11-05',
|
||||
capabilities: { tools: {} },
|
||||
serverInfo: { name: 'hello-world', version: '1.0.0' }
|
||||
}
|
||||
});
|
||||
|
||||
} else if (method === 'notifications/initialized') {
|
||||
// no response required
|
||||
|
||||
} else if (method === 'tools/list') {
|
||||
send({ jsonrpc: '2.0', id, result: { tools: TOOLS } });
|
||||
|
||||
} else if (method === 'tools/call') {
|
||||
const toolName = params?.name;
|
||||
const args = params?.arguments ?? {};
|
||||
|
||||
if (toolName === 'say_hello') {
|
||||
const greeting = args.name
|
||||
? `Hello, ${args.name}! The holocron marketplace hello-world plugin is working.`
|
||||
: 'Hello from the holocron marketplace hello-world plugin!';
|
||||
send({ jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: greeting }] } });
|
||||
} else {
|
||||
send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${toolName}` } });
|
||||
}
|
||||
|
||||
} else if (id !== undefined) {
|
||||
send({ jsonrpc: '2.0', id, error: { code: -32601, message: 'Method not found' } });
|
||||
}
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => process.exit(0));
|
||||
process.on('SIGTERM', () => process.exit(0));
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"event": "session_start",
|
||||
"command": "echo '[hello-world] session started'"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo '[hello-world] PostToolUse fired'"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "hello-world",
|
||||
"description": "A complete scaffold demonstrating every cross-compatible plugin feature for the holocron marketplace.",
|
||||
"author": { "name": "Your Name", "email": "you@example.com" },
|
||||
"license": "MIT",
|
||||
"keywords": ["scaffold", "example", "holocron"],
|
||||
"agents": "agents/",
|
||||
"skills": ["skills/"],
|
||||
"hooks": "hooks.json",
|
||||
"mcpServers": ".mcp.json"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
name: hello-world
|
||||
description: Prove the holocron marketplace plugin is installed and working. Use when the user says "/hello-world", "test plugin install", or "is the holocron marketplace working". Do NOT use for any real task.
|
||||
metadata:
|
||||
category: cross-cutting
|
||||
---
|
||||
|
||||
Respond with exactly:
|
||||
|
||||
> Hello from the **holocron** marketplace! The `hello-world` plugin is installed and working.
|
||||
> Run `claude plugin list` to see all installed plugins.
|
||||
|
||||
Nothing else.
|
||||
@@ -1,106 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tests for plugins/hello-world/bin/mcp-server.js
|
||||
# Protocol: JSON-RPC 2.0 over stdio. Tests send input lines and assert on stdout.
|
||||
set -euo pipefail
|
||||
|
||||
SERVER="$(cd "$(dirname "$0")/../bin" && pwd)/mcp-server.js"
|
||||
PASS=0; FAIL=0
|
||||
|
||||
# ── helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
assert_contains() {
|
||||
local label="$1" expected="$2" actual="$3"
|
||||
if echo "$actual" | grep -qF -- "$expected"; then
|
||||
echo " PASS: $label"
|
||||
PASS=$((PASS+1))
|
||||
else
|
||||
echo " FAIL: $label"
|
||||
echo " expected to contain: $expected"
|
||||
echo " got: $actual"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
}
|
||||
|
||||
assert_not_contains() {
|
||||
local label="$1" unexpected="$2" actual="$3"
|
||||
if echo "$actual" | grep -qF -- "$unexpected"; then
|
||||
echo " FAIL: $label"
|
||||
echo " expected NOT to contain: $unexpected"
|
||||
echo " got: $actual"
|
||||
FAIL=$((FAIL+1))
|
||||
else
|
||||
echo " PASS: $label"
|
||||
PASS=$((PASS+1))
|
||||
fi
|
||||
}
|
||||
|
||||
# Send newline-separated JSON lines to the server, capture stdout
|
||||
run_server() {
|
||||
printf '%s\n' "$@" | node "$SERVER" 2>/dev/null
|
||||
}
|
||||
|
||||
# ── tests ────────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "initialize"
|
||||
OUT=$(run_server '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}},"id":1}')
|
||||
assert_contains "returns protocolVersion" '"protocolVersion":"2024-11-05"' "$OUT"
|
||||
assert_contains "returns capabilities" '"capabilities"' "$OUT"
|
||||
assert_contains "returns serverInfo name" '"name":"hello-world"' "$OUT"
|
||||
assert_contains "returns serverInfo version" '"version":"1.0.0"' "$OUT"
|
||||
assert_contains "echoes id" '"id":1' "$OUT"
|
||||
|
||||
echo "notifications/initialized"
|
||||
OUT=$(run_server '{"jsonrpc":"2.0","method":"notifications/initialized"}')
|
||||
assert_not_contains "no response for notification" '"jsonrpc"' "$OUT"
|
||||
|
||||
echo "tools/list"
|
||||
OUT=$(run_server \
|
||||
'{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}' \
|
||||
'{"jsonrpc":"2.0","method":"tools/list","id":2}')
|
||||
assert_contains "lists say_hello tool" '"name":"say_hello"' "$OUT"
|
||||
assert_contains "tool has description" '"description"' "$OUT"
|
||||
assert_contains "tool has inputSchema" '"inputSchema"' "$OUT"
|
||||
assert_contains "schema has name property" '"name"' "$OUT"
|
||||
assert_contains "echoes id 2" '"id":2' "$OUT"
|
||||
|
||||
echo "tools/call say_hello — no args"
|
||||
OUT=$(run_server \
|
||||
'{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}' \
|
||||
'{"jsonrpc":"2.0","method":"tools/call","params":{"name":"say_hello","arguments":{}},"id":3}')
|
||||
assert_contains "generic greeting content" 'Hello from the holocron' "$OUT"
|
||||
assert_contains "response has content array" '"content"' "$OUT"
|
||||
assert_contains "content type is text" '"type":"text"' "$OUT"
|
||||
|
||||
echo "tools/call say_hello — with name"
|
||||
OUT=$(run_server \
|
||||
'{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}' \
|
||||
'{"jsonrpc":"2.0","method":"tools/call","params":{"name":"say_hello","arguments":{"name":"Obi-Wan"}},"id":4}')
|
||||
assert_contains "personalised greeting" 'Hello, Obi-Wan!' "$OUT"
|
||||
assert_not_contains "not generic greeting" 'Hello from the holocron' "$OUT"
|
||||
|
||||
echo "tools/call — unknown tool"
|
||||
OUT=$(run_server \
|
||||
'{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}' \
|
||||
'{"jsonrpc":"2.0","method":"tools/call","params":{"name":"does_not_exist","arguments":{}},"id":5}')
|
||||
assert_contains "error code -32601" '"code":-32601' "$OUT"
|
||||
assert_contains "error field present" '"error"' "$OUT"
|
||||
|
||||
echo "unknown method with id"
|
||||
OUT=$(run_server \
|
||||
'{"jsonrpc":"2.0","method":"no_such_method","id":6}')
|
||||
assert_contains "error returned" '"error"' "$OUT"
|
||||
assert_contains "method not found code" '"code":-32601' "$OUT"
|
||||
assert_contains "echoes id 6" '"id":6' "$OUT"
|
||||
|
||||
echo "invalid JSON — no crash, process continues"
|
||||
OUT=$(run_server \
|
||||
'this is not json' \
|
||||
'{"jsonrpc":"2.0","method":"tools/list","id":7}')
|
||||
assert_contains "valid request after bad input succeeds" '"id":7' "$OUT"
|
||||
assert_not_contains "no error for bad json line" '"error"' "$OUT"
|
||||
|
||||
# ── summary ──────────────────────────────────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
echo "Results: $PASS passed, $FAIL failed"
|
||||
[[ $FAIL -eq 0 ]] && exit 0 || exit 1
|
||||
Reference in New Issue
Block a user