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/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mkdir -p "$CLAUDE_DIR/skills"
if [ -L "$CLAUDE_DIR/skills/vync-editing" ]; then
rm "$CLAUDE_DIR/skills/vync-editing"
fi
ln -s "$SCRIPT_DIR/skills/vync-editing" "$CLAUDE_DIR/skills/vync-editing"
ln -s "$PROJECT_ROOT/skills/vync-editing" "$CLAUDE_DIR/skills/vync-editing"
echo " [ok] Skill: vync-editing"

# 2. Commands
Expand All @@ -21,7 +21,7 @@ for cmd in vync.md; do
target="$CLAUDE_DIR/commands/$cmd"
[ -L "$target" ] && rm "$target"
[ -f "$target" ] && rm "$target"
ln -s "$SCRIPT_DIR/commands/$cmd" "$target"
ln -s "$PROJECT_ROOT/commands/$cmd" "$target"
echo " [ok] Command: /${cmd%.md}"
done

Expand All @@ -34,7 +34,7 @@ deprecated="$CLAUDE_DIR/commands/vync-create.md"
agents_dir="$CLAUDE_DIR/agents"
mkdir -p "$agents_dir"
for agent in vync-translator.md; do
src="$SCRIPT_DIR/agents/$agent"
src="$PROJECT_ROOT/agents/$agent"
dst="$agents_dir/$agent"
[ -L "$dst" ] && rm "$dst"
ln -s "$src" "$dst" && echo " [ok] Agent: ${agent%.md}"
Expand All @@ -54,7 +54,7 @@ echo " [ok] Backup: $SETTINGS.bak"
node -e "
const fs = require('fs');
const settings = JSON.parse(fs.readFileSync('$SETTINGS', 'utf-8'));
const hooks = JSON.parse(fs.readFileSync('$SCRIPT_DIR/hooks.json', 'utf-8'));
const hooks = JSON.parse(fs.readFileSync('$PROJECT_ROOT/hooks/hooks.json', 'utf-8'));

// Merge hooks: append vync hooks to existing arrays
if (!settings.hooks) settings.hooks = {};
Expand Down
26 changes: 26 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "PresenceWith-Vync",
"description": "Visual planning tool with real-time file sync for Claude Code",
"owner": {
"name": "PresenceWith",
"email": "presence042@gmail.com"
},
"plugins": [
{
"name": "vync",
"source": "./",
"description": "Create and edit mindmaps, flowcharts, and diagrams with real-time file sync between Claude Code and web UI",
"version": "0.1.0",
"author": {
"name": "PresenceWith",
"url": "https://github.com/PresenceWith"
},
"homepage": "https://github.com/PresenceWith/Vync",
"repository": "https://github.com/PresenceWith/Vync",
"license": "MIT",
"category": "productivity",
"tags": ["whiteboard", "mindmap", "flowchart", "diagram", "visual-planning", "file-sync"]
}
]
}
6 changes: 5 additions & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
"name": "vync",
"description": "Visual planning tool with real-time file sync. Create and edit mindmaps, flowcharts, and diagrams from Claude Code.",
"version": "0.1.0",
"author": "PresenceWith",
"author": {
"name": "PresenceWith",
"url": "https://github.com/PresenceWith"
},
"homepage": "https://github.com/PresenceWith/Vync",
"repository": "https://github.com/PresenceWith/Vync",
"license": "MIT",
"keywords": ["whiteboard", "mindmap", "flowchart", "diagram", "visual-planning", "file-sync"]
Expand Down
15 changes: 9 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ npm run package:desktop # Package macOS DMG

## Claude Code Plugin

The plugin is in `.claude-plugin/`. Install with `bash .claude-plugin/install.sh`.

- `/vync init|open|close|stop` — CLI operations (direct execution)
- `/vync create|read|update` — AI diagram operations (delegated to `vync-translator` sub-agent)
- `vync-editing` skill — `.vync` file editing guide with validation
- `vync-translator` agent — Prose ↔ .vync JSON translator (context window protection)
**Marketplace install**: `/plugin marketplace add PresenceWith/Vync` → `/plugin install vync@PresenceWith-Vync`
**Dev install**: `bash .claude-plugin/install.sh`

Plugin layout (marketplace standard — root-level):
- `commands/vync.md` — `/vync init|open|close|stop` (CLI), `/vync create|read|update` (sub-agent)
- `skills/vync-editing/` — `.vync` file editing guide with validation
- `agents/vync-translator.md` — Prose ↔ .vync JSON translator (context window protection)
- `hooks/hooks.json` — PostToolUse (.vync auto-validation), SessionEnd (server cleanup)
- `.claude-plugin/` — plugin.json, marketplace.json, install.sh, uninstall.sh

## Editing .vync Files

