# ADR-005: Dual-Publish Plugin Architecture

## Status

Accepted (2026-01-09)

## Context

Claude Code introduced an official plugin system (October 2025) with:
- `.claude-plugin/plugin.json` for metadata
- `skills/` directory for auto-discovery
- Marketplace distribution via `/plugin install`
- Lifecycle hooks (SessionStart, PostToolUse, etc.)

We already had a working system:
- `SKILL.md` files with YAML frontmatter
- Nix deployment to `~/.claude/skills/`
- Cross-agent support (Gemini, OpenCode, Claude)
- Lenses pattern for multi-pass code review

### The Problem

1. **Claude's system is Claude-only** - Gemini can't read Claude plugins (see skills-bo8: path restrictions)
2. **Our system lacks hooks** - No lifecycle events, mechanical enforcement
3. **Distribution differs** - Nix vs marketplace

### Alternatives Considered

| Option | Pros | Cons |
|--------|------|------|
| **Migrate fully to Claude plugins** | Native UX, hooks, marketplace | Lose Gemini/OpenCode support |
| **Keep Nix-only** | Cross-agent, system-level | No hooks, no marketplace |
| **Dual-publish (chosen)** | Best of both | Maintenance overhead |

## Decision

**Dual-publish**: Maintain both systems in parallel.

Each skill has:
```
skills/my-skill/
├── .claude-plugin/
│   └── plugin.json        # Claude plugin metadata
├── skills/
│   └── my-skill.md        # Claude auto-discovery
├── SKILL.md               # Nix deployment (cross-agent)
└── README.md
```

The repo root has:
```
.claude-plugin/
└── marketplace.json       # Plugin registry for /plugin install
```

### How It Works

**Nix path (Gemini, OpenCode, system-level):**
1. `deploy-skill.sh` copies skill to dotfiles
2. Home-manager deploys to `~/.claude/skills/`
3. Agents read `SKILL.md` directly

**Claude plugin path:**
1. User adds marketplace: `/plugin marketplace add dan/skills`
2. User installs: `/plugin install orch@dan-skills`
3. Claude discovers `skills/orch.md` automatically

**Content is identical** - `skills/orch.md` is a copy of `SKILL.md`.

### Marketplace Structure

```json
{
  "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
  "name": "dan-skills",
  "version": "1.0.0",
  "description": "Dual-publish for cross-agent support",
  "owner": { "name": "dan" },
  "plugins": [
    { "name": "orch", "source": "./skills/orch" }
  ]
}
```

## Consequences

### Positive

- **Cross-agent support preserved** - Gemini, OpenCode continue working
- **Claude features available** - Hooks, marketplace, `/plugin install`
- **Gradual migration** - Convert skills one at a time
- **No breaking changes** - Existing Nix deployment unchanged

### Negative

- **Duplication** - `SKILL.md` and `skills/<name>.md` must stay in sync
- **Two mental models** - Nix vs plugin system
- **Testing complexity** - Must verify both paths work

### Mitigations

- **Automation**: Script to sync `SKILL.md` → `skills/<name>.md`
- **CI validation**: Check files are identical
- **Documentation**: `docs/emes-conversion-guide.md`

## Deployment Environments

**Current:**

| Environment | Issue Tracker | Plugin System |
|-------------|---------------|---------------|
| **Local** (skills, dotfiles) | beads | Our dual-publish |
| **Remote** (ops-jrz1 VPS) | tissue | emes ecosystem |

**Goal:** Deploy our cross-agent skills to ops-jrz1:

| Environment | Issue Tracker | Plugin System | Agents |
|-------------|---------------|---------------|--------|
| **Local** | beads | Our dual-publish | Claude, Gemini, OpenCode |
| **Remote** (ops-jrz1) | tissue | **Our dual-publish** | Claude, Gemini, OpenCode |

The VPS becomes a "skills for all agents" environment - same cross-agent portability we have locally. tissue handles issue tracking, skills are ours.

## Related

- **skills-6x1**: Epic for emes plugin architecture
- **skills-bo8**: Gemini path restriction issue (motivates cross-agent need)
- **skills-1ks**: Task to convert remaining skills
- **skills-17f**: Forgejo access for distribution

## References

- [Claude Code Plugin Docs](https://code.claude.com/docs/en/plugins)
- [emes org](https://github.com/evil-mind-evil-sword) - Inspiration for plugin patterns
- [Anthropic marketplace.json](https://github.com/anthropics/claude-code/blob/main/.claude-plugin/marketplace.json)
