{"id":50373740,"url":"https://github.com/bottd/glossa","last_synced_at":"2026-05-30T08:30:36.203Z","repository":{"id":359700201,"uuid":"1247173221","full_name":"bottd/glossa","owner":"bottd","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-23T02:06:30.000Z","size":42,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T03:26:48.447Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bottd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-05-23T01:39:47.000Z","updated_at":"2026-05-23T02:06:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bottd/glossa","commit_stats":null,"previous_names":["bottd/glossa"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/bottd/glossa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bottd%2Fglossa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bottd%2Fglossa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bottd%2Fglossa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bottd%2Fglossa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bottd","download_url":"https://codeload.github.com/bottd/glossa/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bottd%2Fglossa/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33686018,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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-05-30T08:30:35.600Z","updated_at":"2026-05-30T08:30:36.198Z","avatar_url":"https://github.com/bottd.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Glossa\n\nA community lexicon bot for Discord. Glossa is part dictionary, part shared\nknowledge graph: look up a word and you'll see **the standard dictionary\ndefinition next to your server's own**, plus any messages saved against it.\n\nBuilt with [discord.js](https://discord.js.org) v14 + TypeScript, backed by\nSQLite (`better-sqlite3`).\n\n## What it does\n\n- **`/glossa def \u003cterm\u003e`** — a card combining:\n  - 📖 **Dictionary** — the standard definition (via [dictionaryapi.dev](https://dictionaryapi.dev))\n  - 💬 **Notes** — community notes your members have added\n  - 🔖 **References** — messages saved under this term, linking back to the originals\n  - any images filed against the term\n  - Autocompletes against known terms.\n- **`/glossa find \u003cquery\u003e`** — a **Claude-powered reverse dictionary**. Describe a meaning, concept, or feeling and get the word(s) that fit. Look any up with `/glossa def`.\n- **`/glossa ref \u003cterm\u003e`** — list the messages saved under a term. Autocompletes against known terms.\n- **`/glossa help`** — an in-Discord overview, replied to you privately.\n- **DM the bot** `term :: note` to add a community note.\n- **Reply to a message and @-mention the bot** with a term (e.g. `@Glossa \u003cterm\u003e`) to file that message as a reference. The whole phrase after the mention is one term.\n\nReferences store a **link to the original message**, not a copy of its text; the bot renders a jump link, attributed to the author. Image attachments are recorded by their **Discord attachment URL** (not re-hosted) and shown in the lookup card.\n\n\u003e **Known compromise:** Discord's attachment URLs are signed and expire (~24h), so saved images stop rendering after a while. Accepted for now; re-hosting locally to make them durable was intentionally dropped in favour of a simpler implementation.\n\n## Stack\n\n- **discord.js v14** — slash commands with subcommands, autocomplete, message events\n- **@anthropic-ai/sdk** — Claude (Haiku) powering `/glossa find`, the reverse dictionary (`ANTHROPIC_API_KEY` required at startup)\n- **better-sqlite3** — local persistent storage (`data/glossa.db`)\n- **TypeScript** (ESM, strict, `bundler` module resolution — extensionless imports)\n- **tsx** — runs the TypeScript directly (dev, deploy, and production `start`); no build step\n- **Nix flake + direnv** — reproducible toolchain (Node 22, pnpm, treefmt)\n- **pnpm** — package manager\n- **treefmt + Prettier + ESLint** — formatting and linting\n\n## Project layout\n\n```\nsrc/\n  index.ts              # bootstrap: client, intents, event wiring, shutdown\n  config.ts             # env config\n  deploy-commands.ts    # registers /glossa with Discord\n  logger.ts\n  commands/             # /glossa + subcommands (def, find, ref, help); Command/Subcommand types\n  events/               # ready, interactionCreate (router), messageCreate (DM add + reply-mention refs); Event type\n  services/             # dictionary API, Claude reverse-dictionary search\n  store/                # SqliteStore + its data-shape types\n  lib/                  # term normalization, the /glossa def lookup card, shared COLOR\ndata/                   # SQLite db (gitignored)\n```\n\n## Setup\n\nThe repo ships a Nix flake + direnv for a reproducible toolchain. With\n[direnv](https://direnv.net) installed, `direnv allow` drops you into a shell\nwith Node, pnpm, and treefmt; otherwise run `nix develop` manually. (No Nix?\nAny Node 18+ with pnpm works too.)\n\n1. Create an application at the\n   [Discord Developer Portal](https://discord.com/developers/applications), add a **Bot**, and copy its token.\n2. Install dependencies:\n   ```bash\n   pnpm install\n   ```\n3. Copy `.env.example` to `.env` and fill in `DISCORD_TOKEN`, `CLIENT_ID`, and\n   optionally `GUILD_ID` (a server ID for instant command updates in dev).\n4. Invite the bot with the `bot` and `applications.commands` scopes (OAuth2 \u003e URL Generator).\n5. Register commands, then run:\n   ```bash\n   pnpm deploy\n   pnpm dev\n   ```\n\n\u003e **Intents:** Glossa requests `Guilds`, `GuildMessages`, and `DirectMessages` —\n\u003e **no privileged intents**. Discord delivers message content in DMs and for\n\u003e messages that **@mention the bot**, so DM-based adding and the reply-and-mention\n\u003e reference flow both work without the privileged MessageContent intent.\n\n## Scripts\n\n| Script        | Description                                   |\n| ------------- | --------------------------------------------- |\n| `pnpm dev`    | Run in watch mode with tsx                    |\n| `pnpm start`  | Run the bot with tsx                          |\n| `pnpm deploy` | Register slash commands with Discord          |\n| `pnpm check`  | Type-check without emitting                   |\n| `pnpm lint`   | Lint with ESLint (autofixes)                  |\n| `pnpm format` | Format the tree with treefmt (Prettier + nix) |\n\n## Roadmap ideas\n\n- Clickable suggestions in `/glossa find` (button-row that runs `/glossa def` on tap)\n- Upvoting community notes\n- Editing or removing your own definitions and references\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbottd%2Fglossa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbottd%2Fglossa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbottd%2Fglossa/lists"}