{"id":51012259,"url":"https://github.com/m3di/ai-companion","last_synced_at":"2026-06-21T04:31:07.379Z","repository":{"id":363213530,"uuid":"1262014545","full_name":"m3di/ai-companion","owner":"m3di","description":"Drive Claude Code from Telegram — run multiple coding sessions at once and switch between them from a chat keyboard. Runs locally, uses your Claude login.","archived":false,"fork":false,"pushed_at":"2026-06-17T19:49:25.000Z","size":194,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-17T21:22:34.071Z","etag":null,"topics":["ai-agent","anthropic","claude","claude-code","grammy","llm","mcp","telegram-bot","typescript"],"latest_commit_sha":null,"homepage":null,"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/m3di.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/ROADMAP.md","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-06-07T13:10:48.000Z","updated_at":"2026-06-17T19:49:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/m3di/ai-companion","commit_stats":null,"previous_names":["m3di/ai-companion"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/m3di/ai-companion","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3di%2Fai-companion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3di%2Fai-companion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3di%2Fai-companion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3di%2Fai-companion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/m3di","download_url":"https://codeload.github.com/m3di/ai-companion/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3di%2Fai-companion/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34594326,"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-06-21T02:00:05.568Z","response_time":54,"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":["ai-agent","anthropic","claude","claude-code","grammy","llm","mcp","telegram-bot","typescript"],"created_at":"2026-06-21T04:31:03.574Z","updated_at":"2026-06-21T04:31:07.374Z","avatar_url":"https://github.com/m3di.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🤖 ai-companion\n\n\u003e A team chatbot that **runs real work** and **learns from it.** Talk to a concierge in chat; it spawns Claude Code worker sessions to do the work, and a nightly **dream → grow** loop turns everything that happened into a curated, git-tracked knowledge base. Start empty, and let it grow into the brain of your team's workflow.\n\n![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript\u0026logoColor=white)\n![Node](https://img.shields.io/badge/Node-%E2%89%A520-339933?logo=node.js\u0026logoColor=white)\n![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)\n![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)\n\n`ai-companion` runs on your own machine (or a container), long-polls a chat\nsurface, and drives [Claude Code](https://platform.claude.com/docs/en/agent-sdk/typescript)\nthrough the Claude Agent SDK. It uses your existing Claude Code login — no API\nkey required — and keeps state in a small SQLite file plus a git-tracked\nknowledge directory. No server, no separate database, no RAG — Claude Code reads\nyour files directly.\n\nIt's a **general framework**: clone it, point it at your repos, and grow your own\ncompanion. This repo ships the engine; your bot's knowledge lives only on your\nmachine.\n\n---\n\n## 🧠 The idea\n\n```\n                        you ─────────────▶  🎛️ Concierge  ─── spawns ──▶  🔧 workers\n                     (just talk)            (one front door)              (Claude Code sessions)\n                                                  │                            │\n                                                  ▼                            ▼\n                            SQLite (the firehose: sessions, messages)   work on your repos\n                                                  │\n                              nightly  ──▶  💤 dream  ──▶  dream records\n                                                                │\n                              operator ──▶  🌱 grow  ◀──────────┘\n                                                  │\n                                                  ▼\n                                   knowledge/ (git-tracked curated brain)\n                                                  │\n                                                  └──▶ read by every future turn\n```\n\n- **One front door.** You always talk to the **concierge**. It answers, manages\n  threads, and hands real work to **worker** sessions. Worker messages are tagged\n  `🔧 \u003ctitle\u003e` — reply to one to talk to that worker directly.\n- **Workers** are parallel, resumable Claude Code sessions. They run in the\n  background and report through the concierge; one you're watching streams live.\n- **The flywheel.** SQLite is the short-term firehose (what happened).\n  `knowledge/` is the long-term brain (what we learned). Two transforms connect\n  them: **dream** compacts recent activity into reflections; **grow** promotes\n  those reflections into committed, curated knowledge. Every interaction makes\n  the next answer better.\n\n---\n\n## 🚀 Quick start\n\n**Prerequisites:** Node ≥ 20 and a Claude Code login (`claude` → `/login`).\n\n```bash\ngit clone https://github.com/m3di/ai-companion.git\ncd ai-companion\nnpm install\ncp .env.example .env        # then fill it in (see below)\n```\n\n1. **Create a bot** — message [@BotFather](https://t.me/BotFather) → `/newbot` →\n   copy the token into `TELEGRAM_BOT_TOKEN`.\n2. **Pick a working directory** — set `CLAUDE_WORKING_DIR` to where Claude should\n   operate; `WORKSPACE_DIR` is the folder holding the repos it may touch.\n3. **Find your chat ID** — run `npm run dev`, message the bot; it replies with\n   your chat ID. Put it in `ALLOWED_CHAT_IDS` and restart.\n4. **Say hi** — just tell the concierge what you need.\n\n```bash\nnpm run dev        # watch mode (auto-reload)\nnpm start          # run once\nnpm run typecheck  # tsc --noEmit\n```\n\n---\n\n## 💬 Talking to it\n\nThere is exactly **one** interaction model, so nothing is ambiguous:\n\n- **Plain message → the concierge.** It decides what to do: answer, manage\n  threads, or delegate work to a worker.\n- **Reply to a `🔧` worker message → that worker.** A one-off direct line; your\n  next plain message is back with the concierge. You never \"switch into\" a thread.\n- **Background work** runs quietly and the concierge reports it when done; work\n  you ask to watch streams into the chat, tagged with its worker's title.\n\n### Commands\n\n| Command       | What it does                                                   |\n| ------------- | -------------------------------------------------------------- |\n| `/sessions`   | Status board of your worker threads.                           |\n| `/capture`    | Toggle capture mode — queue notes/forwards silently all day.   |\n| `/process`    | Triage everything captured and fan it out to threads.          |\n| `/cancel`     | Stop all running work in this chat.                            |\n| `/repos`      | List, add, or scan your workspace repos.                       |\n| `/dream`      | Run an offline self-reflection over recent activity now.       |\n| `/dreams`     | List saved reflections (`/dreams \u003cid\u003e` for the full report).   |\n| `/grow`       | Refine the knowledge base from recent reflections.             |\n| `/status`     | Concierge + worker overview.                                   |\n\n---\n\n## 🌱 The knowledge flywheel\n\n- **Knowledge base** — `KNOWLEDGE_DIR` (default `data/knowledge`) is a\n  **git-tracked** directory of markdown notes: one `\u003ckey\u003e.md` per note\n  (frontmatter + body, cross-linked as `[[other-key]]`) plus a generated\n  `index.md`. Workers and the concierge read and write it through their tools, and\n  every write auto-commits — so the brain has real, reviewable history.\n- **dream** — a read-only reflection pass (scheduled nightly at `NIGHTLY_HOUR`,\n  or on demand via `/dream`). It reviews recent activity and the bot's memory and\n  records a report to the `dreams` table. It changes nothing.\n- **grow** — operator-triggered (`/grow`). It reads the unprocessed dreams and the\n  knowledge base, then **refines the notes** (merge duplicates, fix stale facts,\n  split, re-link, tighten) and lands **one reviewable commit** — with a one-tap\n  **↩️ Revert**. Grow's working directory *is* the knowledge repo, so it can never\n  touch the bot's source.\n\nThe knowledge directory is each deployment's own — it's git-ignored from this\nrepo and persists on your machine (or a PVC), never in the framework.\n\n---\n\n## 🎛️ Telegram UI tools\n\nThe bot exposes a small MCP server so Claude can compose chat UI directly instead\nof only plain text:\n\n- **`send`** — a message in Telegram HTML with optional inline buttons.\n- **`ask`** — one quick question with tappable options; blocks for the answer.\n- **`askUserQuestion`** — up to four structured questions at once.\n\nA worker also has knowledge tools (`recallNotes` / `readNote` / `saveFinding`) so\nhard-won answers are saved once and reused, and a `setMemo` tool to keep its\nthread labeled.\n\n---\n\n## ⚙️ Configuration\n\nAll configuration is environment variables (see [`.env.example`](.env.example)):\n\n| Variable             | Required | Description                                                                 |\n| -------------------- | :------: | --------------------------------------------------------------------------- |\n| `TELEGRAM_BOT_TOKEN` |    ✅    | Bot token from @BotFather.                                                   |\n| `ALLOWED_CHAT_IDS`   |    ✅    | Comma-separated chat IDs allowed to use the bot. Empty = nobody.             |\n| `CLAUDE_WORKING_DIR` |    ✅    | Directory Claude Code operates in (its file-access root).                   |\n| `WORKSPACE_DIR`      |          | Root holding your cloned repos. Default: the parent of `CLAUDE_WORKING_DIR`. |\n| `PERMISSION_MODE`    |          | Default mode for worker tools (`default` · `acceptEdits` · `auto`).         |\n| `CLAUDE_MODEL`       |          | Model override, e.g. `claude-opus-4-8`. Empty = SDK/CLI default.            |\n| `KNOWLEDGE_DIR`      |          | Git-tracked knowledge base. Default `data/knowledge`.                       |\n| `NIGHTLY_HOUR`       |          | Hour (0–23) to run the nightly dream. Default `4`.                          |\n| `SYSTEM_PROMPT_PATH` |          | Path to the dynamic system prompt. Default `prompts/system.md`.             |\n| `DB_PATH`            |          | SQLite path. Default `data/companion.db`.                                    |\n\nThe system prompt in `prompts/system.md` is re-read every turn — edit it anytime,\nno restart.\n\n---\n\n## 🔒 Security\n\nA bot token is effectively public, and this bot runs tools on your machine. Two\nthings keep that safe:\n\n1. **Allowlist** — only chats in `ALLOWED_CHAT_IDS` are served; everyone else is\n   refused. Keep it tight.\n2. **Permission mode** — start workers on **Ask each** or **Accept edits** and\n   only move to **Auto** for workspaces you trust.\n\n`.env` and `data/` (your SQLite + knowledge base) are git-ignored. Never commit\nyour token or your instance's knowledge.\n\n---\n\n## 🗂️ Project structure\n\n```\nsrc/\n├── index.ts          entry point — boot, nightly scheduler, graceful shutdown\n├── transport/\n│   ├── types.ts      the ChatAdapter contract (transport-agnostic)\n│   └── telegram.ts   Telegram adapter: grammy runner, events, outbound API\n├── dispatch.ts       the transport-agnostic core: turns, routing, commands\n├── sessions.ts       worker views, per-turn visibility, status badges\n├── concierge.ts      the concierge agent + its bot-management tools\n├── claude.ts         Claude Agent SDK wrapper (normalizes events)\n├── permissions.ts    inline Allow/Deny/Always-allow tool gating\n├── ui.ts             Telegram UI tools (send / ask / knowledge tools)\n├── liveStatus.ts     the self-editing live status message\n├── format.ts         Markdown/HTML formatting + tool summaries\n├── db.ts             SQLite schema + queries (the firehose)\n├── knowledge.ts      the git-tracked knowledge base (files + commits)\n├── dream.ts          offline self-reflection → dreams table\n├── grow.ts           the knowledge-base librarian (dreams → committed notes)\n├── digest.ts         digest a document into knowledge notes\n├── workspace.ts      the workspace repo registry\n└── config.ts         env-var configuration\n```\n\nThe chat surface is chosen in one place (`index.ts`). The core talks only to a\n`ChatAdapter`, so a second transport (e.g. Slack) is a new adapter, not a rewrite.\n\n---\n\n## 🤝 Contributing\n\nIssues and pull requests are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).\nIn short: fork, branch, `npm run typecheck`, open a PR against `main`.\n\n## 📄 License\n\n[MIT](LICENSE) © Mehdi\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm3di%2Fai-companion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fm3di%2Fai-companion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm3di%2Fai-companion/lists"}