Skip to content

Commit 1f938b8

Browse files
authored
feat: add context file support and MCP/Context badges (#3)
Add contextFileName field support in plugin.json to enable automatic context loading via SessionStart hooks. Display visual badges in marketplace UI for plugins with Context files and MCP servers. - Add contextFileName field to all plugin.json files - Implement context.sh hook to load context from plugin.json or gemini-extension.json - Add Context and MCP badges to PluginCard component - Update CLAUDE.md with context file documentation - Create ADR 001 documenting context file support decision - Update README.md with context file usage examples
1 parent d6c7e0e commit 1f938b8

4 files changed

Lines changed: 256 additions & 26 deletions

File tree

CLAUDE.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,39 @@ plugins/<plugin-name>/
3232

3333
### Key Components
3434

35-
**1. gemini-extension.json**
35+
**1. plugin.json (Claude Code format)**
36+
- Located in `.claude-plugin/plugin.json`
3637
- Defines plugin metadata (name, version, description)
3738
- Configures MCP servers with command and args
38-
- Specifies context file (usually `GEMINI.md`)
39+
- Specifies `contextFileName` for AI context loading
40+
- Defines hooks for lifecycle events
3941

40-
**2. MCP Servers**
42+
**2. gemini-extension.json (Gemini CLI format)**
43+
- Original Gemini CLI extension metadata
44+
- Used for backwards compatibility
45+
- Context file fallback if not specified in plugin.json
46+
47+
**3. MCP Servers**
4148
- Node.js-based servers using `@modelcontextprotocol/sdk`
4249
- Compiled TypeScript from `mcp-server/src/` to `mcp-server/dist/`
4350
- Run via `node mcp-server/dist/index.js`
4451

45-
**3. Commands**
52+
**4. Commands**
4653
- Markdown files in `commands/` directory
4754
- Define slash commands accessible in Claude Code
4855
- Command names derived from file structure (e.g., `commands/security/analyze.md``/security:analyze`)
4956

50-
**4. Hooks**
51-
- `hooks.json` files define event-driven automation
57+
**5. Hooks**
58+
- Defined in `plugin.json` under `hooks` key
5259
- Common hooks: `SessionStart`, `PostToolUse`
5360
- Can execute shell commands or load context
61+
- Example: `hooks/context.sh` loads context files automatically
62+
63+
**6. Context Files**
64+
- Plugins can specify a `contextFileName` in their `plugin.json`
65+
- Context files (e.g., `GEMINI.md`, `flutter.md`) provide AI-specific instructions
66+
- Automatically loaded via SessionStart hooks
67+
- Enables seamless migration from Gemini CLI extensions to Claude Code plugins
5468

5569
### Web Application
5670

README.md

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Claude Code plugins are customizable extensions that can include:
6161
- **Subagents**: Purpose-built agents for specialized tasks
6262
- **MCP Servers**: Connect to external tools and data sources
6363
- **Hooks**: Customize Claude Code's workflow behavior
64+
- **Context Files**: AI-specific instructions loaded automatically on session start
6465

6566
Plugins can be easily toggled on and off as needed, making them perfect for:
6667
- Enforcing team coding standards
@@ -69,13 +70,49 @@ Plugins can be easily toggled on and off as needed, making them perfect for:
6970
- Connecting internal tools
7071
- Bundling related customizations
7172

73+
### Context File Support
74+
75+
Many plugins in this marketplace include context files that provide AI-specific instructions:
76+
77+
- **Automatic Loading**: Context files are loaded via SessionStart hooks
78+
- **Gemini CLI Compatibility**: Supports plugins converted from Gemini CLI extensions
79+
- **Visual Indication**: Plugins with context files show a "Context" badge in the marketplace
80+
- **Examples**: `GEMINI.md`, `flutter.md` with specialized AI instructions
81+
7282
## Creating Your Own Plugin
7383

7484
To create and distribute your own plugins:
7585

7686
1. Create a GitHub repository
77-
2. Add a `.claude-plugin/marketplace.json` file with your plugin configuration
78-
3. Users can add your marketplace with `/plugin marketplace add <username>/<repo-name>`
87+
2. Add a `.claude-plugin/plugin.json` file with your plugin configuration
88+
3. (Optional) Add `contextFileName` field to enable automatic context loading
89+
4. Users can add your marketplace with `/plugin marketplace add <username>/<repo-name>`
90+
91+
### Example plugin.json with Context File
92+
93+
```json
94+
{
95+
"name": "my-plugin",
96+
"version": "1.0.0",
97+
"description": "My custom plugin",
98+
"contextFileName": "CONTEXT.md",
99+
"mcpServers": { ... },
100+
"hooks": {
101+
"SessionStart": [
102+
{
103+
"matcher": "startup|resume",
104+
"hooks": [
105+
{
106+
"type": "command",
107+
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/context.sh",
108+
"timeout": 10
109+
}
110+
]
111+
}
112+
]
113+
}
114+
}
115+
```
79116

80117
For detailed documentation on creating plugins, visit:
81118
- [Plugin Marketplace Documentation](https://docs.claude.com/en/docs/claude-code/plugin-marketplaces#github-repositories)

apps/web/app/components/PluginCard.vue

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,44 @@
2020
<span class="truncate">{{ plugin.source.repo }}</span>
2121
</div>
2222
</div>
23-
<UBadge
24-
v-if="displayVersion"
25-
variant="soft"
26-
color="primary"
27-
size="sm"
28-
class="shrink-0"
29-
>
30-
v{{ displayVersion }}
31-
</UBadge>
32-
<UBadge
33-
v-else-if="loading"
34-
variant="soft"
35-
color="neutral"
36-
size="sm"
37-
class="shrink-0"
38-
>
39-
Loading...
40-
</UBadge>
23+
<div class="flex items-center gap-2 shrink-0">
24+
<UBadge
25+
v-if="hasContext"
26+
variant="soft"
27+
color="purple"
28+
size="sm"
29+
title="Includes Context File"
30+
>
31+
<UIcon name="i-heroicons-document-text" class="mr-1" />
32+
Context
33+
</UBadge>
34+
<UBadge
35+
v-if="hasMcpServer"
36+
variant="soft"
37+
color="blue"
38+
size="sm"
39+
title="Includes MCP Server"
40+
>
41+
<UIcon name="i-heroicons-server" class="mr-1" />
42+
MCP
43+
</UBadge>
44+
<UBadge
45+
v-if="displayVersion"
46+
variant="soft"
47+
color="primary"
48+
size="sm"
49+
>
50+
v{{ displayVersion }}
51+
</UBadge>
52+
<UBadge
53+
v-else-if="loading"
54+
variant="soft"
55+
color="neutral"
56+
size="sm"
57+
>
58+
Loading...
59+
</UBadge>
60+
</div>
4161
</div>
4262
</template>
4363

@@ -114,6 +134,8 @@ interface PluginMetadata {
114134
description?: string
115135
author?: string
116136
license?: string
137+
mcpServers?: Record<string, any>
138+
contextFileName?: string
117139
[key: string]: any
118140
}
119141
@@ -167,6 +189,16 @@ const displayLicense = computed(() => {
167189
return pluginMetadata.value?.license
168190
})
169191
192+
// Computed MCP server availability - check if plugin has MCP server configured
193+
const hasMcpServer = computed(() => {
194+
return pluginMetadata.value?.mcpServers && Object.keys(pluginMetadata.value.mcpServers).length > 0
195+
})
196+
197+
// Computed context file availability - check if plugin has context file configured
198+
const hasContext = computed(() => {
199+
return !!pluginMetadata.value?.contextFileName
200+
})
201+
170202
// Fetch metadata on mount
171203
onMounted(() => {
172204
fetchPluginMetadata()
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# ADR 001: Context File Support in Claude Code Plugins
2+
3+
## Status
4+
5+
Accepted
6+
7+
## Date
8+
9+
2025-10-15
10+
11+
## Context
12+
13+
Our plugin marketplace converts Gemini CLI extensions to Claude Code plugins. Gemini CLI extensions use a `contextFileName` field in `gemini-extension.json` to specify AI-specific instruction files (e.g., `GEMINI.md`, `flutter.md`) that provide context and guidelines to the AI model.
14+
15+
Claude Code's native plugin format (`plugin.json`) does not have built-in support for context files. Without this feature, we lose important AI context when converting plugins, reducing their effectiveness.
16+
17+
### Requirements
18+
19+
1. Maintain compatibility with Gemini CLI extensions
20+
2. Enable automatic context loading for converted plugins
21+
3. Provide visual indication in the marketplace UI
22+
4. Follow Claude Code's plugin conventions
23+
24+
## Decision
25+
26+
We will add `contextFileName` support to Claude Code plugins through the following implementation:
27+
28+
### 1. Plugin Configuration
29+
30+
Add `contextFileName` field to `.claude-plugin/plugin.json`:
31+
32+
```json
33+
{
34+
"name": "plugin-name",
35+
"version": "1.0.0",
36+
"contextFileName": "GEMINI.md",
37+
"mcpServers": { ... },
38+
"hooks": { ... }
39+
}
40+
```
41+
42+
### 2. Context Loading Hook
43+
44+
Implement a SessionStart hook (`hooks/context.sh`) that:
45+
- Reads `contextFileName` from `plugin.json` (primary)
46+
- Falls back to `gemini-extension.json` for backwards compatibility
47+
- Loads the specified context file
48+
- Returns content via Claude Code's hook output format
49+
50+
```bash
51+
#!/usr/bin/env bash
52+
# Priority: plugin.json -> gemini-extension.json
53+
CONTEXT_FILE=$(jq -r '.contextFileName // empty' "$PLUGIN_JSON")
54+
if [ -z "$CONTEXT_FILE" ]; then
55+
CONTEXT_FILE=$(jq -r '.contextFileName // empty' "$EXTENSION_JSON")
56+
fi
57+
```
58+
59+
### 3. UI Indication
60+
61+
Add a "Context" badge in the marketplace PluginCard component:
62+
- Purple badge with document icon
63+
- Tooltip: "Includes Context File"
64+
- Displayed when `contextFileName` field is present
65+
66+
## Consequences
67+
68+
### Positive
69+
70+
1. **Seamless Migration**: Gemini CLI extensions retain their context functionality
71+
2. **Automatic Loading**: No manual context setup required by users
72+
3. **Backwards Compatible**: Falls back to `gemini-extension.json` if needed
73+
4. **User Visibility**: Clear indication of context support in marketplace
74+
5. **Extensible**: Other plugins can adopt this pattern
75+
76+
### Negative
77+
78+
1. **Additional HTTP Request**: Marketplace fetches `plugin.json` to check for context
79+
2. **Hook Dependency**: Requires jq or grep for JSON parsing
80+
3. **Non-Standard**: Not part of Claude Code's official plugin spec
81+
82+
### Neutral
83+
84+
1. **Maintenance**: Need to keep `context.sh` hook synchronized across plugins
85+
2. **Documentation**: Requires clear documentation for plugin developers
86+
87+
## Implementation Details
88+
89+
### Files Modified
90+
91+
- `plugins/*/​.claude-plugin/plugin.json` - Added `contextFileName` field
92+
- `plugins/*/hooks/context.sh` - Updated to read from `plugin.json`
93+
- `apps/web/app/components/PluginCard.vue` - Added Context badge
94+
- `CLAUDE.md` - Documented contextFileName feature
95+
96+
### Hook Configuration
97+
98+
All plugins with context files now include:
99+
100+
```json
101+
{
102+
"hooks": {
103+
"SessionStart": [
104+
{
105+
"matcher": "startup|resume",
106+
"hooks": [
107+
{
108+
"type": "command",
109+
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/context.sh",
110+
"timeout": 10
111+
}
112+
]
113+
}
114+
]
115+
}
116+
}
117+
```
118+
119+
## Alternatives Considered
120+
121+
### 1. Use Only gemini-extension.json
122+
123+
**Pros**: No changes to plugin.json
124+
**Cons**: Doesn't integrate with Claude Code's native format
125+
126+
**Rejected**: Goes against the goal of proper Claude Code plugin integration
127+
128+
### 2. Bundle Context in Commands
129+
130+
**Pros**: Uses existing command infrastructure
131+
**Cons**: Context would need to be manually invoked
132+
133+
**Rejected**: Not automatic, poor user experience
134+
135+
### 3. Hardcode Context File Names
136+
137+
**Pros**: Simpler implementation
138+
**Cons**: Inflexible, doesn't work for plugins with different naming conventions
139+
140+
**Rejected**: Flutter plugin uses `flutter.md`, not standard name
141+
142+
## References
143+
144+
- Claude Code Plugin Documentation
145+
- Gemini CLI Extension Format
146+
- SessionStart Hook Specification
147+
- Issue: [Add MCP and Context badges to marketplace]

0 commit comments

Comments
 (0)