Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
{
"name": "MarvinOutputStyle",
"version": "1.3.2",
"version": "1.3.3",

@lukelabonte lukelabonte May 26, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MarvinOutputStyle, iOSSimulator, and PluginBase get patch bumps because their package contents changed from symlinked common directories to generated committed copies. SwiftScaffolding and XcodeBuildTools already had branch-local bumps, so the common-copy note is folded into those existing release entries instead of bumping them twice.

"description": "Adds Marvin the Paranoid Android personality - pessimistic and melancholic but brilliantly competent (mimics the deprecated Marvin output style)",
"source": "./MarvinOutputStyle",
"author": {
Expand All @@ -37,7 +37,7 @@
},
{
"name": "iOSSimulator",
"version": "0.6.4",
"version": "0.6.5",
"description": "Control iOS Simulators using native macOS tools - manage simulators, automate UI interactions, take screenshots, and more",
"source": "./iOSSimulator",
"author": {
Expand All @@ -56,7 +56,7 @@
},
{
"name": "SwiftScaffolding",
"version": "0.4.2",
"version": "0.4.3",
"description": "Swift project scaffolding and code generation tools",
"source": "./SwiftScaffolding",
"author": {
Expand All @@ -73,7 +73,7 @@
},
{
"name": "XcodeBuildTools",
"version": "0.5.9",
"version": "0.5.10",
"description": "Xcode development tools with optional Xcode MCP integration: build/test/run Swift packages, discover projects and schemes, build for simulator/device/macOS, run tests, manage device apps, capture simulator logs, Sparkle auto-update integration",
"source": "./XcodeBuildTools",
"author": {
Expand Down
63 changes: 0 additions & 63 deletions .claude/commands/update-plugin.md

This file was deleted.

40 changes: 40 additions & 0 deletions .claude/skills/update-plugin/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: update-plugin
description: Use when updating, versioning, tagging, or releasing a plugin in this Claude Code-compatible plugin marketplace.
---

# Update Plugin

Use this workflow when preparing a plugin update in this marketplace.

## Workflow

1. Inspect the diff.
- If `common/` changed, every plugin is affected.
- Run `scripts/sync-plugin-common.py` before editing versions so each plugin package has current copied helpers.
- If `common/hooks.json` changed, propagate the hook shape to each plugin's `hooks/hooks.json` while preserving plugin-specific command names.
2. Identify the plugin or plugins to update.
- Ask only if the changed plugin is unclear from the diff.
- Suggest a semantic version bump from the change scope.
3. Update version metadata.
- Update `<PluginDir>/.claude-plugin/plugin.json`.
- Update the matching entry in `.claude-plugin/marketplace.json`.
4. Document the change.
- Update the plugin README changelog.
- Add a matching entry to the plugin `info.json` `versions` array.
- If skills were added, removed, or renamed, update the plugin `info.json` `skills` array.
- If legacy command prompts are present, migrate them to skills before release.
5. Verify.
- Run `scripts/sync-plugin-common.py --check`.
- Run `python3 -m unittest discover -s tests -v`.
- Confirm plugin manifest, marketplace, README, and `info.json` versions match.
6. Commit and tag after the commit lands.
- Tag format: `{PluginName}--v{version}`.
- Push the tag with `git push origin {PluginName}--v{version}`.
- If multiple plugins were bumped, create and push one tag per plugin.

## Notes

- The installed plugin package must be self-contained. Do not edit copied `*/common/` files by hand; edit root `common/` and rerun `scripts/sync-plugin-common.py`.
- JSON files must remain valid.
- Plugin names must match folder names exactly.
7 changes: 3 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ those names as compatibility contracts, not as a reason to make agent-facing
instructions Claude-specific.

Use `CLAUDE.md` for the full repository architecture and release workflow. When
editing skills, commands, READMEs, or session-start context, prefer neutral
editing skills, READMEs, or session-start context, prefer neutral
terms like "agent", "assistant", "host", or "session" unless the text is about a
Claude Code-specific file, command, environment variable, or historical
changelog entry.

Claude-specific tool names are acceptable in Claude-specific metadata such as
slash-command `allowed-tools`. Keep the command body portable by asking for the
host's native mechanism instead of naming a specific tool.
Keep skill bodies portable by asking for the host's native mechanism instead of
naming a specific tool unless a plugin contract requires the concrete name.

Keep new runtime checks and packaging expectations covered by:

Expand Down
32 changes: 12 additions & 20 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The repository has a two-level architecture:
2. **Plugin Level** (subdirectories):
- Each plugin subdirectory is a self-contained Claude Code-compatible plugin package
- Contains its own `.claude-plugin/plugin.json` manifest
- May include: slash commands (`commands/`), skills (`skills/`), agents (`agents/`), and MCP servers (`.mcp.json`)
- May include: skills (`skills/`), agents (`agents/`), hooks (`hooks/`), and MCP servers (`.mcp.json`)

### Key Schema Requirements

Expand Down Expand Up @@ -81,19 +81,21 @@ Users add the marketplace, then install plugins from it:
}
```
4. Create plugin components:
- `commands/` - Slash commands (`.md` files)
- `skills/` - Agent skills (directories with `SKILL.md`)
- `agents/` - Custom agents (`.md` files)
- `hooks/` - Lifecycle hooks and related scripts
- `.mcp.json` - MCP server configurations

### Updating Plugins

When updating a plugin:
1. Update version in plugin's `plugin.json`
2. Update version in marketplace catalog entry (`.claude-plugin/marketplace.json`)
3. Document changes in plugin's README.md and the `versions` array in the plugin's `info.json`
4. Commit and push the version bump
5. Tag the release (see "Tagging Plugin Releases" below)
1. If `common/` changed, run `scripts/sync-plugin-common.py` so every plugin package gets updated helper copies.
2. Update version in plugin's `plugin.json`
3. Update version in marketplace catalog entry (`.claude-plugin/marketplace.json`)
4. Document changes in plugin's README.md and the `versions` array in the plugin's `info.json`
5. Run `scripts/sync-plugin-common.py --check` and `python3 -m unittest discover -s tests -v`
6. Commit and push the version bump
7. Tag the release (see "Tagging Plugin Releases" below)

### Tagging Plugin Releases

Expand All @@ -105,7 +107,7 @@ Every version bump must be tagged so Claude Code can resolve it for plugin depen
- **One tag per bumped plugin**: changes under `common/` affect every plugin; if you bump multiple plugins in one PR, create and push one tag per bumped plugin.
- **Verify**: `git tag -l '{PluginName}*' --sort=-v:refname` should show the new tag; `git show {tag}:{PluginName}/.claude-plugin/plugin.json` should print the matching version.

The `/update-plugin` skill automates these steps end-to-end.
The `update-plugin` skill automates these steps end-to-end.

### Testing Locally

Expand All @@ -124,17 +126,6 @@ Test the marketplace and plugins locally before pushing:

## Plugin Component Guidelines

### Slash Commands
- Standalone `.claude/commands` files use the filename as the command name:
`analyze.md` → `/analyze`
- Plugin commands are namespaced by plugin name to avoid collisions:
`SwiftScaffolding/commands/scaffolding.md` → `/SwiftScaffolding:scaffolding`
- Write the command prompt in markdown
- Located in plugin's `commands/` directory
- Claude-specific tool names are acceptable in Claude-specific metadata such as
`allowed-tools`, but keep the command body portable. For user input, say to use
the host's native structured question mechanism if available.

### MCP Servers
- Configured in plugin's `.mcp.json`
- Standard format:
Expand Down Expand Up @@ -215,7 +206,8 @@ if __name__ == "__main__":
### Skills and Agents
- Skills: directories in `skills/` with `SKILL.md`
- Agents: `.md` files in `agents/`
- Not every plugin has skills or agents; command-only and hook-only plugins are valid.
- Legacy command prompts should be migrated to skills instead of adding `commands/` content.
- Not every plugin has skills or agents; hook-only plugins are valid.

## Git Workflow

Expand Down
2 changes: 1 addition & 1 deletion MarvinOutputStyle/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "MarvinOutputStyle",
"version": "1.3.2",
"version": "1.3.3",
"description": "Adds Marvin the Paranoid Android personality - pessimistic and melancholic but brilliantly competent (mimics the deprecated Marvin output style)",
"author": {
"name": "Gustavo Ambrozio"
Expand Down
3 changes: 3 additions & 0 deletions MarvinOutputStyle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ Marvin represents a different approach to AI assistance - one that questions ass

## Changelog

### 1.3.3
- Released self-contained common helper copies so the plugin package no longer depends on repository-level symlinks, while keeping hook configuration in `hooks/hooks.json` instead of generated `common/hooks.json` templates

### 1.3.2
- Made README and plugin guidance more agent-neutral for Claude Code-compatible hosts while preserving Claude plugin contracts

Expand Down
1 change: 0 additions & 1 deletion MarvinOutputStyle/common

This file was deleted.

59 changes: 59 additions & 0 deletions MarvinOutputStyle/common/detect_xcode_mcp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
# Generated from common/detect_xcode_mcp.py by scripts/sync-plugin-common.py. Do not edit this copy; edit common/detect_xcode_mcp.py and rerun scripts/sync-plugin-common.py.
"""Detect whether Xcode's native MCP server is available."""

import subprocess


def detect_xcode_mcp() -> dict:
"""Check if Xcode MCP bridge is installed and likely active.

Returns dict with:
xcode_mcp_installed: xcrun --find mcpbridge succeeds
xcode_running: Xcode process is running
mcpbridge_running: mcpbridge process is running
xcode_mcp_likely: installed AND (xcode OR bridge running)
"""
result = {
"xcode_mcp_installed": False,
"xcode_running": False,
"mcpbridge_running": False,
"xcode_mcp_likely": False,
}

# Check if mcpbridge binary exists (Xcode 26.3+)
try:
subprocess.run(
["xcrun", "--find", "mcpbridge"],
capture_output=True, timeout=5
).returncode == 0 and result.update({"xcode_mcp_installed": True})
except Exception:
pass

if not result["xcode_mcp_installed"]:
return result

# Check if Xcode is running
try:
if subprocess.run(
["pgrep", "-x", "Xcode"],
capture_output=True, timeout=3
).returncode == 0:
result["xcode_running"] = True
except Exception:
pass

# Check if mcpbridge is running
try:
if subprocess.run(
["pgrep", "-f", "mcpbridge"],
capture_output=True, timeout=3
).returncode == 0:
result["mcpbridge_running"] = True
except Exception:
pass

result["xcode_mcp_likely"] = (
result["xcode_running"] or result["mcpbridge_running"]
)
return result
Loading
Loading