https://github.com/m3di/ai-companion
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.
https://github.com/m3di/ai-companion
ai-agent anthropic claude claude-code grammy llm mcp telegram-bot typescript
Last synced: 4 days ago
JSON representation
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.
- Host: GitHub
- URL: https://github.com/m3di/ai-companion
- Owner: m3di
- License: mit
- Created: 2026-06-07T13:10:48.000Z (18 days ago)
- Default Branch: main
- Last Pushed: 2026-06-17T19:49:25.000Z (8 days ago)
- Last Synced: 2026-06-17T21:22:34.071Z (8 days ago)
- Topics: ai-agent, anthropic, claude, claude-code, grammy, llm, mcp, telegram-bot, typescript
- Language: TypeScript
- Size: 189 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Roadmap: docs/ROADMAP.md
Awesome Lists containing this project
README
# ๐ค ai-companion
> 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.




`ai-companion` runs on your own machine (or a container), long-polls a chat
surface, and drives [Claude Code](https://platform.claude.com/docs/en/agent-sdk/typescript)
through the Claude Agent SDK. It uses your existing Claude Code login โ no API
key required โ and keeps state in a small SQLite file plus a git-tracked
knowledge directory. No server, no separate database, no RAG โ Claude Code reads
your files directly.
It's a **general framework**: clone it, point it at your repos, and grow your own
companion. This repo ships the engine; your bot's knowledge lives only on your
machine.
---
## ๐ง The idea
```
you โโโโโโโโโโโโโโถ ๐๏ธ Concierge โโโ spawns โโโถ ๐ง workers
(just talk) (one front door) (Claude Code sessions)
โ โ
โผ โผ
SQLite (the firehose: sessions, messages) work on your repos
โ
nightly โโโถ ๐ค dream โโโถ dream records
โ
operator โโโถ ๐ฑ grow โโโโโโโโโโโโ
โ
โผ
knowledge/ (git-tracked curated brain)
โ
โโโโถ read by every future turn
```
- **One front door.** You always talk to the **concierge**. It answers, manages
threads, and hands real work to **worker** sessions. Worker messages are tagged
`๐ง ` โ reply to one to talk to that worker directly.
- **Workers** are parallel, resumable Claude Code sessions. They run in the
background and report through the concierge; one you're watching streams live.
- **The flywheel.** SQLite is the short-term firehose (what happened).
`knowledge/` is the long-term brain (what we learned). Two transforms connect
them: **dream** compacts recent activity into reflections; **grow** promotes
those reflections into committed, curated knowledge. Every interaction makes
the next answer better.
---
## ๐ Quick start
**Prerequisites:** Node โฅ 20 and a Claude Code login (`claude` โ `/login`).
```bash
git clone https://github.com/m3di/ai-companion.git
cd ai-companion
npm install
cp .env.example .env # then fill it in (see below)
```
1. **Create a bot** โ message [@BotFather](https://t.me/BotFather) โ `/newbot` โ
copy the token into `TELEGRAM_BOT_TOKEN`.
2. **Pick a working directory** โ set `CLAUDE_WORKING_DIR` to where Claude should
operate; `WORKSPACE_DIR` is the folder holding the repos it may touch.
3. **Find your chat ID** โ run `npm run dev`, message the bot; it replies with
your chat ID. Put it in `ALLOWED_CHAT_IDS` and restart.
4. **Say hi** โ just tell the concierge what you need.
```bash
npm run dev # watch mode (auto-reload)
npm start # run once
npm run typecheck # tsc --noEmit
```
---
## ๐ฌ Talking to it
There is exactly **one** interaction model, so nothing is ambiguous:
- **Plain message โ the concierge.** It decides what to do: answer, manage
threads, or delegate work to a worker.
- **Reply to a `๐ง` worker message โ that worker.** A one-off direct line; your
next plain message is back with the concierge. You never "switch into" a thread.
- **Background work** runs quietly and the concierge reports it when done; work
you ask to watch streams into the chat, tagged with its worker's title.
### Commands
| Command | What it does |
| ------------- | -------------------------------------------------------------- |
| `/sessions` | Status board of your worker threads. |
| `/capture` | Toggle capture mode โ queue notes/forwards silently all day. |
| `/process` | Triage everything captured and fan it out to threads. |
| `/cancel` | Stop all running work in this chat. |
| `/repos` | List, add, or scan your workspace repos. |
| `/dream` | Run an offline self-reflection over recent activity now. |
| `/dreams` | List saved reflections (`/dreams ` for the full report). |
| `/grow` | Refine the knowledge base from recent reflections. |
| `/status` | Concierge + worker overview. |
---
## ๐ฑ The knowledge flywheel
- **Knowledge base** โ `KNOWLEDGE_DIR` (default `data/knowledge`) is a
**git-tracked** directory of markdown notes: one `.md` per note
(frontmatter + body, cross-linked as `[[other-key]]`) plus a generated
`index.md`. Workers and the concierge read and write it through their tools, and
every write auto-commits โ so the brain has real, reviewable history.
- **dream** โ a read-only reflection pass (scheduled nightly at `NIGHTLY_HOUR`,
or on demand via `/dream`). It reviews recent activity and the bot's memory and
records a report to the `dreams` table. It changes nothing.
- **grow** โ operator-triggered (`/grow`). It reads the unprocessed dreams and the
knowledge base, then **refines the notes** (merge duplicates, fix stale facts,
split, re-link, tighten) and lands **one reviewable commit** โ with a one-tap
**โฉ๏ธ Revert**. Grow's working directory *is* the knowledge repo, so it can never
touch the bot's source.
The knowledge directory is each deployment's own โ it's git-ignored from this
repo and persists on your machine (or a PVC), never in the framework.
---
## ๐๏ธ Telegram UI tools
The bot exposes a small MCP server so Claude can compose chat UI directly instead
of only plain text:
- **`send`** โ a message in Telegram HTML with optional inline buttons.
- **`ask`** โ one quick question with tappable options; blocks for the answer.
- **`askUserQuestion`** โ up to four structured questions at once.
A worker also has knowledge tools (`recallNotes` / `readNote` / `saveFinding`) so
hard-won answers are saved once and reused, and a `setMemo` tool to keep its
thread labeled.
---
## โ๏ธ Configuration
All configuration is environment variables (see [`.env.example`](.env.example)):
| Variable | Required | Description |
| -------------------- | :------: | --------------------------------------------------------------------------- |
| `TELEGRAM_BOT_TOKEN` | โ
| Bot token from @BotFather. |
| `ALLOWED_CHAT_IDS` | โ
| Comma-separated chat IDs allowed to use the bot. Empty = nobody. |
| `CLAUDE_WORKING_DIR` | โ
| Directory Claude Code operates in (its file-access root). |
| `WORKSPACE_DIR` | | Root holding your cloned repos. Default: the parent of `CLAUDE_WORKING_DIR`. |
| `PERMISSION_MODE` | | Default mode for worker tools (`default` ยท `acceptEdits` ยท `auto`). |
| `CLAUDE_MODEL` | | Model override, e.g. `claude-opus-4-8`. Empty = SDK/CLI default. |
| `KNOWLEDGE_DIR` | | Git-tracked knowledge base. Default `data/knowledge`. |
| `NIGHTLY_HOUR` | | Hour (0โ23) to run the nightly dream. Default `4`. |
| `SYSTEM_PROMPT_PATH` | | Path to the dynamic system prompt. Default `prompts/system.md`. |
| `DB_PATH` | | SQLite path. Default `data/companion.db`. |
The system prompt in `prompts/system.md` is re-read every turn โ edit it anytime,
no restart.
---
## ๐ Security
A bot token is effectively public, and this bot runs tools on your machine. Two
things keep that safe:
1. **Allowlist** โ only chats in `ALLOWED_CHAT_IDS` are served; everyone else is
refused. Keep it tight.
2. **Permission mode** โ start workers on **Ask each** or **Accept edits** and
only move to **Auto** for workspaces you trust.
`.env` and `data/` (your SQLite + knowledge base) are git-ignored. Never commit
your token or your instance's knowledge.
---
## ๐๏ธ Project structure
```
src/
โโโ index.ts entry point โ boot, nightly scheduler, graceful shutdown
โโโ transport/
โ โโโ types.ts the ChatAdapter contract (transport-agnostic)
โ โโโ telegram.ts Telegram adapter: grammy runner, events, outbound API
โโโ dispatch.ts the transport-agnostic core: turns, routing, commands
โโโ sessions.ts worker views, per-turn visibility, status badges
โโโ concierge.ts the concierge agent + its bot-management tools
โโโ claude.ts Claude Agent SDK wrapper (normalizes events)
โโโ permissions.ts inline Allow/Deny/Always-allow tool gating
โโโ ui.ts Telegram UI tools (send / ask / knowledge tools)
โโโ liveStatus.ts the self-editing live status message
โโโ format.ts Markdown/HTML formatting + tool summaries
โโโ db.ts SQLite schema + queries (the firehose)
โโโ knowledge.ts the git-tracked knowledge base (files + commits)
โโโ dream.ts offline self-reflection โ dreams table
โโโ grow.ts the knowledge-base librarian (dreams โ committed notes)
โโโ digest.ts digest a document into knowledge notes
โโโ workspace.ts the workspace repo registry
โโโ config.ts env-var configuration
```
The chat surface is chosen in one place (`index.ts`). The core talks only to a
`ChatAdapter`, so a second transport (e.g. Slack) is a new adapter, not a rewrite.
---
## ๐ค Contributing
Issues and pull requests are welcome โ see [CONTRIBUTING.md](CONTRIBUTING.md).
In short: fork, branch, `npm run typecheck`, open a PR against `main`.
## ๐ License
[MIT](LICENSE) ยฉ Mehdi