Claude Code 세션 공유 — .jsonl 심볼릭 링크
- 1. Claude Code 멀티 계정 셋업 — 한 Mac에서 4계정 분리 운영
- 2. Claude Code 세션 공유 — .jsonl 심볼릭 링크
- 3. Claude Code 설정 동기화와 트러블슈팅
멀티 계정을 설정하고 나면 새로운 문제가 생긴다. 계정 A에서 작업하던 세션이 계정 B에서는 보이지 않는다. Resume 목록이 계정마다 별도 projects 디렉토리에 쌓이기 때문이다. 계정을 바꿀 때마다 이전 대화 맥락이 끊기면 멀티 계정을 쓰는 의미가 절반쯤 사라진다.
해결책은 모든 계정의 projects 디렉토리를 같은 물리 경로로 가리키는 것이다.
Claude Code는 projects 디렉토리의 .jsonl 파일을 직접 스캔해 재개 가능한 세션 목록을 구성합니다. 여러 계정에서 같은 세션을 이어 쓰려면 모든 계정의 projects 디렉토리를 같은 물리 디렉토리로 가리키는 심볼릭 링크로 설정하면 됩니다.
어떻게 가능한가
Claude Code가 Resume 목록을 구성하는 방식은 외부 색인 파일(index)을 조회하는 것이 아닙니다. 기동 시마다 projects 디렉토리 아래의 모든 .jsonl 파일을 동적으로 스캔해 세션 메타데이터를 직접 파싱합니다. 의사 코드로 표현하면 다음과 같습니다.
function loadResumeList(projectsDir) {
const sessions = [];
const files = fs.readdirSync(projectsDir, { recursive: true });
for (const file of files) {
if (file.endsWith('.jsonl')) {
const session = parseJsonl(file);
sessions.push(session);
}
}
return sessions;
}핵심은 파일의 물리적 위치입니다. 경로 자체가 아니라 그 경로가 실제로 가리키는 파일이 중요합니다. 이 특성 덕분에 projects 디렉토리를 심볼릭 링크로 대체해도 Claude Code의 스캔 로직은 아무 변경 없이 동작합니다. 링크 여부를 구분하지 않기 때문입니다.
일부 외부 도구(cc-session-sync, qmd)는 빠른 조회를 위해 sessions-index.json을 별도로 생성합니다. 그러나 Claude Code 자체는 이 파일을 사용하지 않습니다. sessions-index.json이 오래되거나 손상된 상태여도 Resume 기능에는 영향이 없습니다.
디렉토리 구조와 심볼릭 링크
목표 구조는 다음과 같습니다.
~/.claude-shared/projects/ ← 물리적 디렉토리 (모든 .jsonl 파일 보관)
├── -Users-jaesolshin/
│ └── *.jsonl
├── -private-tmp/
│ └── *.jsonl
└── ...
~/.claude/projects → 심볼릭 링크 → ~/.claude-shared/projects/
~/.claude-2/projects → 심볼릭 링크 → ~/.claude-shared/projects/
~/.claude-3/projects → 심볼릭 링크 → ~/.claude-shared/projects/
~/.claude-4/projects → 심볼릭 링크 → ~/.claude-shared/projects/모든 계정의 projects가 같은 물리 디렉토리를 가리키므로, 한 계정에서 생성한 .jsonl 파일은 다른 계정에서 즉시 접근 가능합니다. 파일 시스템 수준의 투명성이 핵심입니다.
심볼릭 링크를 수동으로 생성하는 명령은 다음과 같습니다.
# 공유 디렉토리 생성
mkdir -p ~/.claude-shared/projects
# 각 계정의 projects를 공유 디렉토리로 연결
ln -sf ~/.claude-shared/projects ~/.claude/projects
ln -sf ~/.claude-shared/projects ~/.claude-2/projects
ln -sf ~/.claude-shared/projects ~/.claude-3/projects
ln -sf ~/.claude-shared/projects ~/.claude-4/projects설정 후 심볼릭 링크를 확인합니다.
ls -la ~/.claude/projects
# 예상 출력:
# lrwxr-xr-x ... ~/.claude/projects -> /Users/user/.claude-shared/projects마이그레이션 절차
기존 세션 데이터가 각 계정의 projects 디렉토리에 분산되어 있는 경우, 초기화 스크립트를 사용하면 병합·백업·심볼릭 링크 교체를 자동으로 처리합니다.
bash ~/.claude/scripts/sessions-shared-init.shPhase 1: 병합
각 계정의 projects 디렉토리 내용을 ~/.claude-shared/projects/로 rsync합니다. --ignore-existing 옵션을 사용하므로 같은 파일명이 이미 존재하면 덮어쓰지 않습니다. 결과적으로 공유 디렉토리는 모든 계정 세션의 합집합이 됩니다.
rsync -a --ignore-existing ~/.claude/projects/ ~/.claude-shared/projects/
rsync -a --ignore-existing ~/.claude-2/projects/ ~/.claude-shared/projects/
# ... 각 계정 반복Phase 2: 백업
원본 projects 디렉토리를 타임스탬프와 함께 백업합니다. 심볼릭 링크로 교체하기 전에 원본을 보존하는 안전장치입니다.
mv ~/.claude/projects ~/.claude/projects.bak.$(date +%s)
mv ~/.claude-2/projects ~/.claude-2/projects.bak.$(date +%s)Phase 3: 심볼릭 링크
각 계정의 projects 위치에 공유 디렉토리로 향하는 심볼릭 링크를 생성합니다.
ln -sf ~/.claude-shared/projects ~/.claude/projects
ln -sf ~/.claude-shared/projects ~/.claude-2/projects스크립트 실행 출력 예시는 다음과 같습니다.
Accounts found: 4
/Users/user/.claude
/Users/user/.claude-2
/Users/user/.claude-3
/Users/user/.claude-4
=== Phase 1: Merge ===
Merging /Users/user/.claude/projects (100 .jsonl files) ...
Merging /Users/user/.claude-2/projects (80 .jsonl files) ...
...
Shared total: 160 .jsonl files
=== Phase 2: Symlink ===
Linked /Users/user/.claude/projects → ~/.claude-shared/projects (backup: ...)
Linked /Users/user/.claude-2/projects → ~/.claude-shared/projects (backup: ...)
...
[OK] Done. Verify: ls -la ~/.claude/projects마이그레이션 전 각 계정에 중복 세션이 있었다면 합집합 기준으로 세션 수가 줄어드는 것은 정상입니다. 4개 계정에 각각 100, 80, 60, 40개 세션이 있어도 중복을 제거하면 공유 디렉토리의 파일 수는 그보다 적을 수 있습니다.
세션 재개 동작
설정 완료 후 사용 방법은 기존과 동일합니다. 계정 전환 후 Resume를 선택하면 다른 계정에서 생성한 세션이 목록에 나타납니다.
# 계정 1에서 새 세션 시작
claude -1
# 계정 2에서 같은 세션 재개
claude -2
# "Resume" 메뉴에 계정 1에서 생성한 세션이 표시됨이것이 가능한 이유는 단순합니다. ~/.claude/projects와 ~/.claude-2/projects가 물리적으로 같은 디렉토리(~/.claude-shared/projects)를 가리키기 때문입니다. 계정 1에서 새 세션을 시작하면 ~/.claude-shared/projects/ 아래에 .jsonl 파일이 생성됩니다. 계정 2에서 Claude Code를 기동하면 동일한 물리 디렉토리를 스캔하므로 해당 파일을 즉시 발견합니다.
claude --resume 플래그를 사용하는 경우도 동일합니다.
# 특정 세션 ID를 지정해 재개
claude -2 --resume <session-id>Resume 목록에 표시되는 세션 ID는 .jsonl 파일에서 직접 파싱됩니다. 색인 파일이나 외부 상태에 의존하지 않으므로, 심볼릭 링크를 통해 같은 파일에 접근하는 한 어느 계정에서든 동일한 목록을 볼 수 있습니다.
계정 1 (claude -1)
→ ~/.claude/projects (symlink)
→ ~/.claude-shared/projects/
└── session1.jsonl (새로 생성)
계정 2 (claude -2)
→ ~/.claude-2/projects (symlink)
→ ~/.claude-shared/projects/ (같은 물리 디렉토리)
└── session1.jsonl (즉시 발견 → Resume 목록에 표시)운영상 주의
권한과 소유권
~/.claude-shared/projects/의 소유자가 현재 사용자와 일치하는지 확인합니다. 초기화 스크립트를 루트 권한으로 실행한 경우 소유권이 root로 설정될 수 있습니다.
ls -la ~/.claude-shared/
# 소유자가 현재 사용자인지 확인
# 필요 시 소유권 교정
chown -R $(whoami) ~/.claude-shared/심볼릭 링크 자체를 rm으로 제거해도 대상 파일은 삭제되지 않습니다. rm ~/.claude/projects는 링크만 제거하며 ~/.claude-shared/projects/ 아래 파일은 그대로입니다.
동시 쓰기
두 계정에서 동시에 같은 프로젝트 디렉토리에 쓰는 경우, .jsonl 파일 단위의 경합이 발생할 수 있습니다. Claude Code는 세션별로 별개의 .jsonl 파일을 사용하므로 서로 다른 세션을 동시에 진행하면 충돌 가능성은 낮습니다. 같은 세션 파일에 두 계정이 동시에 접근하는 상황은 피하는 것이 좋습니다.
외부 도구(cc-session-sync, qmd)가 sessions-index.json을 생성하는 경우 경합이 발생할 수 있습니다. 그러나 앞서 설명한 것처럼 Claude Code 자체는 이 파일을 사용하지 않으므로 Resume 기능에는 영향이 없습니다.
손상된 .jsonl 파일 복구
.jsonl 파일이 부분적으로 손상된 경우 해당 파일만 제거하면 됩니다. Claude Code는 디렉토리 전체를 스캔하므로 손상된 파일 하나가 다른 세션 목록에 영향을 주지 않습니다. 백업 디렉토리(projects.bak.<타임스탬프>)에서 원본 파일을 복원할 수도 있습니다.
# 손상된 파일 확인 (파싱 오류가 있는 .jsonl)
find ~/.claude-shared/projects/ -name "*.jsonl" -exec sh -c '
node -e "
const fs = require(\"fs\");
fs.readFileSync(\"$1\", \"utf8\").split(\"\n\").forEach((l, i) => {
if (l.trim()) try { JSON.parse(l); } catch(e) { process.exit(1); }
});
" 2>/dev/null || echo "손상: $1"
' sh {} \;settings는 분리 유지
projects 디렉토리를 공유해도 각 계정의 settings.json, CLAUDE.md, history.jsonl은 독립적으로 유지됩니다. 모델 지정이나 API 키, 훅 설정은 계정별로 별도 관리됩니다. 세션 공유가 설정 공유를 의미하지는 않습니다.
memory 디렉토리
projects 디렉토리는 공유되지만 memory 디렉토리는 각 계정에 독립적으로 유지됩니다. 계정 1에서 세션 중 메모리에 저장한 정보는 계정 2에서 같은 세션을 재개해도 보이지 않습니다. memory까지 공유가 필요한 경우 별도로 심볼릭 링크를 구성해야 합니다.
mkdir -p ~/.claude-shared/memory
rsync -a --ignore-existing ~/.claude/memory/ ~/.claude-shared/memory/
for ACCT in ~/.claude ~/.claude-[0-9]*; do
rm -rf "$ACCT/memory"
ln -sf ~/.claude-shared/memory "$ACCT/memory"
donememory 공유를 적용하면 한 계정의 변경이 다른 계정에도 즉시 반영됩니다.
롤백
공유를 취소하고 각 계정의 독립 projects 디렉토리를 복원하려면 백업에서 되돌립니다.
for ACCT in ~/.claude ~/.claude-[0-9]*; do
[ -L "$ACCT/projects" ] || continue
rm "$ACCT/projects"
BACKUP=$(ls -td "$ACCT"/projects.bak.* 2>/dev/null | head -1)
[ -d "$BACKUP" ] && mv "$BACKUP" "$ACCT/projects"
echo "Restored $ACCT/projects"
done초기화 이후 생성된 세션(공유 디렉토리에만 존재하는 파일)을 롤백 후에도 보존하려면 rsync를 추가합니다.
for ACCT in ~/.claude ~/.claude-[0-9]*; do
[ -L "$ACCT/projects" ] || continue
rm "$ACCT/projects"
BACKUP=$(ls -td "$ACCT"/projects.bak.* 2>/dev/null | head -1)
[ -d "$BACKUP" ] && mv "$BACKUP" "$ACCT/projects"
rsync -a --update ~/.claude-shared/projects/ "$ACCT/projects/"
echo "Restored and synced $ACCT/projects"
done시리즈 위치
Ep1에서는 CLAUDE_CONFIG_DIR로 계정 디렉토리를 분리하는 방법을 다뤘으며, Ep3에서는 sync-claude.sh를 이용한 설정 파일 동기화와 트러블슈팅을 다룰 예정입니다.