Skip to content

Session Handoff

세션 간 작업 인수인계 도구. 컨텍스트가 차서 다른 세션·디바이스에서 이어가야 할 때, 자기완결 텍스트 한 장으로 작업 환경과 다음 STEP을 넘긴다.

왜?

긴 작업이 한 세션에서 안 끝나거나 컨텍스트가 차서 새 세션을 열 때, 다음 세션의 Claude(또는 본인)가 5분 안에 환경 복구 + 작업 재개할 수 있어야 한다. 핸드오프는 이를 위한 표준 텍스트 메모.

특징:

  • 멀티 디바이스 동기화 — 맥미니에서 저장한 핸드오프를 맥북·iPhone Claude Code 세션에서 즉시 회수
  • 7일 자동 purge — 서버 측 TTL. 영구 보존 필요 시 메모리 또는 dev doc 으로 이전
  • 시각 단위 다중 저장 — 같은 날 같은 토픽 여러 번 저장 가능 (HHMM 접미사)

도구

Tool용도
handoff_save핸드오프 생성/덮어쓰기
handoff_get단일 핸드오프 본문 회수
handoff_list최근 핸드오프 목록 (옵션: 프로젝트 필터)

⚠️ handoff_list / handoff_get 호출 시 7일 지난 핸드오프 자동 purge 가 같이 실행됨 (side effect). 자동화 에이전트는 destructive 한 maintenance call 로 취급.

저장 (Save)

js
mcp__ainote__handoff_save({
  project: "sample-app",      // 영문 소문자 + 숫자 + 하이픈만
  topic:   "login-flow",
  content: "<자기완결 본문>",
  date:    "2026-05-13",      // optional, 생략 시 서버 today
  time:    "1555"             // optional, HHMM (KST). 같은 날 다중 저장 시 접미사
})

저장 경로: handoffs/{project}-{topic}-[{HHMM}-]{YYYY-MM-DD}.txt

작성 원칙:

  1. 자기완결: 다음 세션은 이전 대화 메시지를 못 봄. 파일 하나만으로 환경 복구
  2. 사실만: "잘 동작" 대신 "BUILD SUCCESSFUL" 같은 검증 가능한 표현
  3. 절대 경로 + 줄 번호 명시 → 다음 세션이 grep/Read 즉시 가능
  4. 다음 STEP 은 명령 단위 ("테스트 작성" X → "/path/X.kt 작성, 케이스 A/B/C" O)
  5. 알려진 함정 필수 — 이번 세션에서 부딪힌 빌드/타입/import 함정은 재발 가능성 큼
  6. 비밀값 평문 금지 — "ENV 의 X (1Password 'sample-app' 항목)" 식으로 참조만

Frontmatter (v2)

content 본문 맨 앞에 YAML frontmatter 를 두면, 서버가 저장 시 자동 파싱해 file_indices.frontmatter 에 인덱싱한다. handoff_list 는 이 필드로 본문을 받지 않고 서버사이드 필터링을 한다. frontmatter 없는 v1 평문 핸드오프도 그대로 동작한다 (필터 지정 시에만 제외됨).

yaml
---
project: sample-app           # 슬러그 (영문 소문자+숫자+하이픈)
topic: login-flow
title: "로그인 플로우 포팅"          # 사람·LLM 식별용, 한국어 OK
session_date: "2026-05-23"
status: in_progress           # in_progress | paused | completed | blocked
has_blockers: false
task_type: feature            # feature | bugfix | refactor | research | ops
tags: [auth, oauth, mobile]
---

# SUMMARY
...

서버가 필터링하는 필드 (handoff_list 인자):

필드필터
statusstatus: "in_progress" 등 — v1(frontmatter 없음) 은 필터 지정 시 제외
has_blockerstrue / false
task_typefeature / bugfix / refactor / research / ops
tags배열 AND 매치 — 준 태그를 모두 가진 항목만 (예: ['auth','mobile'])

필터 외에도 handoff_list 응답 각 항목에는 title·priority·session_time· handoff_version 등이 본문 없이 실려 온다 (목록 훑기용). 필터 대상은 위 4개다.

참조 자동첨부 (클라이언트)

Claude Code session-handoff 스킬은 저장 직전 본문에서 plan/memory/skill 파일 참조를 감지해 vault 에 함께 push 하고, frontmatter 에 {vault_path, git_sha, local_path} 로 기록한다 — 다음 세션이 그 파일들을 sha 대조로 복원. 이 자동첨부는 클라이언트(스킬) 동작이며 서버 도구가 강제하는 것은 아니다.

yaml
referenced_plans:
  - vault_path: global/planning/{proj}/{plan}.md
    git_sha: b0959e68
    local_path: ~/{proj}/.planning/{plan}.md
referenced_memory:  [ ... ]     # 동일 형식
referenced_skills:  [ ... ]     # 동일 형식

Environment sidecar (핸드오프 환경 분리)

