AI agent skill · by @kwakseongjae
Omd:Sync
DESIGN.md 변경분을 CLAUDE.md / AGENTS.md / .cursor/rules/omd-design.mdc shim 3종에 전파. 'shim 갱신', 'drift 확인', 'ship', 'publish', 「shimを更新」, 「同步 CLAUDE.md」류의 요청에 트리거. DESIGN.md가 수정됐는데 shim이 오래됐을 때 자동 감지해 제안하기도 함.
Archived 2026-10-23 · Source updated 2026-10-01 · License: MIT. Check the original repository for the latest version.
SKILL.md instructions
<!-- omd:installed-skill — managed by `omd install-skills`. Do not edit; rerun the command to refresh. -->
# omd:sync — Shim Maintenance
DESIGN.md가 모든 주요 AI 코딩 에이전트(Claude Code, Codex, OpenCode, Cursor)에게 보이도록 shim 파일 3종을 관리한다. **CLI 호출 없음** — Read/Write/Edit 툴로 직접 처리.
## 관리 대상 (3 파일)
| ID | 경로 | 모드 |
|---|---|---|
| `claude` | `CLAUDE.md` | block (managed marker만) |
| `agents` | `AGENTS.md` | block (managed marker만) |
| `cursor` | `.cursor/rules/omd-design.mdc` | whole (전체 파일이 omd 전용) |
block 모드는 `<!-- omd:start v=1 hash=<sha256:12> -->` ~ `<!-- omd:end -->` 마커 안만 관리, 나머지 사용자 콘텐츠 보존. whole 모드는 frontmatter 포함 전체 파일이 관리 단위.
## 템플릿 (정확히 이 본문 — 절대 paraphrase 금지)
### CLAUDE.md body
```markdown
# Design System (oh-my-design)
Read the standalone design contract at **@./DESIGN.md** before any UI,
styling, microcopy, or motion work. When a valid adopted Core v2
`.omd/system/manifest.json` declares `profile: portable-core` and binds exact
graph/projection hashes, the System Graph is machine authority and DESIGN.md is
its standalone projection. A migration candidate is never adopted authority.
Preference log (pending corrections): @./.omd/preferences.md
Precedence: pending explicit preference corrections > adopted Bound System
graph/standalone DESIGN.md > your defaults. Fold pending corrections into the
graph and regenerate the projection before clearing them.
```
### AGENTS.md body
```markdown
## Design System (oh-my-design)
**Before any UI, styling, copy, or motion change, open and read `./DESIGN.md` in full.** It is the standalone design contract. If an exact valid adopted Core v2 manifest exists, its hash-bound System Graph is machine authority and DESIGN.md is the projection. A migration candidate remains non-authoritative.
If present, read `./.omd/preferences.md` — pending explicit corrections override the current contract until atomically folded into the graph/projection. Apply them and flag conflicts.
```
### .cursor/rules/omd-design.mdc (whole, frontmatter 포함)
```mdc
---
description: Authoritative brand & UI design system. Read DESIGN.md before UI work.
globs:
- "**/*.tsx"
- "**/*.jsx"
- "**/*.vue"
- "**/*.svelte"
- "**/*.css"
- "**/*.scss"
- "**/tailwind.config.*"
- "**/components/**"
- "**/app/**/page.*"
alwaysApply: true
---
<!-- omd:start v=1 hash=<HASH> -->
<!-- omd:cursor-channel=skills -->
Read the standalone design contract at `@DESIGN.md` before generating/modifying UI. With an exact valid adopted `profile: portable-core` manifest, its hash-bound System Graph is machine authority and DESIGN.md is the projection. A migration candidate is non-authoritative.
Pending preference corrections: `@.omd/preferences.md`.
Precedence: pending explicit preference corrections > adopted Bound System graph/standalone DESIGN.md > framework defaults. Fold pending corrections into the graph and regenerate DESIGN.md before clearing them.
OmD Agent Skills live under `.cursor/skills/`. Use the smallest relevant `omd-*` skill automatically, or invoke it from Cursor with `/omd-<name>`.
Unknown fields stay absent. Never substitute a system font, generic component, guessed token, or adjacent surface as a product fact.
<!-- omd:end -->
```
## 해시 계산
`<HASH>` = sha256 of the body content (마커 제외, body 텍스트만), 12자 hex prefix:
```bash
node -e "console.log(require('crypto').createHash('sha256').update(process.argv[1]).digest('hex').slice(0,12))" "<body 텍스트>"
```
block 모드 마커 형식 정확히:
```
<!-- omd:start v=1 hash=ab12cd34ef56 -->
<body>
<!-- omd:end -->
```
## 실행 절차
사용자가 어떤 모드를 요청하는지 분기:
- **인터랙티브 (디폴트)** — drift 발견 시 사용자에게 묻기
- **--force 의도** ("강제 덮어쓰기") — drift 무시하고 덮어씀
- **--check 의도** ("상태만 검사") — 파일 상태만 출력, write 안 함
각 shim별로:
### Step 1 — Read existing
파일 없으면 → status: `missing`, 새로 write 진행
파일 있으면 → 내용 파싱
### Step 2 — block 모드 파싱
`<!-- omd:start v=N hash=H -->` 라인 찾기:
- 없으면 → status: `missing` (block 부재, 사용자 content 외에 새로 추가 필요)
- 있으면 → marker 사이의 본문 추출. 추출된 본문의 sha256:12를 계산해서 marker의 `hash=H`와 비교
- 불일치 → status: `drifted` (사용자가 수동 편집함)
- 일치 + 본문 == 템플릿 → status: `clean`
- 일치 + 본문 != 템플릿 → status: `out-of-date` (omd 템플릿이 갱신됨)
### Step 3 — whole 모드 파싱
existing 전체 content와 rendered 템플릿 비교:
- 동일 → `clean`
- 차이 → `drifted`
### Step 4 — drift 처리
- **인터랙티브**: drift된 shim별로 "${path}는 수동 편집됐어요. 덮어쓸까요? (yes/no/show diff)" 묻기
- **--force**: drift 무시 덮어씀
- **--check**: drift 있으면 exit 1 동등 — 사용자에게 "drift detected" 보고 후 종료
### Step 5 — Write
- block 모드: existing 안의 marker block만 새 hash + 새 body로 교체. 마커 외부 사용자 content는 보존
- whole 모드: 파일 전체를 새 rendered content로 교체. 디렉토리 (`.cursor/rules/`) 없으면 mkdir
### Step 6 — sync-lock 갱신
`.omd/sync.lock.json` 기록 (없으면 만든다):
```json
{
"design_md_hash": "<DESIGN.md sha256:12>",
"targets": {
"CLAUDE.md": "<hash>",
"AGENTS.md": "<hash>",
".cursor/rules/omd-design.mdc": "<hash>"
},
"updated_at": "<ISO timestamp>"
}
```
DESIGN.md 해시:
```bash
[ -f DESIGN.md ] && node -e "console.log(require('crypto').createHash('sha256').update(require('fs').readFileSync('DESIGN.md')).digest('hex').slice(0,12))"
```
## 결과 보고
```
CLAUDE.md (block) — updated
AGENTS.md (block) — unchanged
.cursor/rules/omd-design.mdc — created
DESIGN.md hash: ab12cd34ef56
```
## 언제 실행하나
- DESIGN.md 변경 직후 (shim hash 갱신용)
- 새 프로젝트 첫 도입 (3종 생성)
- `.claude` / `.cursor` 디렉토리 추가 후
- "drift 확인" 요청
## 금지
- 마커 안 본문에 임의 추가/축약 금지 — 위 템플릿 정확히 사용
- block 모드 파일에서 마커 외부 사용자 content 절대 삭제 금지
- `.omd/sync.lock.json` 무시 금지 — 항상 갱신
- DESIGN.md가 없어도 shim은 만들 수 있음 (DESIGN.md 생성 후에 hash만 채움)