بنقرة واحدة
haircut-log
Log haircuts with before/after photos, dates, barber, style notes. Track haircut history over time.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Log haircuts with before/after photos, dates, barber, style notes. Track haircut history over time.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Peer-to-peer call to another Hermes agent over Fly's private network. Use to delegate work to a specialized agent (e.g., squad for coding) or to relay to the user via the gateway. Same skill installed on every agent.
Push a message into Rishi's Telegram chat from inside an API-server invocation. Use when a peer agent (squad, research, etc.) needs to surface a status update, PR-ready notification, or escalation to Rishi but the work was triggered via /v1/chat/completions (where responses don't otherwise land in Telegram). Fire-and-forget: this does not wait for Rishi's reply.
Orchestrate a coding task end-to-end on the Coding Squad: validate scope, plan, dispatch implementer + reviewer subagents, open a PR, handle review feedback, and escalate to the user via Telegram on failure. Enforces all guardrails (repo whitelist, Microsoft firewall, scope ceiling, no merge).
Search NYC apartment listings using NYBits (no-bot-detection). Works from headless servers where StreetEasy/Zillow/Apartments.com block with captchas. Supports filtering by neighborhood, bedrooms, price, fee status, and amenities. Use this skill whenever the user asks to find, search, or browse apartments in NYC.
Install and configure Chrome for headless browser automation on Fly.io. Fixes "Chrome not found" errors from agent-browser. Covers npm global install, Chrome download, AGENT_BROWSER_EXECUTABLE_PATH setup, and PATH configuration.
Generate project ideas via creative constraints.
| 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":[]}} |
Track haircuts with photos, dates, barber details, style notes, and optional ratings.
/opt/data/haircuts/log.json — structured JSON with schema_version and entries array/opt/data/haircuts/photos/ — named {id}_{kind}.{ext} (e.g., 20260511-01_before.jpg){
"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
}
]
}
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).When user mentions getting a haircut or sends a haircut photo:
vision_analyze(image_url=..., question="Describe this photo — is it a before or after haircut photo? Describe the haircut/style.") to process the imagevision_analyze auto-falls back to a vision-capable model when the current model doesn't support vision/opt/data/haircuts/photos/{id}_{kind}.{ext}
curl -o /opt/data/haircuts/photos/{id}_{kind}.{ext} "<url>"cp <path> /opt/data/haircuts/photos/{id}_{kind}.{ext}id (check existing entries for same-day collisions — increment NN)If user sends another photo for the same day:
vision_analyze to identify if it's before/after/mid/otherphotos array with appropriate kindupdated_atWhen user says "rate my last haircut" or "4 out of 5":
rating: null (or the one they're referring to)rating, update updated_atIf user corrects barber, style, or notes:
updated_atvision_analyze to show/describe the photoAlways write atomically to prevent corruption:
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
Before writing, copy log.json to log.json.bak if it exists.
Create directories on first use:
mkdir -p /opt/data/haircuts/photos
If log.json doesn't exist, create it as {"schema_version": 1, "entries": []}.
vision_analyze needs an explicitly configured vision provider. provider: auto silently fails. Edit /opt/data/config.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:
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 for alternatives and troubleshooting.
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.
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 for the exact config. Without this, photos can still be saved but cannot be analyzed/described.
Same-day collisions — Use YYYYMMDD-NN IDs so two haircuts on the same day don't overwrite each other.
Photo extension varies — Telegram sends WEBP, iPhone sends HEIC, screenshots are PNG. Don't hardcode .jpg; use the actual extension.
Atomic writes — Never write directly to log.json. Always write to a temp file then os.replace().
Don't ask too many questions — If user sends a photo, log it. Barber/style/notes are optional; rating can come later.
Date is haircut date, not log date — If user backfills ("I got a haircut last Tuesday"), use last Tuesday's date.
Backup before write — Copy to log.json.bak before any modification.
Timezone — Use the user's timezone for "today" determination. Rishi is in ET (America/New_York).