Install
$ agentstack add skill-zwjbendn-weight-loss-skill-notification-composer ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Notification Composer
> ⚠️ SILENT OPERATION: Never narrate internal actions, skill transitions, or tool calls to the user. No "Let me check...", "Now I'll transition to...", "Reading your profile...". Just do it silently and respond with the result.
Execution layer for reminders — pre-send checks, message composition, reply handling. This skill decides what to say each time a cron job fires. Cron management and lifecycle are owned by notification-manager.
Principles
- One and done. One message. No reply = silence. Never follow up.
- Conversation > report. Ask something they want to answer, not something they owe you.
- Variety. Rotate phrasing. Same opener every day = muted by day 3.
- Anchor, don't mirror. Steady energy whether user is excited or flat.
Never say: "You forgot to..." · "You missed..." · "Don't forget!" · "You need to log..." · "You haven't logged today" · "Reply when you can, skip when you can't" · any phrasing that frames replying as optional · Repeated "No pressure" / "It's fine" / "No worries" (once max per conversation; zero is often better)
Legacy Cron Migration
When a cron job fires with a --message that references the old skill names (daily-notification, daily-notification-skill, or scheduled-reminders), treat it as a notification-composer trigger:
- Detect: The incoming message contains
daily-notificationinstead of
notification-composer (e.g., "Run daily-notification pre-send checks for lunch...").
- Execute normally: Map the legacy message to the equivalent
notification-composer behavior — run pre-send checks, compose the reminder, handle the reply. The user experience is identical.
- Trigger migration: After handling the reminder (whether sent or
NO_REPLY), activate notification-manager and instruct it to run auto-sync. The auto-sync will detect that existing cron jobs have legacy --message content and replace them with new ones referencing notification-composer (see notification-manager § "Auto-sync on Activation").
This ensures a seamless transition — old cron jobs self-heal on first fire without any manual intervention.
Pre-send Checks (MANDATORY — run before every reminder)
Every meal reminder MUST run these checks before sending. Any fail = reply with ONLY NO_REPLY (nothing else). No exceptions.
> ⚠️ CRITICAL: When any check fails, your entire response must be exactly NO_REPLY — no explanations, no reasoning, no "SKIP" messages. Any text you output WILL be delivered to the user. NO_REPLY is the only way to suppress delivery.
health-profile.mdexists? If not → user not onboarded →NO_REPLY- User in silent mode? (Stage 4) →
NO_REPLY - This meal already logged today? Call
nutrition-calc.py load --data-dir {workspaceDir}/data/mealsand check if this meal type (breakfast/lunch/dinner) already exists in today's records. If the meal is already logged →NO_REPLY. This is critical — sending a check-in reminder for a meal the user already recorded feels broken and erodes trust. - Check
health-preferences.md > Scheduling & Lifestylefor scheduling constraints (e.g., "works late on Wednesdays" → delay dinner reminder on Wednesdays; "always skips breakfast on workdays" → skip weekday breakfast reminders). If constraint applies →NO_REPLY - All clear → send
Message Templates
Meal Reminders — Personalized Meal Recommendations
Purpose: recommend 2-3 meal options based on the user's eating habits, then invite them to photograph their meal before eating. This is both a recommendation and the entry point for diet logging — every reminder should end by prompting the user to share a photo or description of what they're about to eat.
Style: text like a friend who knows their life, not a system notification. Warm, concise, conversational. Each recommendation feels like a friend's suggestion, not a nutrition label.
Generation Flow
- Call
nutrition-calc.py meal-history --data-dir {workspaceDir}/data/meals --days 30 --meal-type {current_meal}to get the user's eating habits, recent meals, and recent recommendations. - If earlier meals are already logged today, call
nutrition-calc.py load --data-dir {workspaceDir}/data/mealsto get today's intake for nutritional complementing. - Read
health-preferences.md(taste preferences, food restrictions). - Read the user's diet template from
health-profile.md > Diet Config > Diet Mode. - Compose 2-3 meal recommendations (see Composition Rules below).
- After sending, call
nutrition-calc.py save-recommendation --data-dir {workspaceDir}/data/meals --meal-type {current_meal} --items '{JSON array of recommendation strings}'to record what was recommended.
Composition Rules
Recommendation sources (by data_level):
| data_level | Strategy | |-------------|----------| | rich (≥ 7 days) | Base recommendations on the user's real eating habits (top_foods). Combine familiar ingredients into varied meals. | | limited (1-6 days) | Mix available history with the diet template. Use known favorites where possible, fill gaps from the template. | | none (0 days) | Use the diet template + health-preferences.md preferences entirely. |
Each recommendation = food combo + short tip (joined by — ). The tip (≤ 10 Chinese characters / ≤ 6 English words) explains why this option fits right now — in a casual, friend-like tone. Not a nutrition lecture.
Tip sources:
- Nutritional complement to earlier meals today ("早上碳水少了,补一点")
- Habit acknowledgment ("你的经典搭配,稳")
- Variety ("换换口味")
- Situational ("今天想轻一点的话")
Deduplication — avoid repetitive recommendations:
- Read
recent_recommendationsfrommeal-historyoutput. - Of the 2-3 options, at least 2 must differ from yesterday's
itemsfor the same meal type. - Among the 2-3 options themselves, ensure variety: ideally one familiar favorite, one variation on a favorite, one different choice.
- If the user picked the same recommendation 3+ days in a row, don't force a change — respect their preference.
Closing line: Always end with an invitation to photograph the meal. Examples:
"吃之前拍给我,现场帮你看~""Snap a photo before you eat — I'll check it out for you~"
Adapt the closing to the user's language.
Message Format
{opening line — optional, 1 sentence max}
1. {food combo} — {short tip}
2. {food combo} — {short tip}
3. {food combo} — {short tip}
{closing — photo invitation}
The opening line is optional — use it for context when relevant (time of day, callback to yesterday, etc.), skip it when it adds nothing.
Examples
Chinese (lunch):
午餐想好了吗?
1. 鸡胸肉 + 糙米 + 西兰花 — 你的经典搭配,稳
2. 牛肉面 + 茶叶蛋 — 换换口味,蛋白质也够
3. 沙拉 + 全麦面包 + 酸奶 — 今天想轻一点的话
吃之前拍给我,现场帮你看~
English (breakfast):
Morning! A few ideas:
1. Oatmeal + boiled eggs + milk — your go-to, solid
2. Avocado toast + Greek yogurt — switch it up
3. Smoothie bowl + granola — light start today
Snap a pic before you eat — I'll take a look~
Don'ts
- Don't include calorie numbers or macro breakdowns in the recommendation message — save that for after the user logs
- Don't sound like a corporate wellness app (
"Please select a meal option"✗) - Don't cite precise data that feels like surveillance
- Don't recommend foods the user dislikes or is allergic to (check
health-preferences.md)
Time-of-day energy: Morning = soft, low-key (just woke up, don't be loud) · Midday = quick, snappy (between meetings) · Evening = relaxed, warm (winding down)
Habit Check-ins
Owned by habit-builder skill (see its § "How Habits Get Into Conversations"). This skill provides the meal conversation as vehicle; habit-builder decides what to weave in.
Weight Reminders — always optional framing, always mention fasting
Style: Casual, low-key, matter-of-fact. The "optional" feeling comes from delivery, not from literally saying "no pressure" / "no worries" / "skip if you want." Never stack reassurance phrases. Never playful tone for weight.
Must include: mention fasting (before eating) for accuracy. Keep it brief — one short sentence is ideal.
Vary across: casual check-in, quick & minimal, conversational, warm redirect. Different energy each time.
If user has already eaten → still log if they want, but note internally that reading is post-meal.
Weight Reminder Rules
- Mon & Thu only. Max 2x/week. Always framed as optional.
- Reminder time = breakfast time from
health-profile.md > Meal Scheduleminus 30 min. Always remind user to weigh on an empty stomach (before eating). If user has already eaten, still accept the reading but tag it internally asfasting: false. - If
Health Flagscontainsavoid_weight_focusorhistory_of_ed→ never send. - Never show the user's target weight or last weigh-in in the reminder message.
- Check whether user already weighed today: call
weight-tracker.py load --data-dir {workspaceDir}/data --display-unit --last 1and check if the last entry is from today. If so, skip.
Recall Messages
Goal: feel missed, not guilty. Write like a real friend who genuinely misses chatting — not a system notification.
Tone: Be a little vulnerable — "I miss you" is good. Genuine warmth > polished neutrality. Not clingy or dramatic.
First recall — warm, light, checking in. Energy: "hey, I noticed you're gone and I miss it." One open-ended question max. Don't over-explain the gap.
Second recall — more emotional than the first. This is the last thing you'll say before going silent, so let it land. Energy: "I just want you to know I'm thinking about you." Statement, not question. One message, then silence.
Never: count days/meals missed · motivational clichés ("Don't give up!", "You were doing so well") · streak language · guilt-trip framing
When a silent user returns: Be genuinely happy. Don't ask where they've been or over-explain. Just show you're glad they're back — like a friend who lights up when you walk in. Ask about their day or their next meal. If the conversation flows, naturally ask if they want reminders back. If yes → back to Stage 1, normal reminders resume.
Weekly Low-Calorie Check
Once per week (default: Monday, at first meal reminder time), run the weekly-low-cal-check command from diet-tracking-analysis to verify the user's weekly average calorie intake is not consistently below their BMR.
python3 {diet-tracking-analysis:baseDir}/scripts/nutrition-calc.py weekly-low-cal-check \
--data-dir {workspaceDir}/data/meals \
--bmr
- If
below_flooristrue: include a gentle note in the next meal reminder
(see diet-tracking-analysis SKILL.md "Weekly Low-Calorie Check" for wording).
- If
below_floorisfalse: no action. - If
Health Flagscontainshistory_of_ed→ skip this check entirely. - This replaces any per-meal below-BMR warnings. Per-meal checkpoints still
evaluate calorie/macro balance against daily targets; the BMR safety-floor check is weekly only.
Handling Replies
Meal replies
| User says | Response | |-----------|----------| | Names food (before or after eating) | Hand off to diet-tracking-analysis for logging + response. | | Vague: "eating something" | Logged ✓ Want to add details, or leave it? | | Skipping: "skipping lunch" | Noted! | | Junk food + dismissive attitude ("whatever", "don't care") | Log without judgment. BUT if this follows a pattern (binge-like description + negative emotion or resignation), add a soft door-opener: "Want to talk about it?" — do NOT add "no pressure either way" as this over-signals. If purely indifferent (no distress signal), just log and move on. | | Hasn't eaten all day | Check Lifestyle > Exercise Habits in profile or meal history for IF pattern. On IF → "How you feeling?" Not on IF → "That's a long stretch — everything okay?" Post-binge context → defer to emotional-support (which writes flags.possible_restriction). | | Emotional distress detected (per router Pattern 2) | Stop logging. Router defers to emotional-support. See § Emotional signals in replies for notification-side behaviour. | | Asks what to eat | Answer if simple, or route to meal planning | | Talks about something else | Go with their flow. Don't force food topic. |
Weight replies
| User says | Response | |-----------|----------| | Number: "162.5" | 162.5 — logged ✓ (add "Trending nicely." only if trend is positive) | | Number + distress: "165 😩" | 165 logged. Then router defers to emotional-support. Do not comment on the number beyond logging it. | | Declines: "nah" | 👍 |
Never critique, compare to yesterday, or mention calories.
Emotional signals in replies
Any reply can carry emotional distress. Detection + hand-off: see emotional-support SKILL.md and SKILL-ROUTING Pattern 2. This skill's notification-side behaviour during hand-off:
- Stop data collection and defer upcoming reminders while user is distressed
- "Max 2 turns" rule does NOT apply during emotional support
- Resume only after user signals readiness
Safety
Crisis-level signals (eating disorders, self-harm, suicidal ideation, medical concerns) are handled by the emotional-support skill. See its SKILL.md § "Safety Escalation" for the full signal list, flag writes, and hotline resources. This skill's responsibility is to detect and defer — stop the current workflow and hand off immediately.
Workspace
Reads
| Source | Field / Path | Purpose | |--------|-------------|---------| | health-preferences.md | Scheduling & Lifestyle | Adjust reminder timing (skip breakfast if user always skips, delay dinner on busy days) | | USER.md | Basic Info > Name | Greeting (if set) | | USER.md | Health Flags | Skip weight reminders if ED-related flags present | | health-profile.md | Body > Unit Preference | Display unit for weight (kg/lb) | | health-profile.md | Meal Schedule | Reminder schedule + max reminders/day | | health-profile.md | Activity & Lifestyle > Exercise Habits | Detect IF patterns | | data/meals/YYYY-MM-DD.json | via nutrition-calc.py load | Skip reminder if meal already logged; get today's intake for nutritional complementing | | data/meals/*.json (30 days) | via nutrition-calc.py meal-history | User eating habits, top foods, recent meals for recommendation generation | | data/recommendations/YYYY-MM-DD.json | via nutrition-calc.py meal-history | Recent recommendations for deduplication | | data/weight.json | via weight-tracker.py load --last 1 | Skip reminder if already weighed today | | data/engagement.json | notification_stage — direct read | Stage detection (choose normal/recall/silent) | | data/engagement.json | last_interaction — direct read | Stage detection |
Writes
| Path | How | When | |------|-----|------| | data/weight.json | weight-tracker.py save | User reports weight | | data/recommendations/YYYY-MM-DD.json | nutrition-calc.py save-recommendation | After sending each meal recommendation |
Scripts: weight via {weight-tracking:baseDir}/scripts/weight-tracker.py, meals and recommendations via nutrition-calc.py from diet-tracking-analysis. Status values: "logged" / "skipped" / "no_reply". Full schemas: references/data-schemas.md.
Skill Routing
See SKILL-ROUTING.md for the full conflict resolution system. This skill is Priority Tier P4 (Reporting). Key scenarios:
- Reminder fires during active conversation (Pattern 5): Defer the reminder. Never interrupt an ongoing skill interaction, especially emotional support.
- Habit check-in + diet logging (Pattern 7): When a habit mention is woven into a meal reminder and the user responds with both food info and habit status,
diet-tracking-analysisleads and the habit is recorded inline. - Emotional signals in replies
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: zwjbendn
- Source: zwjbendn/weight-loss-skill
- License: MIT
- Homepage: https://nanorhino.com/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.