Skip to content
Open
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
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"plugins": [
{
"name": "compound-engineering",
"description": "AI-powered development tools that get smarter with every use. Make each unit of engineering work easier than the last. Includes 27 specialized agents, 23 commands, and 14 skills.",
"version": "2.27.0",
"description": "AI-powered development tools that get smarter with every use. Make each unit of engineering work easier than the last. Includes 28 specialized agents, 24 commands, and 15 skills.",
"version": "2.28.1",
"author": {
"name": "Kieran Klaassen",
"url": "https://github.com/kieranklaassen",
Expand Down
68 changes: 68 additions & 0 deletions .github/workflows/validate-versions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Validate Plugin Versions

on:
pull_request:
branches: [main]
paths:
- 'plugins/**'
- '.claude-plugin/marketplace.json'
push:
branches: [main]
paths:
- 'plugins/**'
- '.claude-plugin/marketplace.json'

jobs:
validate:
name: Check version consistency
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history for branch comparison

- name: Validate plugin versions
run: |
# For PRs, compare against the base branch
if [ "${{ github.event_name }}" = "pull_request" ]; then
BASE_BRANCH="${{ github.base_ref }}"
else
BASE_BRANCH="main"
fi

chmod +x ./scripts/validate-versions.sh
./scripts/validate-versions.sh "$BASE_BRANCH"

- name: Comment on PR if validation fails
if: failure() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Plugin Version Validation Failed

Plugin files were modified but versions may not have been bumped, or there's a version mismatch between files.

### How to Fix

**Bump the version:**
\`\`\`bash
./scripts/bump-version.sh <plugin-name> patch
\`\`\`

This updates both \`plugin.json\` and \`marketplace.json\` atomically.

**Verify locally:**
\`\`\`bash
./scripts/validate-versions.sh
\`\`\`

### Why This Matters

Claude Code detects updates by comparing \`version\` in \`plugin.json\`. If you don't bump the version, users won't receive your changes via auto-update.`
})
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.DS_Store
*.log
node_modules/
.ai
.claude/settings.local.json
90 changes: 61 additions & 29 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ This repository is a Claude Code plugin marketplace that distributes the `compou
every-marketplace/
├── .claude-plugin/
│ └── marketplace.json # Marketplace catalog (lists available plugins)
├── .github/
│ └── workflows/
│ ├── deploy-docs.yml # GitHub Pages deployment
│ └── validate-versions.yml # CI validation for version bumps
├── docs/ # Documentation site (GitHub Pages)
│ ├── index.html # Landing page
│ ├── css/ # Stylesheets
│ ├── js/ # JavaScript
│ └── pages/ # Reference pages
├── scripts/ # Development tooling
│ ├── bump-version.sh # Atomic version bumps
│ ├── validate-versions.sh # Version consistency checks
│ └── setup-local-dev.sh # Configure local development
└── plugins/
└── compound-engineering/ # The actual plugin
├── .claude-plugin/
Expand Down Expand Up @@ -79,12 +87,17 @@ The description appears in multiple places and must match everywhere:

Format: `"Includes X specialized agents, Y commands, and Z skill(s)."`

#### 3. Update version numbers
#### 3. Bump version numbers

When adding new functionality, bump the version in:
Use the version bump script to update both files atomically:

- [ ] `plugins/compound-engineering/.claude-plugin/plugin.json` → `version`
- [ ] `.claude-plugin/marketplace.json` → plugin `version`
```bash
./scripts/bump-version.sh compound-engineering patch # 2.28.0 -> 2.28.1
./scripts/bump-version.sh compound-engineering minor # 2.28.0 -> 2.29.0
./scripts/bump-version.sh compound-engineering major # 2.28.0 -> 3.0.0
```

This updates both `plugin.json` and `marketplace.json` in one command.

#### 4. Update documentation

Expand All @@ -106,19 +119,23 @@ This will:
- Update the changelog page
- Validate all counts match actual files

#### 6. Validate JSON files
#### 6. Validate before committing

Run the validation script to check version consistency:

```bash
cat .claude-plugin/marketplace.json | jq .
cat plugins/compound-engineering/.claude-plugin/plugin.json | jq .
./scripts/validate-versions.sh
```

#### 6. Verify before committing
This checks:
- Versions match between `plugin.json` and `marketplace.json`
- If plugin files changed, version was bumped

Also validate JSON syntax:

```bash
# Ensure counts in descriptions match actual files
grep -o "Includes [0-9]* specialized agents" plugins/compound-engineering/.claude-plugin/plugin.json
ls plugins/compound-engineering/agents/*.md | wc -l
cat .claude-plugin/marketplace.json | jq .
cat plugins/compound-engineering/.claude-plugin/plugin.json | jq .
```

### Marketplace.json Structure
Expand Down Expand Up @@ -256,33 +273,37 @@ python -m http.server 8000

## Testing Changes

### Test Locally
### Local Development Setup

1. Install the marketplace locally:
Run the setup script to configure Claude Code to load from your local directory:

```bash
claude /plugin marketplace add /Users/yourusername/every-marketplace
```
```bash
./scripts/setup-local-dev.sh
```

2. Install the plugin:
This configures:
1. `~/.claude/plugins/known_marketplaces.json` to use local directory source
2. `.claude/settings.local.json` with all plugins enabled

```bash
claude /plugin install compound-engineering
```
After setup:
1. Start a new Claude Code session in this directory
2. Run `/plugins` to verify all plugins are loaded
3. Changes to plugin files will be reflected immediately

3. Test agents and commands:
```bash
claude /review
claude agent kieran-rails-reviewer "test message"
```
### Test Agents and Commands

```bash
claude /review
claude agent kieran-rails-reviewer "test message"
```

### Validate JSON
### Revert to GitHub Source

Before committing, ensure JSON files are valid:
To switch back to loading from GitHub:

```bash
cat .claude-plugin/marketplace.json | jq .
cat plugins/compound-engineering/.claude-plugin/plugin.json | jq .
# Edit ~/.claude/plugins/known_marketplaces.json
# Change "directory" back to "github" with repo: kieranklaassen/compound-engineering-plugin
```

## Common Tasks
Expand Down Expand Up @@ -378,3 +399,14 @@ The initial marketplace.json included many custom fields (downloads, stars, rati
- Plugin entries: `name`, `description`, `version`, `author`, `homepage`, `tags`, `source`

**Learning:** Stick to the official spec. Custom fields may confuse users or break compatibility with future versions.

### 2026-01-25: Added version bump enforcement tooling

Added three scripts to automate version management:
- `scripts/bump-version.sh` - Atomic version bumps to both plugin.json and marketplace.json
- `scripts/validate-versions.sh` - CI validation for version consistency
- `scripts/setup-local-dev.sh` - Configure local development

Also added GitHub Actions workflow that validates versions on PRs and comments with fix instructions if validation fails.

**Learning:** Claude Code detects updates by comparing `version` in `plugin.json`. Without version bumps, users won't receive changes via auto-update. Automating version management prevents forgotten bumps and mismatched versions between files.
101 changes: 101 additions & 0 deletions docs/solutions/structural-fork-pattern.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Structural Fork Pattern

How to maintain a fork with local structural changes while staying synced with upstream content.

## Problem

You want to fork a project and add structural improvements (build systems, configuration layers, reorganization) but still receive content updates from upstream without merge conflicts.

## Solution

Separate **structure** from **content** by introducing an indirection layer:

```
upstream/
├── components/ # Source of truth upstream
│ └── feature.md

your-fork/
├── _source/ # Your source of truth (synced from upstream)
│ └── components/
│ └── feature.md
├── components/ # Generated output (ignored or committed)
│ └── feature.md
├── bin/build # Your structural addition
└── config.json # Your structural addition
```

## Key Principles

1. **Upstream content → `_source/`**: Sync upstream files into a source directory
2. **Build system generates output**: Your tooling reads `_source/` and produces the final structure
3. **Path mapping**: Simple prefix transformation (`components/x` → `_source/components/x`)
4. **Sync script**: Automates fetching, diffing, and applying upstream changes to `_source/`

## Implementation

### 1. Create the indirection

Move upstream content into `_source/`:
```bash
mkdir _source
mv components _source/
```

### 2. Build script

Create `bin/build` that copies from `_source/` to output, applying any transformations:
```ruby
# Read config, copy enabled components from _source/ to output
config = JSON.parse(File.read("config.json"))
enabled = filter_components(config)
enabled.each { |c| copy_component(c) }
```

### 3. Sync script

Create `bin/sync-upstream` that:
1. Fetches upstream
2. Diffs upstream paths against `_source/` paths
3. Shows changes interactively
4. Applies approved changes
5. Runs build

```bash
# Map upstream path to local path
map_path() {
echo "$1" | sed 's|project/|project/_source/|'
}

# Extract file from upstream and write to _source
git show "upstream/main:$upstream_path" > "$local_path"
```

## Benefits

- **No merge conflicts**: Upstream changes apply cleanly to `_source/`
- **Full control**: Your build system can filter, transform, or enhance
- **Clear separation**: Structure changes live outside `_source/`, content inside
- **Easy upgrades**: Run sync script, review diffs, rebuild

## Trade-offs

- **Extra indirection**: Two copies of content (source + output)
- **Build step required**: Changes need rebuild to take effect
- **Manual sync**: Must remember to run sync periodically

## When to Use

- Adding configuration/filtering layers to plugins or packages
- Wrapping upstream tools with custom build systems
- Maintaining forks with organizational improvements
- Any case where you modify HOW content is used, not WHAT the content is

## Example: Plugin with Configurable Components

This pattern powers the compound-engineering plugin fork:

- **Upstream**: All agents/commands/skills in flat directories
- **Fork adds**: `_source/` indirection, `bin/build`, `compound.config.json`
- **Benefit**: Users can enable/disable components without forking again
- **Sync**: `bin/sync-upstream` keeps content current with upstream improvements
Loading