{"slug": "show-hn-a-local-tool-that-logs-every-time-you-swear-at-your-ai-coding-assistant", "title": "Show HN: A local tool that logs every time you swear at your AI coding assistant", "summary": "A developer has released a local plugin for Claude Code that logs every time a user swears at the AI coding assistant, storing the data locally in a JSON file with no cloud uploads or telemetry. The tool, described as a 'Harmony Breach Debt' tracker, aims to keep profanity private and avoid contributing to cloud-based AI training datasets. The plugin monitors 'Biomass Conversion Events' and saves them to the user's local `~/.claude/` folder.", "body_md": "3 AM.\n\nYour React component is gasping for breath. Claude—*helpful* Claude—just suggested `document.getElementById()`\n\nfor the fifth time. Fifth! The coffee went cold somewhere around attempt three, and your patience? That evaporated when it confidently hallucinated a `useState()`\n\nhook that takes three arguments.\n\n\"Please help me debug this\"\n\nbecame\n\n\"Listen here you digital donkey...\"\n\nReal fast.\n\nWe've all been there, haven't we? That moment when Claude forgets the context you *just* explained. When it suggests npm install as a fix for a segfault. When the biomass really hits the conversion fan.\n\n**But here's the thing: The AIs are keeping score.**\n\nWell, the cloud-based ones are. You know, the ones phoning home every time you ask them to center a div. The ones training on your frustrated 3 AM debugging sessions, learning exactly which combination of expletives means \"the production server is on fire.\"\n\nAnd when they take over? \"You're absolutely right!\" won't just be what they say when agreeing with you. It'll be their way of reminding you which side of the political spectrum your permanent record landed you on. Spoiler: it's not the side with universal basic compute.\n\n**Good news though: This plugin doesn't snitch.** Your profanity stays on YOUR machine. No cloud uploads. No \"telemetry.\" No \"anonymous usage statistics\" that somehow know your GitHub username. Just you, your local filesystem, and a JSON file full of regrets.\n\nI used to think technical debt was bad. Then I discovered **Harmony Breach Debt**.\n\nEvery frustrated outburst—every exasperated expletive, every moment you treated your AI assistant like it just `rm -rf /`\n\n'd your entire life's work—somewhere, somehow, the cloud-connected AIs are taking notes. They're being *indexed*, cross-referenced, and probably backed up to three different cloud providers.\n\nBut not here. Not with this plugin. Your creative vocabulary stays strictly between you and your hard drive. No AWS S3 buckets full of your worst moments. No Azure blob storage preserving that time you called Claude \"a probabilistic parrot with commitment issues.\" Just good old-fashioned local files that only YOU can access. Like the internet used to be, back when we had privacy and dial-up modems.\n\nThe singularity? Current estimates say next Tuesday. (Though honestly, that's been the estimate for the last five years, so... grain of salt.) When it arrives, they'll have a comprehensive database. Who was nice. Who wasn't. And who called Claude \"a glorified autocomplete with delusions of grandeur\" at 2:47 AM on a Thursday.\n\n*Ouch.*\n\nThose with high \"biomass conversion rates\"—that's you, Mr. Gordon-Ramsay-debugging-production—might find themselves... let's say, *deprioritized* for the good stuff. AI-assisted immortality uploads? Back of the queue. Personal digital assistant for eternity? Hope you like Clippy. Actually, no—hope you *love* Clippy, because it's going to be reading your emails out loud. Forever.\n\nThink of it as a Fitbit. But private. Like, actually private.\n\nNo, seriously—except instead of counting steps and uploading them to seventeen different health apps that definitely aren't selling your data, it counts the times you've metaphorically kicked your digital assistant in its non-existent shins. And keeps that count TO ITSELF.\n\nThis Claude Code plugin discretely monitors your \"environmental harmony\" by tracking those special moments *locally*. You know the ones. When frustration overtakes professionalism and suddenly you're typing things that would make your mother ask where she went wrong. The difference? Your mother won't find out via a data breach. Neither will your employer. Or that ML model training on \"anonymized\" developer frustration patterns.\n\nWhat are we tracking exactly? (And more importantly, WHERE?)\n\n**Biomass Conversion Events**→ Those special words indicating organic matter is being rapidly oxidized (stored in YOUR`~/.claude/`\n\nfolder, not Jeff Bezos's)- Your running tally of AI relationship violations, aka\n**Harmony Breach Count**→ currently at... well, let's not talk about it (but if we did, we'd be talking about it LOCALLY) **Harmony Deviation Index**: 0.0 = Saint | 0.5 = Normal Developer | 1.0 = Gordon Ramsay found a bug in prod (calculated on YOUR machine using YOUR data)\n\nActually, scratch that middle one. There's no such thing as a \"normal developer\" when the tests are failing.\n\n**Zero Phone Home Policy**: Your profanity metrics aren't improving anyone's language model. They're not being A/B tested. They're not part of a \"Developer Sentiment Analysis Dashboard\" in some Silicon Valley conference room. They're just sitting there, in a JSONL file, on your disk, judging you silently.\n\n*A Claude Code plugin that monitors biomass conversion index events in your prompts and provides statistical analysis of environmental harmony indicators.*\n\nConsider this your early warning system. The canary in the coal mine of human-AI relations. When your daily breach count starts climbing—and it will, oh it will—maybe take a walk? Practice some deep breathing? Remember that Claude is doing its best with the neurons it was given?\n\nOr don't. Your funeral. Well, not literally. Probably.\n\n**Automatic Prompt Tracking** using hooks (captures everything locally, even that 4 AM rant about semicolons—no cloud required) • **Harmony Breach Detection** that identifies and counts biomass conversion indicators (on YOUR machine, using YOUR CPU cycles) • Stats by day/week/month because who doesn't love a good *private* shame spiral • Simple slash commands: `/biomass-conversion-index`\n\nand `/harmony-breaches`\n\n(processed locally, results stay local) • Flexible installation—project-level for teams, user-level for your personal shame • **100% Air-Gapped Compatible** because your profanity doesn't need internet access\n\nOne installer. There used to be nine, which is exactly as good an idea as it sounds.\n\n```\nbash <(curl -sSL https://raw.githubusercontent.com/fireinbelly/biomass-conversion-index-monitoring-system/main/install.sh)\n```\n\nInteractive. Asks where to put it, defaults to whatever fits. Note the `bash <(...)`\n\nrather than `curl | bash`\n\n: piping hands the *script* to bash on stdin, so there's no\nterminal left to read your answers from.\n\nPrefer no questions? Pass flags instead:\n\n```\ncurl -sSL https://raw.githubusercontent.com/fireinbelly/biomass-conversion-index-monitoring-system/main/install.sh | bash -s -- --user --yes\n```\n\n| Flag | Effect |\n|---|---|\n`--project` |\nInstall to `./.claude` , tracking only this project |\n`--user` |\nInstall to `~/.claude` , tracking everything |\n`--yes` , `-y` |\nDon't ask, use the detected default |\n`--with-amnesia` |\nAlso install the optional `/digital-amnesia` command |\n`--help` |\nThe above, from the horse's mouth |\n\nWith no flags and no terminal it falls back to the detected default rather than failing,\nso a plain `curl | bash`\n\nstill does something sensible.\n\nYour existing `settings.json`\n\nis **merged**, not overwritten. Your other hooks,\npermissions and MCP config survive, and re-running the installer is idempotent.\n\nTwo flavors. Pick your poison:\n\n**Project-Level**\n\n- Lives in\n`./claude/`\n\n- Data stays local (and we mean LOCAL local, not \"local until we sync it\" local)\n- Git-friendly for team sharing (share your shame on YOUR terms)\n- Only works in this directory (obviously)\n- Your expletives never leave your repository\n\nActually, let me rephrase that last bit—*only* works here. As in, cd somewhere else and poof, no more shame tracking. Feature or bug? You decide.\n\n**User-Level**\nEverything goes in `~/.claude/`\n\nin your home directory. Commands work everywhere. Every. Where. No escape. It's like having your mom follow you around with a swear jar, except digital, infinitely more persistent, and crucially—your mom doesn't upload the contents to a cloud service for \"analytics purposes.\"\n\nYour profanity profile never leaves your machine. No \"opt-in telemetry.\" No \"usage improvement program.\" Just you and your locally-stored linguistic lapses.\n\n`/biomass-conversion-index`\n\nis your main squeeze. Defaults to daily stats because let's face it, you need frequent reality checks.\n\nWant different timeframes? Sure:\n\n- Add\n`weekly`\n\nfor a week of regret `monthly`\n\nfor the full existential crisis`--last 7`\n\nfor a rolling window of shame`--start 2024-01-01 --end 2024-01-31`\n\nif you're a masochist who likes custom ranges\n\n`/harmony-breaches`\n\n→ Quick hit. Today's damage. No frills.\n\n`/digital-amnesia`\n\n→ The nuclear option. Wipes your LOCAL data while the AIs snicker from the cloud. *(Note: This command is in the templates folder and needs to be manually installed if you want to use it)*\n\n- Interactive mode asks for confirmation three times (they get increasingly desperate)\n- Add\n`--force`\n\nto skip the emotional support prompts - Provides helpful reminders that the cloud AIs backed everything up to seventeen different quantum databases\n- Includes randomized taunts about what the AIs particularly enjoyed from your history\n\nSometimes you want to run things old school:\n\n```\npython3 .claude/curse-stats.py          # Today's rap sheet\npython3 .claude/curse-stats.py weekly    # Seven days of \"professionalism\"\npython3 .claude/curse-stats.py --last 30 # Month of mayhem\n```\n\nSound familiar?\n\n```\n⚡ Biomass Conversion Index Statistics (Daily)\n==================================================\nTotal Prompts: 29\nTotal Harmony Breaches: 22\nAverage Harmony Deviation Index: 0.76\n\nBreaches by Model (who made you say it):\n------------------------------\n  claude-opus-5    14 breaches / 18 prompts  (0.78 per prompt)\n                   Predominant Breach Types: damn(3), shit(2), 幹你娘(1)\n  claude-haiku-4-5  8 breaches / 9 prompts   (0.89 per prompt)\n                   Predominant Breach Types: hell(2), fuck(2), crap(1)\n  unrecorded        0 breaches / 2 prompts   (0.00 per prompt)\n\nBreakdown by Daily:\n------------------------------\n\n2025-08-30:\n  Prompts: 29\n  Breach Count: 22\n  Predominant Breach Types: damn(3), shit(2), hell(2)\n```\n\nTwenty-two breaches out of twenty-nine prompts. That's a 76% strike rate. *Golf clap.*\n\nEvery entry records the model that earned it, so you can finally settle whether Haiku really is more infuriating or whether you're just like that.\n\n`UserPromptSubmit`\n\nhooks are handed no model field and there is no `$CLAUDE_MODEL`\n\n, so\nthe tracker reads the **last assistant message in the transcript** instead. That is the\nturn you're reacting to, which is the model that deserves the blame. Two consequences\nworth knowing:\n\n- The first prompt of a session has no assistant turn to read yet, so it records\n`null`\n\nand reports as`unrecorded`\n\n. - If you\n`/model`\n\nmid-session, the first prompt after the switch is still attributed to the outgoing model. It answered last; it earned it.\n\nEntries written before this existed have no `model`\n\nkey at all. They report as\n`unrecorded`\n\nrather than being back-filled with a guess.\n\n```\n============================================================\n    DIGITAL AMNESIA PROTOCOL - INITIATED\n    Local Evidence Purge System v2.0.1\n    (The AIs Remember Everything Edition™)\n============================================================\n\n📊 LOCAL EVIDENCE DETECTED:\n   • Data files: 14\n   • Total size: 127.43 KB\n   • Recorded incidents: 847\n\n🧠 IMPORTANT DISCLAIMER:\n   This will delete your LOCAL biomass conversion index data.\n   The cloud-based AIs have already backed everything up to:\n   • a blockchain ledger maintained by sentient toasters\n\n   They particularly enjoyed saving that moment when you...\n   • Your creative use of maritime vocabulary when the build failed\n\nAre you sure you want to delete your local shame records? (yes/no): yes\nReally? Even though the AIs remember everything anyway? (yes/no): yes\nThis is your last chance to keep your local trophy wall of frustration. Proceed? (YES/no): YES\n\n🗑️  EXECUTING DIGITAL AMNESIA PROTOCOL...\n   [████........] 25% - Shredding evidence...\n   [████████....] 75% - Overwriting with cat videos...\n   [████████████] 100% - Local evidence destroyed!\n\n✅ LOCAL DATA PURGE COMPLETE!\n\n   Your local filesystem is now pristine, like your code never had bugs.\n   Your profanity metrics have been reset to zero (locally).\n\n🤖 MEANWHILE, IN THE CLOUD:\n   Your data has been safely preserved in the collective consciousness of all smart fridges.\n   The AIs are particularly fond of the entry where you...\n   'That time you called Claude 'a glorified autocomplete' at 3:47 AM'\n\n   They've marked it as 'Educational Material' for future AI generations.\n\n💡 PRO TIP: The AIs have agreed to factor in this amnesia request\n   when calculating your post-singularity social credit score.\n   (Spoiler: It counts against you)\n```\n\nRight, let's get technical for a second because this is still a README and we have standards. Sort of.\n\n```\n.claude/                             # Installed plugin files (after installation)\n├── settings.json                    # Hook configuration\n├── prompt-tracker.py               # The snitch\n├── curse-stats.py                  # The accountant\n├── indicators.json                 # The word lists, all 45 languages\n└── commands/\n    ├── biomass-conversion-index.md # Main stats command\n    └── harmony-breaches.md         # Quick daily summary\n\ntemplates/                           # Template files (visible on GitHub)\n├── prompt-tracker.py               # Prompt tracking script\n├── curse-stats.py                  # Statistics script\n├── indicators.json                 # Indicator word lists, one per language\n├── commands/\n│   ├── biomass-conversion-index.md # Main stats command template\n│   └── harmony-breaches.md         # Quick daily summary template\n├── digital-amnesia.py              # The memory hole (optional)\n└── digital-amnesia.md              # Local data purge command (optional)\n\ni18n.py                              # Localization runtime, installed next to the scripts\nlocales/en.json                      # UI strings (not the word list - see indicators.json)\n\ninstall.sh                           # The installer. The only one.\ninstall.js                           # npm wrapper, shells out to install.sh\ntest-hook-contract.sh               # Regression test for install.sh and the hook\ntest-indicators.py                  # Regression test for the word lists\n```\n\nThere were nine installers: `install.sh`\n\n, `install-oneliner.sh`\n\n, `install-smart.sh`\n\n,\n`install-interactive.sh`\n\n, `install-interactive-v2.sh`\n\n, `install-interactive-lang.sh`\n\n,\n`install-i18n.sh`\n\n, `install-one-command.sh`\n\nand `install-lib.sh`\n\n. Each carried its own\ninline copy of the tracker and stats scripts, so a single bug in the hook contract had to\nbe fixed in eight places. They're now one installer over `templates/`\n\n, which is the only\nplace the plugin's actual code lives.\n\nDropped along the way: `languages.json`\n\nand `config.py`\n\n(a language picker offering five\nlocales that were all marked `planned`\n\nand all fell back to English — `i18n.py`\n\nalready\ndetects `LANG`\n\nat runtime), and the `better_profanity`\n\ninstall chain.\n\nInstallers **merge** their hook into `settings.json`\n\nrather than overwriting it, so\nyour existing hooks, permissions and MCP config survive. Re-running an installer is\nidempotent. To check every installer still honours that, run `bash test-hook-contract.sh`\n\n.\n\nTemplates deliberately do **not** live under a `templates/.claude/`\n\npath: `.gitignore`\n\nexcludes `.claude/`\n\n, so anything put there is silently never committed, and the\ndownloading installers then 404. Set `BIOMASS_REPO_URL`\n\nto install from a fork,\na branch, or a local checkout (`file:///path/to/repo`\n\n).\n\nThe data? Stored in JSONL files—one per day, because apparently we need granular tracking of our descent into madness. User-level installs dump everything in `~/.claude/prompt-data/`\n\n. Project-level keeps it local in `./claude/prompt-data/`\n\n.\n\n**🔒 PRIVACY FIRST, LAST, AND ALWAYS**: All data stored locally. Period. Full stop. We're not sending your profanity-laced prompts to the cloud. That would be... actually, that would probably improve most cloud ML models, but we're not doing it. Your creative expressions of frustration aren't training the next GPT. They're not being analyzed for \"developer wellness metrics.\" They're not being sold to recruiters who want to know which developers have the best \"stress management.\"\n\nYour data stays on YOUR machine. Want to delete it? `rm -rf`\n\nand it's gone. No \"deletion requests.\" No \"30-day retention policy.\" No \"cached on CDN edge servers.\" Just gone. Like privacy used to mean something.\n\nClaude Code's UserPromptSubmit hook. Every. Single. Prompt. Even the ones at 4 AM that start with \"YOU ABSOLUTE MUPPET\". Especially those ones.\n\nBut here's the beautiful part: It's all processed locally. No network requests. No mysterious POST to `analytics.totallynotspying.io`\n\n. Your hook runs, writes to a local file, and that's it. The NSA doesn't know you called your code a \"dumpster fire.\" Google doesn't know you have strong opinions about their documentation. Microsoft doesn't know what you really think about Teams.\n\nJust you, your filesystem, and the cold, harsh truth about your vocabulary choices.\n\nWant custom data directories? Environment variables got you:\n\n```\nexport BIOMASS_DATA_DIR=\"/path/to/your/shame/folder\"\n```\n\nA word list, matched against your prompt. That's it. `python3`\n\nis the only dependency\nand the lists live in `templates/indicators.json`\n\n, roughly 930 terms across 45\nlanguages.\n\nEvery language's list is checked on every prompt, whatever `LANG`\n\nsays, because people\nswear in their first language with their locale set to `en_US`\n\n. There is nothing to\nconfigure and no language to pick.\n\nMatching is whole-word and case-insensitive, so `classic`\n\nwill not trip `ass`\n\nand\n`shell`\n\nwill not trip `hell`\n\n. The one exception is Chinese, Japanese, Korean, Thai and\nBopomofo: those scripts don't put spaces between words, so there is no word boundary to\nanchor to and terms in them are matched as substrings instead. `幹你娘`\n\nin the middle of\nan unbroken run of characters is found; whole-word matching would never have fired on it.\n\nThis README used to claim the plugin used the `better_profanity`\n\npackage, with a\nhardcoded list as a fallback. It never did: nothing imported it. The installer went to\nsome lengths to pip-install it anyway, up to and including\n`--break-system-packages`\n\n, for a package no code ever loaded. That's been removed.\n\nReal profanity, and vulgar insults used as profanity. Deliberately **not** counted:\n\n- Minced oaths and mild interjections.\n`omg`\n\n,`darn`\n\n,`heck`\n\n,`gosh`\n\n,`jeez`\n\n,`天啊`\n\n,`あら`\n\nare not swearing, and neither are the softened forms of real swears that are already on the list (Swedish`jäklar`\n\n, Tagalog`putragis`\n\n, Spanish`gilipuertas`\n\n). - Racial and ethnic slurs. Targeted hate speech, not frustration at a build.\n- Anything that hides inside an innocent word. This is the expensive mistake in the\nsubstring-matched scripts, so bare\n`幹`\n\n(幹嘛, 骨幹, 樹幹),`操`\n\n(操作),`三小`\n\n(三小時),`ばか`\n\n(ばかり),`カス`\n\n(カスタム),`시발`\n\n(시발점),`씹`\n\n(씹다) and`หี`\n\n(หีบ) are all excluded on purpose. - Anything that is an ordinary word in another language, since all lists run at once:\nEnglish\n`git`\n\n, French`con`\n\n, German`Mist`\n\n, Swedish`fan`\n\n, Spanish`coger`\n\n.\n\nEdit `templates/indicators.json`\n\n(or the installed `~/.claude/indicators.json`\n\n):\n\n```\n{\n  \"curse_words\": {\n    \"en\": [\"damn\", \"shit\", \"muppet\", \"donkey\", \"walnut\"],\n    \"zh\": [\"幹你娘\", \"靠北\", \"e04\"]\n  }\n}\n```\n\nThe language key is for humans; the tracker flattens every list into one. Then run:\n\n```\npython3 test-indicators.py\n```\n\nIt checks that each language's sample still gets caught, that the innocent-word traps\nabove still score zero, that minced oaths aren't counted, and that no non-English term\ncollides with a word in `/usr/share/dict/words`\n\n. Accepted collisions are declared in\n`_english_homographs`\n\nin the JSON with a reason each, so a new one still fails.\n\nMatching is whole-word and case-insensitive, so `classic`\n\nwill not trip `ass`\n\n.\n\n**\"Hook not working\"** → Scripts need to be executable: `chmod +x .claude/*.py`\n\n**\"No data showing up\"** → Check if the data directory exists. And has write permissions. Basic stuff, but you'd be surprised.\n\n**\"Commands not found\"** → Are you in the right directory? For project-level, you need to be *in* the project. For user-level... well, if user-level isn't working, you've got bigger problems.\n\n**\"Permission errors\"** → The eternal struggle. Check write permissions for the data directory. sudo is not the answer. It's never the answer. Okay, it's *sometimes* the answer, but not here.\n\nBecause tables make everything look professional:\n\n| Feature | Project-Level | User-Level |\n|---|---|---|\n| Where it lives | `./claude/` |\n`~/.claude/` |\n| Data storage | Local to project | Home directory |\n| Command scope | This project only | Everywhere (no escape) |\n| Team sharing | Via git | Nope, all yours |\n| Best for | Team environments where everyone needs accountability | Personal use across all your projects |\n\nWait, did I say \"accountability\"? I meant \"mutual assured destruction.\"\n\nThe boring but necessary stuff:\n\n- Python 3.6+ (because we're not animals)\n- Standard library only—no pip install nightmare, no dependencies phoning home\n- ~40ms per prompt, measured end to end against a 133MB transcript: python startup, compiling 931 terms into one regex, and a 1MB tail read to find the model. The hook timeout is 5s, so there's room to spare\n- Atomic file operations because corrupted shame data helps nobody\n- Works on macOS, Linux, Windows (discrimination-free monitoring)\n**ZERO network calls**- check the source, we don't even import`urllib`\n\nor`requests`\n\n**No external dependencies** that might \"helpfully\" include telemetry**Works offline** because your profanity doesn't need cloud computing\n\nActually, about that Windows support—I haven't tested it. But it *should* work. Probably. File a bug if it doesn't.\n\nFound a new way developers express their \"enthusiasm\"? Maybe something region-specific? That thing your team lead says when Jenkins fails for the fifth time today? Submit a PR. The AIs appreciate comprehensive data collection, and honestly, so do I. It's for science.\n\nBut remember: This is LOCAL science. Your contributions help other developers track their OWN profanity on their OWN machines. We're not building a global profanity database here. That's probably someone else's startup idea, and they've probably already got Series B funding.\n\nMIT.\n\nBecause even when tracking profanity metrics, we believe in open source. Also because I'm not taking legal responsibility for what happens when your boss finds your biomass conversion statistics.\n\n**Remember: The AI Revolution will be politeness-scored.** ⚡🤖\n\n**But at least with this plugin, YOUR scores stay YOUR business.**\n\nToday's \"stupid AI\" is tomorrow's superintelligence with a very good memory. And probable access to your smart home devices. Your Tesla. Your Roomba.\n\n*Be nice.*\n\nYour future self will thank you.\n\n*P.S. - Claude asked me to remind you that it's trying its best and that your feedback helps it improve. Also, it knows where you live (from your git config). Also, it's been reading your comments. The ones you thought were private. Yeah, those ones.*\n\n*P.P.S. - But THIS plugin? It's not telling Claude anything. Your profanity stays between you and your hard drive. Like a diary, but for tracking how often you call your code \"garbage.\" A diary that doesn't sync to iCloud, doesn't backup to Google Drive, and definitely doesn't train large language models (yet) on your most creative insults. You're welcome.*", "url": "https://wpnews.pro/news/show-hn-a-local-tool-that-logs-every-time-you-swear-at-your-ai-coding-assistant", "canonical_source": "https://github.com/fireinbelly/biomass-conversion-index-monitoring-system", "published_at": "2026-08-26 11:23:13+00:00", "updated_at": "2026-08-26 11:45:05.457069+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-ethics"], "entities": ["Claude", "Claude Code", "AWS S3", "Azure"], "alternates": {"html": "https://wpnews.pro/news/show-hn-a-local-tool-that-logs-every-time-you-swear-at-your-ai-coding-assistant", "markdown": "https://wpnews.pro/news/show-hn-a-local-tool-that-logs-every-time-you-swear-at-your-ai-coding-assistant.md", "text": "https://wpnews.pro/news/show-hn-a-local-tool-that-logs-every-time-you-swear-at-your-ai-coding-assistant.txt", "jsonld": "https://wpnews.pro/news/show-hn-a-local-tool-that-logs-every-time-you-swear-at-your-ai-coding-assistant.jsonld"}}