Expand Down
File renamed without changes.
File renamed without changes.
28 changes: 16 additions & 12 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,19 +343,23 @@ Vync/ # nx monorepo (Drawnix 포크 기반)
│ └── open.test.ts # smart restart + vyncStop 유닛 테스트
├── bin/
│ └── vync.js # CLI 진입점 (CommonJS, tsx spawn) [VYNC 추가]
├── .claude-plugin/ # Claude Code 플러그인 (marketplace 표준) [VYNC 추가]
├── .claude-plugin/ # Claude Code 플러그인 메타 (marketplace 표준) [VYNC 추가]
│ ├── plugin.json # 플러그인 메타데이터
│ ├── install.sh # ~/.claude/에 심볼릭 링크 + 설정 머지
│ ├── uninstall.sh # 정리
│ ├── hooks.json # PostToolUse + SessionEnd 설정
│ ├── skills/
│ │ └── vync-editing/ # 편집 가이드 Skill
│ │ ├── SKILL.md
│ │ ├── references/ # 상세 가이드 (mindmap, geometry, arrow-line, coordinates)
│ │ ├── scripts/ # validate.js, generate-id.js
│ │ └── assets/ # schema.json, 예시 .vync 파일
│ ├── agents/ # 커스텀 sub-agent (vync-translator) [VYNC 추가: Phase 7]
│ └── commands/ # /vync 슬래시 커맨드 (create/read/update 통합)
│ ├── marketplace.json # 마켓플레이스 등록 정보
│ ├── install.sh # 개발자 설치 (심볼릭 링크 + 설정 머지)
│ └── uninstall.sh # 정리
├── commands/ # /vync 슬래시 커맨드 (marketplace 표준 위치) [VYNC 추가]
│ └── vync.md
├── skills/ # 편집 가이드 Skill (marketplace 표준 위치) [VYNC 추가]
│ └── vync-editing/
│ ├── SKILL.md
│ ├── references/ # 상세 가이드 (mindmap, geometry, arrow-line, coordinates)
│ ├── scripts/ # validate.js, generate-id.js
│ └── assets/ # schema.json, 예시 .vync 파일
├── agents/ # 커스텀 sub-agent (marketplace 표준 위치) [VYNC 추가: Phase 7]
│ └── vync-translator.md
├── hooks/ # PostToolUse + SessionEnd (marketplace 표준 위치) [VYNC 추가]
│ └── hooks.json
├── docs/ # 프로젝트 문서
├── examples/ # .vync 예시 파일 [VYNC 추가]
├── electron-builder.yml # Electron 패키징 설정 (macOS DMG) [VYNC 추가]
Expand Down
2 changes: 1 addition & 1 deletion docs/FUTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ D-008에서 Last Write Wins로 결정. 후속 개선 옵션:
| 항목 | 설명 |
|------|------|
| 배포/패키징 | Electron DMG 패키징 구현 완료 (→ D-012). 추가: 코드 서명/공증, 자동 업데이트, `npx vync`/npm 발행 |
| 다중 파일 | **1단계 완료** (Phase 8, → D-014): Hub Server + 멀티 윈도우. **2단계 설계 완료** (Phase 9): 멀티 탭 UI ([설계](plans/2026-03-09-multi-tab-ui-design.md)). 후속: 대시보드, 파일 간 링크 |
| 다중 파일 | **1단계 완료** (Phase 8, → D-014): Hub Server + 멀티 윈도우. **2단계 완료** (Phase 9): 멀티 탭 UI ([설계](plans/2026-03-09-multi-tab-ui-design.md)). 후속: 대시보드, 파일 간 링크 |
| 보안 | 기본 보안 구현 완료 (Phase 8): validateFilePath(allowlist + .vync + realpath) + Host 헤더 검증 + CORS + WS Origin 검증. 추가: 디렉토리 접근 제한 고도화 |
| `vync watch` | UI 없이 파일 감시 데몬 (자동 변환 파이프라인용) |
| 업스트림 (Drawnix) 추적 | 주기적 upstream diff, 핵심 변경 최소화 |
Expand Down
239 changes: 239 additions & 0 deletions docs/plans/2026-03-09-marketplace-registration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
# Design: Claude Code Marketplace 등록

**Date:** 2026-03-09
**Status:** Draft
**Depends on:** Phase 9 완료 (Multi-Tab UI)

## Goal

Vync Claude Code 플러그인을 마켓플레이스에 등록하여, 프로젝트를 clone하지 않고도 `/plugin install vync`로 설치하고 `/plugin update`로 업데이트할 수 있도록 한다.

현재 설치 방식 (npm postinstall → install.sh 심링크)은 개발자 전용. 마켓플레이스 등록으로 일반 사용자도 접근 가능하게 확장.

## 리서치 결과

### 마켓플레이스 시스템 분석