프로젝트의 안정 환경 사실(테스트 계정 참조, 에뮬레이터/시뮬레이터 셋업, 빌드 커맨드, 반복 함정)을 핸드오프마다 다시 쓰지 않고 vault 의 한 파일로 분리한다. 핸드오프의 ENVIRONMENT 섹션은 "이번 세션 delta + 치명 정보 1줄" 로 줄고, 안정 사실은 sidecar 가 정본이 된다.

  • 정본 위치: global/planning/environments/{proj}.md
    • ⚠️ handoffs/ 아래에 두지 말 것 — 핸드오프 TTL(7일) purge 가 handoffs/ 전체를 재귀로 쓸어가므로 sidecar 도 소멸한다. global/planning/ 은 TTL 이 없다.
  • 핸드오프에서 참조: frontmatter 에 sha 를 박아 버전을 고정한다.
yaml
environment_ref:
  vault_path: global/planning/environments/{proj}.md
  git_sha: <sidecar 의 content SHA1 — 서버가 sync_list/sync_pull 로 주는 git_sha>

⚠️ 여기서 git_sha 는 vault 가 저장하는 content SHA1 (Digest::SHA1.hexdigest(content)) 이지 git blob-object hash 가 아니다. 클라이언트는 같은 계산(sha1(content))으로 네트워크 없이 얻을 수 있다.

  • resolution 은 클라이언트가 수행: /r 복구(또는 handoff CLI)가 위 ref 를 읽어 sidecar 를 가져온다. 로컬 캐시의 content SHA1 이 git_sha 와 일치하면 네트워크 0회로 캐시를 쓰고, 다르면 그 파일만 한 번 pull 해서 갱신한다. 가져오기에 실패하거나 오프라인이면 환경 정보만 degrade 되고 핸드오프 본문 복구는 절대 막히지 않는다. (서버는 sidecar 를 일반 vault 파일로 저장·인덱싱할 뿐, environment_ref 를 해석하지는 않는다.)
  • 자기완결 유지: sidecar 를 못 받는 상황을 대비해 핸드오프 본문에 치명 정보 1줄 요약은 항상 남긴다.

복구 (Restore) — 시간대 cluster 가져오기

여러 프로젝트를 같은 시간대에 몰아서 저장한 경우 (예: 오전에 5개), 하나만 회수하면 인접 핸드오프를 놓칠 위험이 있다. 복구 모드는 최근 cluster + 직전 cluster 의 메타데이터를 묶어 보여줘서 빠뜨림 없이 작업을 재개하도록 돕는다.

알고리즘

  1. handoff_list({limit: 50}) 호출 (응답은 updated_at 내림차순)
  2. Cluster 탐지 (gap 기반):
    • 기본 GAP_THRESHOLD = 30분
    • 인접 항목 간 gap 계산. gap ≤ 30분 → 같은 cluster, 초과 시 break
  3. 반환 범위: 최신 cluster + 직전 cluster 1개 (빠진 것 확인용)
  4. 출력: cluster 별 표 (HHMM KST / project / topic) — 본문은 fetch 하지 않음
  5. 사용자가 선택 시 단일 메시지에서 병렬 handoff_get 호출

출력 예시

## Cluster 1 — 2026-05-19 08:18~08:36 KST (5건, 18분 span)
| 시각 | project / topic |
|---|---|
| 08:36 | tennis / bracket-share-button-universal-links-0830 |
| 08:35 | refra / v2-deploy-step1-done-0834 |
| 08:30 | krx / listing-phase-10-complete-0830 |
| 08:24 | krx / listing-testflight-build2-uploaded-0824 |
| 08:18 | tennis / bracket-predict-feature-0818 |

## Cluster 2 (직전) — 2026-05-19 00:16~00:30 KST (2건)
| 00:30 | ainote / web-logout-cookie-fix-0030 |
| 00:16 | tennis / bracket-predict-feature-0016 |

옵션

  • "오전만"/"오후만" → KST hour 필터 (06~12 / 12~18)
  • "프로젝트 X 만" → project/topic 필터 후 cluster
  • "이전 cluster 더" → 직전 1개 → 2~3개로 확장
  • "본문 전부 펴줘" → cluster 내 모든 항목 병렬 fetch

구현

별도 MCP tool 없이 기존 handoff_list + 클라이언트의 in-conversation cluster 추론으로 처리. Claude Code 사용자는 session-handoff 스킬의 §복구 섹션 알고리즘 자동 발동.

Claude Code 트리거 예시

저장:

  • "이어서 다른 세션", "핸드오프 만들어", "다음 세션 넘기기"
  • "바탕화면에 핸드오프 만들어" (Desktop fallback)

복구:

  • "오전 핸드오프 복구해줘", "최근 핸드오프 복구"
  • "이어서 작업 가져와", "오늘 작업한 거 묶어서 보여줘"

안티패턴

  • ❌ "잘 진행됨" 같은 측정 불가 표현
  • ❌ 절대 경로 없이 "feature/auth 의 XXX" — 다음 세션이 못 찾음
  • ❌ STEP 에 "테스트 추가" 같은 추상적 한 줄
  • ❌ 비밀값 평문 포함
  • ❌ project/topic 슬러그에 한글·이모지·공백 (slugify 가 비-ASCII 를 - 로 변환)
  • ❌ 복구 시 메타데이터 없이 곧바로 모든 본문 fetch (토큰 낭비)
  • ❌ cluster 경계 무시하고 임의로 N개 자름