{"id":48805682,"url":"https://github.com/thedeutschmark/forgetmenot","last_synced_at":"2026-05-23T09:02:10.609Z","repository":{"id":339090211,"uuid":"1160429586","full_name":"thedeutschmark/forgetmenot","owner":"thedeutschmark","description":"AI personality with persistent memory for Twitch streams. Remembers your chatters, stream lore, \u0026 inside jokes - from stream to stream.","archived":false,"fork":false,"pushed_at":"2026-04-14T05:11:53.000Z","size":557,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-14T05:31:11.688Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thedeutschmark.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-17T23:33:35.000Z","updated_at":"2026-04-13T05:13:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"1167065c-562b-4102-848a-d7d6795201e6","html_url":"https://github.com/thedeutschmark/forgetmenot","commit_stats":null,"previous_names":["thedeutschmark/persistence_bot","thedeutschmark/forgetmenot"],"tags_count":41,"template":false,"template_full_name":null,"purl":"pkg:github/thedeutschmark/forgetmenot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedeutschmark%2Fforgetmenot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedeutschmark%2Fforgetmenot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedeutschmark%2Fforgetmenot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedeutschmark%2Fforgetmenot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thedeutschmark","download_url":"https://codeload.github.com/thedeutschmark/forgetmenot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedeutschmark%2Fforgetmenot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31980783,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T17:30:12.329Z","status":"ssl_error","status_checked_at":"2026-04-18T17:29:59.069Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-14T05:02:44.278Z","updated_at":"2026-05-23T09:02:10.604Z","avatar_url":"https://github.com/thedeutschmark.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\".github/icon.png\" alt=\"ForgetMeNot\" width=\"120\"\u003e\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eForgetMeNot\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\u003cstrong\u003eA Twitch chat bot that actually remembers your regulars — names, inside jokes, the callback from three weeks ago. Runs locally on your machine with your own AI key.\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/TypeScript-Node.js-3178C6?logo=typescript\u0026logoColor=white\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/SQLite-local%20memory-003B57?logo=sqlite\u0026logoColor=white\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/LLM-Gemini%20%2F%20OpenAI-6a8fe6\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-MIT-green\"\u003e\n\u003c/p\u003e\n\n---\n\n## What it does\n\n- **Remembers chatters across streams** — names, running jokes, callbacks, channel lore. Context lives in a local SQLite database on your machine, not on anyone else's server.\n- **Configurable persona** — bot name, tone, and reply policy set from the toolset dashboard. Safe mode enforces stricter filters; shows terminal or runs silently in the background.\n- **Reply modes** — mentions-only (default), shadow (generates replies without posting, for review), or live (replies to the chat stream directly). Switchable without a restart.\n- **Moderation actions** — timeout proposals with configurable allow-lists and a shadow mode so no action fires without explicit policy opt-in.\n- **Eval suite** — fixture-based regression runner catches behavior drift before each release.\n\n## How it works\n\n1. The engine connects to Twitch chat via [tmi.js](https://github.com/tmijs/tmi.js).\n2. Incoming messages are evaluated against reply policy and cooldown rules.\n3. Relevant context (chatter notes, episode recaps, channel lore) is read from a local SQLite database.\n4. A reply is generated by calling Gemini or OpenAI directly from your machine using your own API key.\n5. Post-generation filters apply (safe mode, budget, tone) before anything is posted.\n6. Memory is compacted periodically — the current session is summarised on shutdown so recall survives across streams.\n\nNothing passes through a shared backend. LLM calls travel from your machine directly to the AI provider you chose.\n\n## Getting started\n\nThe full distributable (Windows executable + system tray app) ships from [Releases](https://github.com/thedeutschmark/forgetmenot/releases). Configuration, personality templates, and the review dashboard live at [toolkit.deutschmark.online](https://toolkit.deutschmark.online/tools/chat-bot) — the toolset drives the initial pairing and wizard flow.\n\n**To run from source** (Node.js 22+ required):\n\n```bash\nnpm install\nnpm run dev        # tsx watch — live reload\n```\n\n```bash\nnpm run build:exe  # packages the engine into a standalone executable\n```\n\nThe runtime expects credentials supplied by the toolset pairing flow (stored locally). An LLM API key (Gemini or OpenAI) must be set — either through the toolset wizard or via the `BOT_LLM_API_KEY` environment variable. Without an API key the reply engine starts in disabled mode.\n\n**Eval suite** (regression checks before release):\n\n```bash\nnpm run eval           # run fixtures against current engine\nnpm run eval:gate      # pass/fail against baseline scores\nnpm run eval:baseline  # write a new baseline from current results\n```\n\n## Project structure\n\n| Path | What it is |\n| --- | --- |\n| `src/` | Engine source — Twitch chat ingest, SQLite memory, LLM calls, action evaluation, post-gen filters |\n| `src/gateway/` | Twitch connection (tmi.js wrapper) |\n| `src/memory/` | SQLite read/write, session compaction, chatter notes, episode recaps |\n| `src/reply/` | LLM provider adapter, reply engine, budget, post-processing |\n| `src/actions/` | Moderation action proposals and executor |\n| `src/runtime/` | Config loading, credential management, config refresh loop |\n| `src/api/` | Local health API, pairing endpoints, setup wizard endpoints |\n| `eval/` | Fixtures and rubric runner used to catch behaviour regressions before release |\n| `scripts/` | Build helpers — packages the engine into a single-file executable |\n\n## Privacy\n\nLocal-first: all chat memory lives in a SQLite file on the broadcaster's machine. LLM calls go from your machine directly to Gemini or OpenAI — no shared server ever holds your chat data. Credentials are not stored in plaintext on disk.\n\n---\n\n## License\n\n[MIT](LICENSE)\n\n---\n\n## deutschmark's other apps\n\n\u003ctable\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\".github/apps/alert-alert.svg\" width=\"34\"\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003e\u003ca href=\"https://github.com/thedeutschmark/alert-alert\"\u003eAlert! Alert!\u003c/a\u003e\u003c/b\u003e\u003cbr\u003eStream-alert clips from any video source.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\".github/apps/clipline.svg\" width=\"34\"\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003e\u003ca href=\"https://github.com/thedeutschmark/clipline\"\u003eClipline\u003c/a\u003e\u003c/b\u003e\u003cbr\u003eLivestream VODs → shortform clips with auto-captions.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\".github/apps/toolset.svg\" width=\"34\"\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003e\u003ca href=\"https://toolset.deutschmark.online\"\u003eThe Stream Toolset\u003c/a\u003e\u003c/b\u003e\u003cbr\u003eOBS overlays + companion apps. One login, no subscriptions.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\".github/apps/collab.svg\" width=\"34\"\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003e\u003ca href=\"https://collab.deutschmark.online\"\u003eCollab Planner\u003c/a\u003e\u003c/b\u003e\u003cbr\u003eFinds collab windows from streamers' broadcast history.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cimg src=\".github/apps/pathos.svg\" width=\"34\"\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003e\u003ca href=\"https://yourpathos.app\"\u003eP.A.T.H.O.S.\u003c/a\u003e\u003c/b\u003e\u003cbr\u003eAI career platform — resume tailoring + ATS scoring.\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003csub\u003eAll projects → \u003ca href=\"https://github.com/thedeutschmark\"\u003egithub.com/thedeutschmark\u003c/a\u003e\u003c/sub\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthedeutschmark%2Fforgetmenot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthedeutschmark%2Fforgetmenot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthedeutschmark%2Fforgetmenot/lists"}