- Claude Code 마켓플레이스는 **GitHub repo 기반 self-hosted** 방식이 표준
- claude-hud, everything-claude-code 등 주요 플러그인 모두 동일 패턴 사용
- `.claude-plugin/`에는 `plugin.json` + `marketplace.json`만 위치
- commands, skills, agents, hooks는 **프로젝트 루트 레벨**에 위치해야 함

### Repo 크기 이슈

- Vync repo: working tree ~3GB (node_modules, dist 포함), `.git` 4.4MB
- 마켓플레이스 clone 시 `.gitignore` 대상은 제외됨 → git tracked 파일만 clone
- 실제 clone 크기: 수십 MB 수준 → 문제 없음
- 비교: claude-hud ~2.6MB, everything-claude-code ~46MB, claude-plugins-official ~7.7MB

### 설치 흐름

```
사용자: /plugin marketplace add PresenceWith/Vync
→ GitHub repo clone → ~/.claude/plugins/marketplaces/PresenceWith-Vync/

사용자: /plugin install vync@PresenceWith-Vync
→ marketplace에서 plugin 복사 → ~/.claude/plugins/cache/PresenceWith-Vync/vync/<version>/
→ commands, skills, agents, hooks 자동 등록

사용자: /plugin update vync@PresenceWith-Vync
→ marketplace git pull → 새 버전 복사 → 자동 재등록
```

## Decisions

| ID | Decision | Rationale |
|----|----------|-----------|
| P-1 | 같은 repo에서 self-hosted marketplace | 코드와 플러그인 한 repo, 버전 동기화 쉬움. 업계 표준 패턴 (claude-hud, ECC 동일). |
| P-2 | 루트 레벨 파일 재배치 | 마켓플레이스 표준 필수사항. `.claude-plugin/` 안에서 루트로 이동. |
| P-3 | hooks.json validate 인라인화 | 마켓플레이스 설치 시 `$HOME/.claude/skills/` 경로가 달라짐. 인라인 node 스크립트로 경로 독립성 확보. |
| P-4 | 개발자 모드 (install.sh) 병행 유지 | npm install → postinstall로 기존 개발자 워크플로우 유지. 마켓플레이스와 충돌 없음. |
| P-5 | Anthropic Official Directory는 안정화 후 | 먼저 self-hosted로 검증, 이후 공식 제출 (clau.de/plugin-directory-submission). |

## Architecture

### 현재 구조 → 목표 구조

```
# 현재 (.claude-plugin/ 안에 모든 것) # 목표 (마켓플레이스 표준)
.claude-plugin/ .claude-plugin/
├── plugin.json ├── plugin.json ← 수정
├── hooks.json ├── marketplace.json ← 신규
├── install.sh ├── install.sh ← 경로 수정
├── uninstall.sh └── uninstall.sh ← 확인
├── agents/ agents/ ← 루트로 이동
│ └── vync-translator.md └── vync-translator.md
├── commands/ commands/ ← 루트로 이동
│ └── vync.md └── vync.md
└── skills/ skills/ ← 루트로 이동
└── vync-editing/ └── vync-editing/
├── SKILL.md └── (전체 유지)
├── references/ (4) hooks/ ← 루트에 신규
├── scripts/ (2) └── hooks.json ← 인라인화
└── assets/ (3)
```

### hooks.json 인라인화

현재 PostToolUse hook이 `$HOME/.claude/skills/vync-editing/scripts/validate.js`를 참조.
마켓플레이스 설치 시 이 경로는 존재하지 않음 (플러그인이 `~/.claude/plugins/cache/`에 설치됨).

해결: validate.js 핵심 로직 (version, viewport, elements 검증)을 인라인 node 스크립트로 변환.
validate.js 원본은 skills/vync-editing/scripts/에 유지 (sub-agent가 명시적으로 호출 가능).

## Implementation Steps

### Step 1: 파일 재배치 (git mv)

```bash
git mv .claude-plugin/commands commands
git mv .claude-plugin/skills skills
git mv .claude-plugin/agents agents
mkdir hooks
git mv .claude-plugin/hooks.json hooks/hooks.json
```

### Step 2: plugin.json 업데이트

`.claude-plugin/plugin.json`:

```json
{
"name": "vync",
"description": "Visual planning tool with real-time file sync. Create and edit mindmaps, flowcharts, and diagrams from Claude Code.",
"version": "0.1.0",
"author": {
"name": "PresenceWith",
"url": "https://github.com/PresenceWith"
},
"homepage": "https://github.com/PresenceWith/Vync",
"repository": "https://github.com/PresenceWith/Vync",
"license": "MIT",
"keywords": ["whiteboard", "mindmap", "flowchart", "diagram", "visual-planning", "file-sync"]
}
```

### Step 3: marketplace.json 생성

