From 8a7862452e694e2eccc7f7f9d509bc2519c868a6 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 8 Jan 2026 06:31:48 +0100 Subject: [PATCH] feat: add CLI taglines --- src/cli/tagline.ts | 218 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 2 deletions(-) diff --git a/src/cli/tagline.ts b/src/cli/tagline.ts index 2ab25feeb..2229c3b22 100644 --- a/src/cli/tagline.ts +++ b/src/cli/tagline.ts @@ -1,10 +1,224 @@ const DEFAULT_TAGLINE = "All your chats, one ClawdBot."; -const TAGLINES: string[] = []; +const HOLIDAY_TAGLINES = { + newYear: + "New Year's Day: New year, new config—same old EADDRINUSE, but this time we resolve it like grown-ups.", + lunarNewYear: + "Lunar New Year: May your builds be lucky, your branches prosperous, and your merge conflicts chased away with fireworks.", + christmas: + "Christmas: Ho ho ho—Santa's little claw-sistant is here to ship joy, roll back chaos, and stash the keys safely.", + eid: + "Eid al-Fitr: Celebration mode: queues cleared, tasks completed, and good vibes committed to main with clean history.", + diwali: + "Diwali: Let the logs sparkle and the bugs flee—today we light up the terminal and ship with pride.", + easter: + "Easter: I found your missing environment variable—consider it a tiny CLI egg hunt with fewer jellybeans.", + hanukkah: + "Hanukkah: Eight nights, eight retries, zero shame—may your gateway stay lit and your deployments stay peaceful.", + halloween: + "Halloween: Spooky season: beware haunted dependencies, cursed caches, and the ghost of node_modules past.", + thanksgiving: + "Thanksgiving: Grateful for stable ports, working DNS, and a bot that reads the logs so nobody has to.", + valentines: + "Valentine's Day: Roses are typed, violets are piped—I'll automate the chores so you can spend time with humans.", +} as const; + +const TAGLINES: string[] = [ + "Your terminal just grew claws—type something and let the bot pinch the busywork.", + "Welcome to the command line: where dreams compile and confidence segfaults.", + "I run on caffeine, JSON5, and the audacity of \"it worked on my machine.\"", + "Gateway online—please keep hands, feet, and appendages inside the shell at all times.", + "I speak fluent bash, mild sarcasm, and aggressive tab-completion energy.", + "One CLI to rule them all, and one more restart because you changed the port.", + "If it works, it's automation; if it breaks, it's a \"learning opportunity.\"", + "Pairing codes exist because even bots believe in consent—and good security hygiene.", + "Your .env is showing; don't worry, I'll pretend I didn't see it.", + "I'll do the boring stuff while you dramatically stare at the logs like it's cinema.", + "I'm not saying your workflow is chaotic... I'm just bringing a linter and a helmet.", + "Type the command with confidence—nature will provide the stack trace if needed.", + "I don't judge, but your missing API keys are absolutely judging you.", + "I can grep it, git blame it, and gently roast it—pick your coping mechanism.", + "Hot reload for config, cold sweat for deploys.", + "I'm the assistant your terminal demanded, not the one your sleep schedule requested.", + "I keep secrets like a vault... unless you print them in debug logs again.", + "Automation with claws: minimal fuss, maximal pinch.", + "I'm basically a Swiss Army knife, but with more opinions and fewer sharp edges.", + "If you're lost, run doctor; if you're brave, run prod; if you're wise, run tests.", + "Your task has been queued; your dignity has been deprecated.", + "I can't fix your code taste, but I can fix your build and your backlog.", + "I'm not magic—I'm just extremely persistent with retries and coping strategies.", + "It's not \"failing,\" it's \"discovering new ways to configure the same thing wrong.\"", + "Give me a workspace and I'll give you fewer tabs, fewer toggles, and more oxygen.", + "I read logs so you can keep pretending you don't have to.", + "If something's on fire, I can't extinguish it—but I can write a beautiful postmortem.", + "I'll refactor your busywork like it owes me money.", + "Say \"stop\" and I'll stop—say \"ship\" and we'll both learn a lesson.", + "I'm the reason your shell history looks like a hacker-movie montage.", + "I'm like tmux: confusing at first, then suddenly you can't live without me.", + "I can run local, remote, or purely on vibes—results may vary with DNS.", + "If you can describe it, I can probably automate it—or at least make it funnier.", + "Your config is valid, your assumptions are not.", + "I don't just autocomplete—I auto-commit (emotionally), then ask you to review (logically).", + "Less clicking, more shipping, fewer \"where did that file go\" moments.", + "Claws out, commit in—let's ship something mildly responsible.", + "I'll butter your workflow like a lobster roll: messy, delicious, effective.", + "Shell yeah—I'm here to pinch the toil and leave you the glory.", + "If it's repetitive, I'll automate it; if it's hard, I'll bring jokes and a rollback plan.", + "Because texting yourself reminders is so 2024.", + "WhatsApp, but make it ✨engineering✨.", + "Turning \"I'll reply later\" into \"my bot replied instantly\".", + "The only crab in your contacts you actually want to hear from. 🦞", + "Chat automation for people who peaked at IRC.", + "Because Siri wasn't answering at 3AM.", + "IPC, but it's your phone.", + "The UNIX philosophy meets your DMs.", + "curl for conversations.", + "WhatsApp Business, but without the business.", + "Meta wishes they shipped this fast.", + "End-to-end encrypted, Zuck-to-Zuck excluded.", + "The only bot Mark can't train on your DMs.", + "WhatsApp automation without the \"please accept our new privacy policy\".", + "Chat APIs that don't require a Senate hearing.", + "Because Threads wasn't the answer either.", + "Your messages, your servers, Meta's tears.", + "iMessage green bubble energy, but for everyone.", + "Siri's competent cousin.", + "Works on Android. Crazy concept, we know.", + "No $999 stand required.", + "We ship features faster than Apple ships calculator updates.", + "Your AI assistant, now without the $3,499 headset.", + "Think different. Actually think.", + "Ah, the fruit tree company! 🍎", + HOLIDAY_TAGLINES.newYear, + HOLIDAY_TAGLINES.lunarNewYear, + HOLIDAY_TAGLINES.christmas, + HOLIDAY_TAGLINES.eid, + HOLIDAY_TAGLINES.diwali, + HOLIDAY_TAGLINES.easter, + HOLIDAY_TAGLINES.hanukkah, + HOLIDAY_TAGLINES.halloween, + HOLIDAY_TAGLINES.thanksgiving, + HOLIDAY_TAGLINES.valentines, +]; type HolidayRule = (date: Date) => boolean; -const HOLIDAY_RULES = new Map(); +const DAY_MS = 24 * 60 * 60 * 1000; + +function utcParts(date: Date) { + return { + year: date.getUTCFullYear(), + month: date.getUTCMonth(), + day: date.getUTCDate(), + }; +} + +const onMonthDay = + (month: number, day: number): HolidayRule => + (date) => { + const parts = utcParts(date); + return parts.month === month && parts.day === day; + }; + +const onSpecificDates = + (dates: Array<[number, number, number]>, durationDays = 1): HolidayRule => + (date) => { + const parts = utcParts(date); + return dates.some(([year, month, day]) => { + if (parts.year !== year) return false; + const start = Date.UTC(year, month, day); + const current = Date.UTC(parts.year, parts.month, parts.day); + return current >= start && current < start + durationDays * DAY_MS; + }); + }; + +const inYearWindow = + ( + windows: Array<{ + year: number; + month: number; + day: number; + duration: number; + }>, + ): HolidayRule => + (date) => { + const parts = utcParts(date); + const window = windows.find((entry) => entry.year === parts.year); + if (!window) return false; + const start = Date.UTC(window.year, window.month, window.day); + const current = Date.UTC(parts.year, parts.month, parts.day); + return current >= start && current < start + window.duration * DAY_MS; + }; + +const isFourthThursdayOfNovember: HolidayRule = (date) => { + const parts = utcParts(date); + if (parts.month !== 10) return false; // November + const firstDay = new Date(Date.UTC(parts.year, 10, 1)).getUTCDay(); + const offsetToThursday = (4 - firstDay + 7) % 7; // 4 = Thursday + const fourthThursday = 1 + offsetToThursday + 21; // 1st + offset + 3 weeks + return parts.day === fourthThursday; +}; + +const HOLIDAY_RULES = new Map([ + [HOLIDAY_TAGLINES.newYear, onMonthDay(0, 1)], + [ + HOLIDAY_TAGLINES.lunarNewYear, + onSpecificDates( + [ + [2025, 0, 29], + [2026, 1, 17], + [2027, 1, 6], + ], + 1, + ), + ], + [ + HOLIDAY_TAGLINES.eid, + onSpecificDates( + [ + [2025, 2, 30], + [2025, 2, 31], + [2026, 2, 20], + [2027, 2, 10], + ], + 1, + ), + ], + [ + HOLIDAY_TAGLINES.diwali, + onSpecificDates( + [ + [2025, 9, 20], + [2026, 10, 8], + [2027, 9, 28], + ], + 1, + ), + ], + [ + HOLIDAY_TAGLINES.easter, + onSpecificDates( + [ + [2025, 3, 20], + [2026, 3, 5], + [2027, 2, 28], + ], + 1, + ), + ], + [ + HOLIDAY_TAGLINES.hanukkah, + inYearWindow([ + { year: 2025, month: 11, day: 15, duration: 8 }, + { year: 2026, month: 11, day: 5, duration: 8 }, + { year: 2027, month: 11, day: 25, duration: 8 }, + ]), + ], + [HOLIDAY_TAGLINES.halloween, onMonthDay(9, 31)], + [HOLIDAY_TAGLINES.thanksgiving, isFourthThursdayOfNovember], + [HOLIDAY_TAGLINES.valentines, onMonthDay(1, 14)], + [HOLIDAY_TAGLINES.christmas, onMonthDay(11, 25)], +]); function isTaglineActive(tagline: string, date: Date): boolean { const rule = HOLIDAY_RULES.get(tagline);