동기화와 저장소 구조
저장소가 원본이고 컴퓨터 쪽은 전부 링크입니다. 공용 파일은 common/ 에 한 벌, 도구별 파일은 claude/·codex/ 에 두고, sync.sh 가 링크와 설정 병합을 맡습니다.
저장소 구조
hossam-skills/
├── common/
│ ├── skills/ 공용 스킬 (실제 파일). Claude·Codex 가 모두 읽는다
│ └── commands/ 공용 커맨드. Claude 의 commands/ 와 Codex 의 prompts/ 가 같은 파일
├── claude/
│ ├── skills/ → ~/.claude/skills 공용 스킬 상대 링크 + Claude 전용(synced/)
│ ├── CLAUDE.md → ~/.claude/CLAUDE.md
│ └── settings.shared.json ~/.claude/settings.json 에 병합할 공유 키
├── codex/
│ ├── skills/ → ~/.agents/skills 공용 스킬 상대 링크 + Codex 전용
│ ├── AGENTS.md → ~/.codex/AGENTS.md
│ ├── hooks.json → ~/.codex/hooks.json
│ └── config.shared.toml ~/.codex/config.toml 에 병합할 최상위 키
├── docs/ 이 매뉴얼 (GitHub Pages, CNAME 포함)
└── README.md
컴퓨터 쪽과의 대응
→ Claude Code 는 링크 3개와 병합 1개.
| 저장소 | 컴퓨터 쪽 | 방식 |
|---|---|---|
claude/skills/ |
~/.claude/skills |
심볼릭 링크 |
common/commands/ |
~/.claude/commands |
심볼릭 링크 |
claude/CLAUDE.md |
~/.claude/CLAUDE.md |
심볼릭 링크 |
claude/settings.shared.json |
~/.claude/settings.json |
공유 키만 병합. permissions 는 절대 건드리지 않음 |
→ Codex 는 링크 4개와 병합 1개.
| 저장소 | 컴퓨터 쪽 | 방식 |
|---|---|---|
codex/skills/ |
~/.agents/skills |
심볼릭 링크. Codex 공식 사용자 스킬 폴더 |
common/commands/ |
~/.codex/prompts |
심볼릭 링크. Codex 커스텀 프롬프트 = 슬래시 커맨드 |
codex/AGENTS.md, codex/hooks.json |
~/.codex/AGENTS.md, ~/.codex/hooks.json |
심볼릭 링크 |
codex/config.shared.toml |
~/.codex/config.toml |
최상위 키 = 값 줄만 병합. [plugins.*] 같은 테이블은 컴퓨터별 |
→ 출력 스타일은 내려받습니다. attention-span 3종을 ~/.claude/output-styles/ 와 ~/.codex/output-styles/ 에 설치합니다. AGPL 이라 저장소에 넣지 않습니다.
왜 Dropbox 가 아니라 git 인가
→ 충돌이 보입니다. 두 컴퓨터에서 같은 파일을 고치면 git 은 멈추고 알려 주지만, Dropbox 는 “충돌 복사본”을 조용히 만듭니다.
→ 되돌릴 수 있습니다. 스킬을 잘못 고쳤을 때 git log 로 어느 시점이든 복구됩니다.
→ 링크가 삽니다. 이 구조의 핵심은 심볼릭 링크인데, macOS Dropbox 는 링크를 실제 폴더로 풀거나 건너뜁니다.
→ 비밀·DB 가 섞이지 않습니다. ~/.codex 에는 로그인 토큰(auth.json)과 세션 DB(sqlite)가 있습니다. 폴더째 클라우드에 올리면 토큰이 유출되고 DB 가 깨집니다. git 은 올릴 파일만 고릅니다.
→ “pull 을 눌러야 한다”는 단점은 SessionStart 훅으로 없앴습니다.
SessionStart 훅
→ 세션마다 자동 실행. Claude Code 는 claude/settings.shared.json 의 hooks.SessionStart, Codex 는 codex/hooks.json 으로 다음을 돌립니다.
bash "$HOME/.claude/skills/env-sync/scripts/sync.sh" apply --quiet # Claude
bash "$HOME/.agents/skills/env-sync/scripts/sync.sh" apply --quiet # Codex
→ --quiet 는 ⚠️·❌ 만 출력합니다. 출력은 에이전트 컨텍스트에 들어가므로 정상이면 아무것도 남기지 않습니다.
→ 오프라인이어도 오래 붙잡지 않습니다. git 은 SSH ConnectTimeout=5, 출력 스타일 내려받기는 --max-time 10 입니다.
→ Codex 는 출력 스타일도 훅으로 넣습니다. cat ~/.codex/output-styles/attention-kind.md 를 추가로 돌려 Attention Span 규칙을 컨텍스트에 넣습니다. Claude 는 settings.json 의 outputStyle 로 같은 일을 합니다.
→ 주의: Codex 훅은 처음 한 번 /hooks 로 신뢰해야 돕니다.
sync.sh 명령
| 명령 | 하는 일 |
|---|---|
sync.sh apply |
pull → 공용 스킬 링크 보충 → 링크 7개 → settings·config 병합 → 출력 스타일 → 깨진 링크 정리 → 점검 |
sync.sh apply --force |
위와 같되, 저장소와 다른 로컬 실제 파일·폴더를 버리고 링크 |
sync.sh apply --quiet |
훅용. ⚠️·❌ 만 출력 |
sync.sh check |
변경 없이 점검만 |
sync.sh push "메시지" |
git add -A → commit → pull --rebase → push |
→ 도구 안에서는 Claude Code /env-sync [apply|check|push 메시지], Codex /prompts:env-sync … 가 같은 일을 합니다.
작성 규칙
→ 절대 경로·홈 경로를 하드코딩하지 않습니다. 설치 위치가 컴퓨터마다 다를 수 있습니다. 스킬 안에서 자기 스크립트를 부를 때는 찾습니다.
find -L ~/.claude/skills ~/.agents/skills -name <스크립트> -path "*<스킬이름>*" 2>/dev/null | head -1
→ 저장소 밖을 가리키는 심볼릭 링크는 커밋하지 않습니다. claude/skills/·codex/skills/ 안의 ../../common/skills/<이름> 같은 저장소 안 상대 링크만 커밋합니다. 이건 어느 컴퓨터에서도 깨지지 않습니다.
→ 공용 스킬은 common/skills/ 에 한 벌. sync.sh apply 가 양쪽 링크를 만듭니다. 한쪽 전용 스킬은 claude/skills/ 또는 codex/skills/ 에 실제 폴더로 둡니다. 같은 이름이 양쪽에 있으면 전용 폴더가 이기고 공용 링크는 만들지 않습니다.
→ Claude 용어를 써도 됩니다. Skill 도구, AskUserQuestion, ~/.claude/... 가 스킬 문서에 있어도 Codex 는 codex/AGENTS.md 의 대응표로 읽습니다. 다만 새 스킬은 가능하면 “사용자에게 선택지를 묻는다”처럼 도구 중립적으로 적습니다.
→ 커맨드는 스킬 이름으로 지목합니다. 파일 경로로 가리키면 설치 위치가 바뀔 때 깨집니다. 커맨드 이름은 Claude Code 내장(/review, /init, /run, /loop 등)과 겹치지 않게 짧게 짓습니다. da-project-feedback 이 /review 가 아니라 /da-project 인 이유입니다.
→ 새 스킬을 추가하면 문서도 같이. 사용자가 직접 부르는 작업 스킬에는 1:1 커맨드를 만들고, 스킬과 커맨드 와 출처 페이지를 함께 갱신합니다.
→ settings.json 전체는 넣지 않습니다. 컴퓨터마다 절대 경로가 박힌 permissions 가 생기기 때문입니다. 공유할 키는 claude/settings.shared.json 에만 추가합니다.
→ claude/skills/synced/ 와 .trash/ 는 건드리지 않습니다. claude.ai 가 자동 동기화하는 스킬과 그 쓰레기통입니다. 메타데이터는 .gitignore 에 있습니다.