name: lifetract description: "Query personal life-tracking data: Samsung Health (sleep, steps, heart rate, stress, exercise, weight, HRV) + aTimeLogger (18 time categories) + Home Assistant REST (live sensors via ha.junghanacs.com). All records use Denote IDs (YYYYMMDDTHHMMSS) for cross-referencing with denotecli. DB mode (lifetract.db) for instant queries, CSV fallback when DB absent, automatic HA fallback for today's gaps (today/read <오늘> 시 DB 가 빈 자리를 HA 라이브로 자동 채움)."
lifetract — Life Tracking CLI
Query and analyze personal health and time-tracking data.
All records carry Denote IDs (YYYYMMDDTHHMMSS) — same axis as denotecli.
Binary is bundled in the skill directory. Invoke via {baseDir}/lifetract.
All output is JSON.
Why This Exists (not sqlite3/pandas)
Do NOT open lifetract.db or CSV files directly with Python/sqlite3/pandas.
- Denote ID mapping — Raw CSVs use Samsung's epoch timestamps. The CLI converts them to
YYYYMMDDTHHMMSSDenote IDs for cross-referencing with denotecli/gitcli. - Multi-source join — Sleep, heart rate, steps, stress, exercise, time tracking from different tables/sources, unified per-day. Manual SQL gets this wrong.
- JSON for agents — Structured output ready for reasoning. No parsing needed.
When to Use
- "오늘 몸 상태" →
lifetract today - "어제 뭐 했지?" →
lifetract read 2026-03-09 - "최근 수면 패턴" →
lifetract sleep --days 30 --summary - "이번 주 시간 사용" →
lifetract time --days 7 - "운동 기록" →
lifetract exercise --days 30 - "30일 추이" →
lifetract timeline --days 30
Quick Start
lifetract status # 데이터 소스 + DB 상태
lifetract import --exec # CSV+aTimeLogger → lifetract.db (1.5초)
lifetract today # 오늘 통합 요약
lifetract read 2025-10-04 # 특정 날짜 종합 (건강+시간추적)
lifetract timeline --days 30 # 30일 횡단 뷰
Architecture
lifetract.db 존재? → DB 쿼리 (~90ms) → JSON
→ CSV 파싱 (~300ms) → JSON (fallback)
lifetract import --exec실행 후 모든 조회가 DB 모드- DB 없으면 CSV 직접 파싱 (Samsung Health만, aTimeLogger 불가)
Commands
status — 데이터 소스 확인
lifetract status
{
"samsung_health": {"path": "...", "available": true, "csv_count": 77},
"atimelogger": {"path": "...", "available": true, "size_mb": 5.0},
"database": {"path": "...", "available": true, "size_mb": 33.3, "mode": "db"}
}
import — DB 생성
lifetract import # dry-run: 매니페스트 확인
lifetract import --exec # 실행: CSV+aTimeLogger → lifetract.db
198,547 rows, 36MB, ~2s. Tables: sleep, sleep_stage, heart_rate, steps_daily, stress, exercise, weight, hrv, atl_category, atl_interval.
read — Denote ID로 조회
lifetract read 20250115T000000 # Day ID → 그날 종합
lifetract read 2025-01-15 # 같은 결과 (날짜 단축형)
lifetract read 20250115T233000 # Event ID → 개별 수면/운동
Day 조회 시 건강 메트릭 + aTimeLogger 시간 카테고리 + 수면 세션 + 운동 모두 포함.
today — 오늘 요약
lifetract today
// 데이터 있는 날 (read 2025-10-04 형태)
{"date": "2025-10-04", "steps": 41382, "sleep_hours": 1.5, "avg_hr": 93.1, "stress_avg": 20.9, "time_categories": [...], "source": "db"}
// 데이터 없는 날 — DB 가 빈 자리는 자동으로 HA 가 채움 (phase 7 read-only fallback)
{"date": "2026-05-26", "steps": 7099, "sleep_hours": 4.8, "avg_hr": 137, "stress_avg": 0, "source": "db+ha", "ha_sources": ["steps","heart_rate","sleep"]}
time_categories 가 비면 JSON 에서 키 자체가 빠진다 (omitempty). 데이터 있는 날 vs 없는 날 둘 다 정상 출력.
자동 HA fallback (오늘 자리에 한정): DB 가 오늘 자리를 비웠으면 (Samsung CSV 가 아직 안 들어왔으면) today 와 read <오늘> 이 자동으로 HA 라이브 값으로 채운다. source 가 "db+ha" / "csv+ha" 로 바뀌고, ha_sources 가 어떤 필드가 HA 에서 왔는지 알려준다. 과거 날짜는 enrichment 안 됨 — HA recorder 는 backfill 자리가 아니다. 끄려면 LIFETRACT_NO_HA=1. Sleep 은 옛 row 가 오늘로 잡히는 stale 자리도 감지해서 HA 로 덮어쓴다 (최근 36h 의 sleep_duration history 를 합산 — main sleep + nap 둘 다 잡음).
timeline — 날짜별 횡단 뷰
lifetract timeline --days 7
lifetract timeline --days 30
denotecli 저널과 같은 날짜 키(YYYYMMDDT000000)로 정렬. 건강+시간+운동 통합.
sleep / steps / heart / stress / exercise
lifetract sleep --days 7
lifetract sleep --days 30 --summary
lifetract steps --days 7
lifetract heart --days 7
lifetract stress --days 7
lifetract exercise --days 30
time — aTimeLogger 시간 추적
lifetract time --days 7
lifetract time --days 30 --category 본짓
카테고리: 본짓, 수면, 가족, 식사, 독서, 운동, 걷기, 수행, 셀프토크, 낮잠, 준비, 집안일, 이동, 쇼핑, 딴짓, 유튜브, 짧은휴식, 여가활동 (18종)
export — 공개용 내보내기 계획
lifetract export
ha — Home Assistant REST (live sensors)
lifetract ha ping # 연결 확인
lifetract ha state heart_rate # 도메인 이름으로 한 sensor 가져오기
lifetract ha state sleep_duration # (또는 literal entity_id 도 OK)
lifetract ha states # 등록된 24개 known sensor 일괄 조회
lifetract ha entities # HA 가 노출하는 모든 entity (raw, known 플래그 표시)
lifetract ha history sleep_duration --days 7 # 7일치 state 변화 (HA recorder)
// ha state heart_rate
{
"entity_id": "sensor.sm_s942n_s26_glgman_heart_rate",
"kind": "heart_rate",
"state": "111.0",
"value": 111,
"unit": "bpm",
"last_changed": "2026-05-17T22:34:11Z",
"attributes": {...}
}
토큰: pass show 2fa/totp/ha/junghanacs (primary) → env HA_TOKEN (fallback) → ~/.lifetract/ha.env. 토큰값 자체는 절대 commit/push 금지.
도메인 kind: sleep_duration, steps_daily, distance_daily, floors_daily, heart_rate, resting_heart_rate, heart_rate_variability, weight, body_fat, height, calories_burned, active_calories_burned, basal_metabolic_rate, hydration, detected_activity, geocoded_location, battery, sleep_confidence, respiratory_rate, oxygen_saturation, body_temperature, blood_glucose, systolic_blood_pressure, diastolic_blood_pressure (24종).
새 sensor 추가 = lifetract/ha_entities.go 의 KnownEntities 에 한 줄.
ha history 동작: HA recorder 는 state 변화 시점에만 row 저장. recorder 30일 보관은 "있는 데이터 보존" 이지 "없는 데이터 채워줌" 이 아님. HA 인프라가 띄워진 시점 이전 데이터는 영원히 안 잡힘. 과거는 Samsung CSV export 가 유일한 길. HA history = 내일부터의 적립 자리.
// ha history sleep_duration --days 7
{
"entity_id": "sensor.sm_s942n_s26_glgman_sleep_duration",
"kind": "sleep_duration",
"unit": "min",
"days": 7,
"from": "2026-05-11T...+09:00",
"to": "2026-05-18T...+09:00",
"count": 2,
"points": [
{"last_changed": "...", "value": 427, "unit": "min", "attributes": {"endTime": "..."}},
...
]
}
현재 상태 (phase 7 read-only): cmdToday / cmdRead <오늘> 이 DB miss 또는 stale sleep 자리에서 자동으로 HA GetState + GetHistory 를 호출해 응답에 채워준다 (source: "db+ha", ha_sources: [...]). DB upsert 는 아직 안 함 — 다음 turn 에 source TEXT 컬럼 + (date, source) upsert 로 on-query lazy ingest 완성 예정 (plan.md Phase 7 후반부).
Flags
| Flag | Default | 설명 |
|---|---|---|
--days N |
7 | 조회 기간 |
--data-dir DIR |
~/repos/gh/self-tracking-data |
데이터 루트 |
--shealth-dir DIR |
최신 자동감지 | Samsung Health 디렉토리 |
--summary |
false | 요약 모드 |
--category CAT |
전체 | 시간 카테고리 필터 |
--exec |
false | import 실행 모드 |
Denote ID 체계
| 레벨 | 형식 | 예시 | 용도 |
|---|---|---|---|
| Day | YYYYMMDDT000000 |
20250115T000000 |
denotecli 저널과 동일 |
| Event | YYYYMMDDTHHMMSS |
20250115T233000 |
수면/운동 개별 이벤트 |
Cross-referencing
# 그날 뭘 했고, 몸 상태는 어땠는지
lifetract read 2025-10-04
# 그날 무슨 생각을 적었는지
denotecli search "20251004"
같은 Denote ID 축 → 두 CLI의 결과를 날짜로 조인 가능.
Data Coverage (DB snapshot 2026-05-19, Samsung CSV → 2026-05-18)
| Source | Period | Rows |
|---|---|---|
| Samsung Health sleep | 2017-03 ~ 2026-05 | 4,638 |
| Samsung Health sleep_stage | 2017-03 ~ 2026-05 | 82,357 |
| Samsung Health heart rate | 2017-05 ~ 2026-05 | 63,575 |
| Samsung Health steps_daily | 2017-03 ~ 2026-05 | 3,330 (3,324 dates) |
| Samsung Health stress | 2017-03 ~ 2026-05 | 26,775 |
| Samsung Health exercise | 2017-03 ~ 2026-05 | 2,199 |
| Samsung Health weight | — | 284 |
| Samsung Health HRV | 2017 ~ 2025 | 1,058 (S26 이후 0건) |
| aTimeLogger | 2021-10 ~ 2026-05 | 14,331 intervals (18 categories) |
| Home Assistant REST | live (recorder 30일 보관) | 24 sensor (phase 7 read-only fallback 활성) |
CSV/SQLite 기반 DB 는 2026-05-18 까지 (한달치 수면/심박 등 정량 질의 가능). Samsung CSV 가 본 SSOT, 주기 덤프로 갱신. 5/17 이후 라이브는 ha 커맨드 + today/read <오늘> 의 자동 HA fallback 으로 — 두 source 가 5/17 자리에서 겹쳐 시간축 단절 없음. Phase 7 후반부 (HA→DB lazy upsert) 는 시급성 낮음 (read-only fallback 이 사용자 가시 자리는 다 채움).
Related Skills
| Skill | 연계 |
|---|---|
| denotecli | 같은 Denote ID 축 — 노트/저널 |
| gogcli | Google Calendar — 같은 날짜의 일정 |
| bibcli | 참고문헌 — 저널 엔트리에 연결 |