`.claude-plugin/marketplace.json`:

```json
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "PresenceWith-Vync",
"description": "Visual planning tool with real-time file sync for Claude Code",
"owner": {
"name": "PresenceWith",
"email": "presence042@gmail.com"
},
"plugins": [
{
"name": "vync",
"source": "./",
"description": "Create and edit mindmaps, flowcharts, and diagrams with real-time file sync between Claude Code and web UI",
"version": "0.1.0",
"author": {
"name": "PresenceWith",
"url": "https://github.com/PresenceWith"
},
"homepage": "https://github.com/PresenceWith/Vync",
"repository": "https://github.com/PresenceWith/Vync",
"license": "MIT",
"category": "productivity",
"tags": ["whiteboard", "mindmap", "flowchart", "diagram", "visual-planning", "file-sync"]
}
]
}
```

### Step 4: hooks.json 수정

`hooks/hooks.json` — PostToolUse validate를 인라인 스크립트로 변경:

```json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "<인라인 node 검증 스크립트>"
}
]
}
],
"SessionEnd": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "<기존 Hub Server 정리 스크립트 유지>"
}
]
}
]
}
}
```

### Step 5: install.sh 업데이트

경로를 `$SCRIPT_DIR/` → `$PROJECT_ROOT/` 기준으로 변경:
- skills: `$PROJECT_ROOT/skills/vync-editing`
- commands: `$PROJECT_ROOT/commands/vync.md`
- agents: `$PROJECT_ROOT/agents/vync-translator.md`
- hooks: `$PROJECT_ROOT/hooks/hooks.json`

### Step 6: CLAUDE.md 업데이트

플러그인 섹션 경로 설명을 마켓플레이스 표준 구조로 업데이트.

## Files to Modify

| File | Action |
|------|--------|
| `commands/vync.md` | git mv from `.claude-plugin/commands/` |
| `skills/vync-editing/` | git mv (전체 디렉토리) |
| `agents/vync-translator.md` | git mv from `.claude-plugin/agents/` |
| `hooks/hooks.json` | git mv + PostToolUse 인라인화 |
| `.claude-plugin/plugin.json` | author → object, homepage 추가 |
| `.claude-plugin/marketplace.json` | 새로 생성 |
| `.claude-plugin/install.sh` | 경로 $PROJECT_ROOT/ 기준 변경 |
| `.claude-plugin/uninstall.sh` | 확인 (변경 최소) |
| `CLAUDE.md` | 플러그인 구조 설명 업데이트 |

## Verification

1. `/plugin validate .` → 플러그인 매니페스트 유효성 확인
2. 로컬 마켓플레이스 테스트:
```bash
/plugin marketplace add /Users/presence/projects/Vync
/plugin install vync@PresenceWith-Vync
```
3. 기능 확인:
- `/vync` 명령어 전체 (init, open, close, stop, create, read, update)
- `vync-editing` 스킬 로드
- `vync-translator` 에이전트 인식
- PostToolUse hook (.vync 검증)
4. 개발자 모드: `npm install` → install.sh 정상 동작
5. GitHub 마켓플레이스 (push 후):
```bash
/plugin marketplace add PresenceWith/Vync
/plugin install vync@PresenceWith-Vync
```

## User Installation Workflow (Result)

```bash
# 1회: 마켓플레이스 등록
/plugin marketplace add PresenceWith/Vync

# 플러그인 설치
/plugin install vync@PresenceWith-Vync

# 업데이트
/plugin update vync@PresenceWith-Vync
```
2 changes: 1 addition & 1 deletion .claude-plugin/hooks.json → hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path // \"\"' | { read f; [[ \"$f\" == *.vync ]] && node \"$HOME/.claude/skills/vync-editing/scripts/validate.js\" \"$f\" 2>&1 || true; }"
"command": "jq -r '.tool_input.file_path // \"\"' | { read f; [[ \"$f\" == *.vync ]] && node -e \"const fs=require('fs'),p=process.argv[1];try{const d=JSON.parse(fs.readFileSync(p,'utf8'));const e=[];if(typeof d.version!=='number')e.push('missing version');if(!d.viewport||typeof d.viewport!=='object')e.push('missing viewport');else{if(typeof d.viewport.zoom!=='number')e.push('viewport.zoom');if(typeof d.viewport.x!=='number')e.push('viewport.x');if(typeof d.viewport.y!=='number')e.push('viewport.y')}if(!Array.isArray(d.elements))e.push('elements must be array');if(e.length){console.error('[vync-validate] '+p+': '+e.join(', '));process.exit(1)}console.log('[vync-validate] '+p+': OK')}catch(err){console.error('[vync-validate] '+p+': '+err.message);process.exit(1)}\" \"$f\" 2>&1 || true; }"
}
]
}
Expand Down