Skip to main content

haircut-log

Log haircuts with before/after photos, dates, barber, style notes. Track haircut history over time.

설치로 이동

소스 정보

저장소
rishijatia/Hakan
최근 소스 활동
2026년 5월 13일 03:15
감지된 SKILL.md 언어
영어
스타
0
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
haircut-log
version
0.1.0
description
Log haircuts with before/after photos, dates, barber, style notes. Track haircut history over time.
triggers
["haircut","barber","hair style","before after","haircut log","haircut history"]
metadata
{"hermes":{"tags":["lifestyle","photos","personal","grooming"],"related_skills":[]}}
# Haircut Log Track haircuts with photos, dates, barber details, style notes, and optional ratings. ## Storage - **Log file:** `/opt/data/haircuts/log.json` — structured JSON with `schema_version` and `entries` array - **Photos:** `/opt/data/haircuts/photos/` — named `{id}_{kind}.{ext}` (e.g., `20260511-01_before.jpg`) ## Schema (v1) ```json { "schema_version": 1, "entries": [ { "id": "20260511-01", "date": "2026-05-11", "created_at": "2026-05-11T10:30:00Z", "updated_at": "2026-05-11T18:00:00Z", "barber": "Name or shop", "style": "Description of cut", "tags": ["fade", "short"], "cost": null, "notes": "Any extra notes", "photos": [ {"kind": "before", "path": "photos/20260511-01_before.jpg"}, {"kind": "after", "path": "photos/20260511-01_after.jpg"} ], "rating": null } ] } ``` ### Fields - `id` — `YYYYMMDD-NN` (date + sequence number for same-day duplicates). Required. - `date` — Haircut date, `YYYY-MM-DD`. Required. - `created_at` — ISO 8601 timestamp when entry was created. Required. - `updated_at` — ISO 8601 timestamp of last modification. Updated on rating, photo additions, etc. - `barber` — Name of barber or shop. Optional. - `style` — Description of the haircut/style requested. Optional. - `tags` — Array of searchable tags: `["fade", "beard-trim", "short", "long"]`. Optional. - `cost` — Price in dollars (number). Optional. - `notes` — Freeform notes. Optional. - `photos` — Array of `{kind, path}` objects. `kind` is `"before"`, `"after"`, `"mid"`, or `"other"`. Optional. - `rating` — 1-5 rating, can be added later. Optional (stored as `null` until rated). ## Usage ### Logging a New Haircut When user mentions getting a haircut or sends a haircut photo: 1. **Photo processing with vision model:** - Use `vision_analyze(image_url=..., question="Describe this photo — is it a before or after haircut photo? Describe the haircut/style.")` to process the image - `vision_analyze` auto-falls back to a vision-capable model when the current model doesn't support vision - This lets you "see" the photo even on non-vision models 2. **Save the photo** to `/opt/data/haircuts/photos/{id}_{kind}.{ext}` - If the image is a URL, download it: `curl -o /opt/data/haircuts/photos/{id}_{kind}.{ext} "<url>"` - If the image is a local file path, copy it: `cp <path> /opt/data/haircuts/photos/{id}_{kind}.{ext}` 3. **Create entry** with today's date and a new `id` (check existing entries for same-day collisions — increment `NN`) 4. **Ask minimally** — if user just sends a photo, log it. Don't interrogate about barber/style/notes unless they volunteer. ### Adding a Photo Later If user sends another photo for the same day: - Process with `vision_analyze` to identify if it's before/after/mid/other - Find existing entry for today (or most recent entry if sent same day) - Add photo to the entry's `photos` array with appropriate `kind` - Update `updated_at` ### Rating Later When user says "rate my last haircut" or "4 out of 5": - Find the most recent entry with `rating: null` (or the one they're referring to) - Set `rating`, update `updated_at` ### Updating an Entry If user corrects barber, style, or notes: - Find entry by date or "last one" - Update the field(s), set `updated_at` ### Queries - **"Show last haircut"** → Read last entry, use `vision_analyze` to show/describe the photo - **"How often do I get haircuts?"** → Compute average days between entries - **"Show all by Tony"** → Filter entries by barber field - **"Show all fades"** → Filter by tags containing "fade" ## Atomic Write Rule **Always** write atomically to prevent corruption: ```python import json, os, tempfile fd, tmp = tempfile.mkstemp(dir="/opt/data/haircuts", suffix=".tmp") try: with os.fdopen(fd, "w") as f: json.dump(data, f, indent=2) os.replace(tmp, "/opt/data/haircuts/log.json") except: os.unlink(tmp) raise ``` ## Backup Rule Before writing, copy `log.json` to `log.json.bak` if it exists. ## Setup Create directories on first use: ```bash mkdir -p /opt/data/haircuts/photos ``` If `log.json` doesn't exist, create it as `{"schema_version": 1, "entries": []}`. ### Vision Setup (required for photo analysis) `vision_analyze` needs an explicitly configured vision provider. `provider: auto` silently fails. Edit `/opt/data/config.yaml`: ```yaml auxiliary: vision: provider: openrouter model: google/gemini-2.0-flash-001 base_url: https://openrouter.ai/api/v1 api_key: '' # empty = uses main provider's key timeout: 120 ``` After editing, **restart the gateway** for changes to take effect: ```bash fly apps restart hermes-agent ``` The config change must also be synced to GitHub (`flyio/config.yaml` in the Hakan repo). See [references/vision-setup.md](references/vision-setup.md) for alternatives and troubleshooting. ## Pitfalls 1. **EXIF leaks location** — Always strip EXIF from photos before saving. Telegram re-encodes photos (usually strips EXIF), but direct file uploads may retain it. If Pillow is available: `python3 -c "from PIL import Image; Image.open(f).save(f, exif=b'')"`. If not, note it as a known limitation. 2. **Vision model for photos** — `vision_analyze` requires a vision provider **explicitly** configured in `config.yaml`. The `provider: auto` setting silently fails even when API keys are present. You must set all three: `provider`, `model`, and `base_url`. See [references/vision-setup.md](references/vision-setup.md) for the exact config. Without this, photos can still be saved but cannot be analyzed/described. 3. **Same-day collisions** — Use `YYYYMMDD-NN` IDs so two haircuts on the same day don't overwrite each other. 3. **Photo extension varies** — Telegram sends WEBP, iPhone sends HEIC, screenshots are PNG. Don't hardcode `.jpg`; use the actual extension. 4. **Atomic writes** — Never write directly to `log.json`. Always write to a temp file then `os.replace()`. 5. **Don't ask too many questions** — If user sends a photo, log it. Barber/style/notes are optional; rating can come later. 6. **Date is haircut date, not log date** — If user backfills ("I got a haircut last Tuesday"), use last Tuesday's date. 7. **Backup before write** — Copy to `log.json.bak` before any modification. 8. **Timezone** — Use the user's timezone for "today" determination. Rishi is in ET (America/New_York).
GitHub에서 보기