dcellison/kai

GitHub: dcellison/kai

基于 Claude Code 的本地 Telegram AI 助手,具备完整 shell 权限、多层安全机制和持久记忆能力。

Stars: 12 | Forks: 0

# Kai [![CI](https://img.shields.io/github/actions/workflow/status/dcellison/kai/ci.yml?branch=main&label=CI)](https://github.com/dcellison/kai/actions/workflows/ci.yml) [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue)](https://python.org) [![License](https://img.shields.io/github/license/dcellison/kai)](LICENSE) [![Version](https://img.shields.io/github/v/tag/dcellison/kai?label=version)](https://github.com/dcellison/kai/releases) 一个居住在 Telegram 中并完全运行在你自己机器上的个人 AI 助手。由 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 驱动,拥有完整的工具访问权限 —— shell、文件系统、网络搜索 —— 其安全模型正是基于它拥有所有这些权限这一事实而设计的。 有关设置、架构和可选功能的详细指南,请参阅 **[Wiki](https://github.com/dcellison/kai/wiki)**。 ## 为什么选择本地? Kai 连接了 Telegram 和一个在你硬件上持久运行的 Claude Code 进程。消息传入,流式响应返回,Claude 拥有你系统的真实访问权限。这种能力正是其核心所在 —— 也是为何其安全模型不容妥协的原因。 一切均在本地运行。对话从不经过中继服务器。语音转录与合成在设备端完成。API 密钥通过内部服务层进行代理,因此它们永远不会出现在对话上下文中。你和你的机器之间不存在云端组件。 ## 安全模型 赋予 AI agent shell 访问权限是一个真正的信任决策。Kai 采用分层防御策略 —— 每一层都是独立的,因此任何单点故障都不会导致灾难性后果: - **Telegram auth** - 只有显式列入白名单的用户 ID 才能进行交互。未经授权的消息在到达任何处理器之前会被静默丢弃。 - **TOTP gate** (可选) - 通过基于时间的一次性密码进行双因素认证。在可配置的空闲超时后,Kai 在处理任何请求之前要求输入 6 位验证码。密钥存储在一个 root 拥有的文件(模式 0600)中,bot 进程无法直接读取;它通过范围受限的 sudoers 规则来验证代码。即使有人攻破了你的 Telegram 账户,如果没有你的验证器设备,他们也无法使用你的助手。结合磁盘持久化的速率限制锁定,可防止暴力破解。 - **Process isolation** - 认证状态存在于 bot 的内存上下文中,而非文件系统或对话历史中。内部 Claude 进程无法读取、操纵或绕过认证关卡。 - **Path confinement** - 文件交换操作通过 `Path.relative_to()` 被限制在活动工作区内。路径遍历尝试会被拒绝。 - **Service proxy** - 外部 API 密钥存在于服务端配置(`services.yaml`)中,并在请求时注入。Claude 通过本地代理端点调用 API;密钥永远不会进入对话。 设置 TOTP 需要可选依赖项组和 root 权限: ``` pip install -e '.[totp]' # adds pyotp and qrcode sudo python -m kai totp setup # generate secret, display QR code, confirm ``` 有关完整架构,请参阅 [System Architecture](https://github.com/dcellison/kai/wiki/System-Architecture)。有关 TOTP 详情,请参阅 [TOTP Authentication](https://github.com/dcellison/kai/wiki/TOTP-Authentication)。 ## 特性 ### 流式响应 响应实时流式传输到 Telegram,每 2 秒更新一次消息。 ### 模型切换 通过 `/models`(交互式选择器)或 `/model `(直接指定)在 Opus、Sonnet 和 Haiku 之间切换。更改模型会重启会话。 ### 工作区 使用 `/workspace ` 将 Claude 指向任何项目。名称相对于 `WORKSPACE_BASE`(在 `.env` 中设置)进行解析。来自主工作区的身份和记忆会保留。使用 `/workspace new ` 创建新工作区。不接受绝对路径 —— 所有工作区必须位于配置的基目录下。 ### 文件交换 直接在聊天中发送任何文件类型 —— 照片、文档、PDF、压缩包等。文件会以带时间戳的名称保存到活动工作区内的 `files/` 目录中,Claude 会获得路径以便通过 shell 工具对其进行操作。Claude 也可以通过内部 API 向你回传文件。图片内联渲染;其他内容以文档附件形式到达。 ### 语音输入 语音笔记使用 [whisper.cpp](https://github.com/ggerganov/whisper.cpp) 在本地转录并转发给 Claude。需要 `ffmpeg` 和 `whisper-cpp`。默认禁用 —— 安装依赖项后设置 `VOICE_ENABLED=true`。请参阅 [Voice Setup](https://github.com/dcellison/kai/wiki/Voice-Setup) wiki 页面。 ### 语音响应 (TTS) 通过 [Piper TTS](https://github.com/rhasspy/piper) 进行文本转语音。三种模式:`/voice only`(仅语音笔记,无文本)、`/voice on`(文本 + 语音)、`/voice off`(仅文本,默认)。8 种精选英语语音。需要 `pip install -e '.[tts]'` 和 `TTS_ENABLED=true`。请参阅 [Voice Setup](https://github.com/dcellison/kai/wiki/Voice-Setup)。 ### 双模式 Telegram 传输 Kai 支持两种接收 Telegram 更新的方式:**长轮询**(默认)和 **webhooks**。轮询在 NAT 后开箱即用,无需任何基础设施。在 `.env` 中设置 `TELEGRAM_WEBHOOK_URL` 以切换到 webhook 模式以获得更低延迟 —— 这需要隧道或反向代理(请参阅 [Exposing Kai to the Internet](https://github.com/dcellison/kai/wiki/Exposing-Kai-to-the-Internet)))。 ### Webhooks 一个 HTTP 服务器接收 GitHub webhook 事件(推送、PR、issue、评论、审查)并将其转发到 Telegram。签名通过 HMAC-SHA256 验证。一个通用 webhook 端点(`POST /webhook`)接受来自任何服务的 JSON。请参阅 [Exposing Kai to the Internet](https://github.com/dcellison/kai/wiki/Exposing-Kai-to-the-Internet)。 ### 定时任务 提醒和循环 Claude 任务,支持一次性、每日和间隔计划。自然语言提问(“remind me at 3pm”)或使用 HTTP API(`POST /api/schedule`)。Claude 任务支持用于监控用例的条件自动移除(`CONDITION_MET` / `CONDITION_NOT_MET` 协议)。请参阅 [Scheduling and Conditional Jobs](https://github.com/dcellison/kai/wiki/Scheduling-and-Conditional-Jobs)。 ### 记忆 三层持久化上下文: 1. **Auto-memory** - 由 Claude Code 针对每个工作区管理。项目架构和模式。 2. **Home memory** (`workspace/.claude/MEMORY.md`) - 个人记忆,无论当前工作区如何都会注入。由 Kai 主动更新。 3. **Conversation history** (`workspace/.claude/history/`) - JSONL 日志,每天一个文件。可搜索过去的对话。 外部工作区也有自己的 `.claude/MEMORY.md` 与主记忆一起注入。请参阅 [System Architecture](https://github.com/dcellison/kai/wiki/System-Architecture)。 ### 崩溃恢复 如果在响应过程中中断,Kai 会在重启时通知你并要求你重新发送上一条消息。 ## 命令 | Command | Description | |---|---| | `/new` | 清除会话并重新开始 | | `/stop` | 中断正在进行的流式响应 | | `/models` | 交互式模型选择器 | | `/model ` | 切换模型(`opus`、`sonnet`、`haiku`) | | `/workspace` | 显示当前工作区 | | `/workspace ` | 按名称切换(在 `WORKSPACE_BASE` 下解析) | | `/workspace home` | 返回默认工作区 | | `/workspace new ` | 创建新工作区并进行 git init | | `/workspaces` | 交互式工作区选择器 | | `/voice` | 切换语音响应开/关 | | `/voice only` | 仅语音模式(无文本) | | `/voice on` | 文本 + 语音模式 | | `/voice ` | 设置语音 | | `/voices` | 交互式语音选择器 | | `/stats` | 显示会话信息、模型和成本 | | `/jobs` | 列出活动的计划任务 | | `/canceljob ` | 取消计划任务 | | `/webhooks` | 显示 webhook 服务器状态 | | `/help` | 显示可用命令 | ## 要求 - Python 3.13+ - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) 已安装并认证 - 来自 [@BotFather](https://t.me/BotFather) 的 Telegram bot token - 你的 Telegram 用户 ID(可从 [@userinfobot](https://t.me/userinfobot) 获取) ## 设置 ``` git clone git@github.com:dcellison/kai.git cd kai python3 -m venv .venv source .venv/bin/activate pip install -e '.[dev]' cp .env.example .env ``` ### 环境变量 | Variable | Required | Default | Description | |---|---|---|---| | `TELEGRAM_BOT_TOKEN` | Yes | | 来自 BotFather 的 Bot token | | `ALLOWED_USER_IDS` | Yes | | 逗号分隔的 Telegram 用户 ID | | `CLAUDE_MODEL` | No | `sonnet` | 默认模型(`opus`、`sonnet` 或 `haiku`) | | `CLAUDE_TIMEOUT_SECONDS` | No | `120` | 每条消息的超时时间 | | `CLAUDE_MAX_BUDGET_USD` | No | `10.0` | 会话预算上限 | | `WORKSPACE_BASE` | No | | 工作区名称解析的基目录 | | `ALLOWED_WORKSPACES` | No | | 逗号分隔的绝对路径,作为 `WORKSPACE_BASE` 之外可访问的工作区 | | `WEBHOOK_PORT` | No | `8080` | 用于 webhook 和调度 API 的 HTTP 服务器端口 | | `WEBHOOK_SECRET` | No | | 用于 webhook 验证和调度 API 认证的密钥 | | `TELEGRAM_WEBHOOK_URL` | No | | Telegram webhook URL(启用 webhook 模式;轮询模式请留空) | | `TELEGRAM_WEBHOOK_SECRET` | No | | 用于 Telegram webhook 认证的独立密钥(默认为 `WEBHOOK_SECRET`) | | `VOICE_ENABLED` | No | `false` | 启用语音消息转录 | | `TTS_ENABLED` | No | `false` | 启用文本转语音响应 | | `TOTP_SESSION_MINUTES` | No | `30` | 需要 TOTP 重新认证之前的分钟数 | | `TOTP_CHALLENGE_SECONDS` | No | `120` | 代码输入窗口保持打开的秒数 | | `TOTP_LOCKOUT_ATTEMPTS` | No | `3` | 临时锁定前的 TOTP 尝试失败次数 | | `TOTP_LOCKOUT_MINUTES` | No | `15` | TOTP 锁定持续时间(分钟) | | `CLAUDE_USER` | No | | 内部 Claude 进程的 OS 用户(通过 `sudo -u` 启用进程隔离) | `CLAUDE_MAX_BUDGET_USD` 通过 Claude Code 的 `--max-budget-usd` 标志限制 Claude 在单个会话中的工作量。在 Pro/Max 计划中,这纯粹是一种失控预防机制(没有按 token 收费)。会话在 `/new`、切换模型或切换工作区时重置。 ## 运行 ``` make run ``` 或手动运行:`source .venv/bin/activate && python -m kai` ### 作为服务运行 (macOS) 创建 `~/Library/LaunchAgents/com.kai.bot.plist`: ``` Label com.kai.bot ProgramArguments /path/to/kai/.venv/bin/python -m kai WorkingDirectory /path/to/kai EnvironmentVariables PATH /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin RunAtLoad KeepAlive ProcessType Background ``` 将 `/path/to/kai` 替换为你的实际项目路径。`PATH` 必须包含 `claude`、`ffmpeg` 以及 Kai 调用的任何其他工具的目录。 ``` launchctl load ~/Library/LaunchAgents/com.kai.bot.plist ``` Kai 将立即启动,并在登录或崩溃时自动重启。日志记录到 `logs/kai.log`,每日轮换(保留 14 天历史记录)。停止方法: ``` launchctl unload ~/Library/LaunchAgents/com.kai.bot.plist ``` ### 作为服务运行 (Linux) 创建 `/etc/systemd/system/kai.service`: ``` [Unit] Description=Kai Telegram Bot After=network-online.target Wants=network-online.target [Service] Type=simple User=YOUR_USERNAME WorkingDirectory=/path/to/kai ExecStart=/path/to/kai/.venv/bin/python -m kai Restart=always RestartSec=5 Environment=PATH=/usr/local/bin:/usr/bin:/bin [Install] WantedBy=multi-user.target ``` 将 `YOUR_USERNAME` 和 `/path/to/kai` 替换为你的值。将 `claude`、`ffmpeg` 等安装的任何额外目录添加到 `PATH` 中。 `network-online.target` 依赖项确保 systemd 在启动 Kai 之前等待网络连接,从而防止启动期间发生 DNS 故障。 ``` sudo systemctl enable kai sudo systemctl start kai ``` 使用 `tail -f logs/kai.log` 或 `journalctl -u kai -f` 检查日志。停止方法: ``` sudo systemctl stop kai ``` ## 项目结构 ``` kai/ ├── src/kai/ # Source package │ ├── __init__.py # Version │ ├── __main__.py # python -m kai entry point │ ├── main.py # Async startup and shutdown │ ├── bot.py # Telegram handlers, commands, message routing │ ├── claude.py # Persistent Claude Code subprocess management │ ├── config.py # Environment config loading │ ├── sessions.py # SQLite session, job, and settings storage │ ├── cron.py # Scheduled job execution (APScheduler) │ ├── webhook.py # HTTP server: GitHub/generic webhooks, scheduling API │ ├── history.py # Conversation history (read/write JSONL logs) │ ├── locks.py # Per-chat async locks and stop events │ ├── install.py # Protected installation tooling │ ├── totp.py # TOTP verification, rate limiting, and CLI │ ├── transcribe.py # Voice message transcription (ffmpeg + whisper-cpp) │ └── tts.py # Text-to-speech synthesis (Piper TTS + ffmpeg) ├── tests/ # Test suite ├── workspace/ # Claude Code working directory │ ├── .claude/ # Identity, memory, and chat history │ └── files/ # File exchange directory (created at runtime) ├── kai.db # SQLite database (gitignored, created at runtime) ├── logs/ # Daily-rotated log files (gitignored) ├── models/ # Whisper and Piper model files (gitignored) ├── services.yaml # External service configs (gitignored) ├── pyproject.toml # Package metadata and dependencies ├── Makefile # Common dev commands ├── .env # Environment variables (gitignored, copy from .env.example) └── LICENSE # Apache 2.0 ``` ## 开发 ``` make setup # Install in editable mode with dev tools make lint # Run ruff linter make format # Auto-format with ruff make check # Lint + format check (CI-friendly) make test # Run test suite make run # Start the bot ``` ## 生产部署 对于将源代码、数据和密钥分离到受保护目录的强化安装: ``` python -m kai install config # Interactive Q&A, writes install.conf (no sudo) sudo python -m kai install apply # Creates /opt layout, migrates data (root) python -m kai install status # Shows current installation state (no sudo) ``` 这将创建一个分离的布局: - `/opt/kai/` - 只读源代码和 venv(root 拥有) - `/var/lib/kai/` - 可写运行时数据:数据库、日志、文件(服务用户拥有) - `/etc/kai/` - 密钥:env 文件、服务配置、TOTP(root 拥有,模式 0600) 安装模块处理目录创建、源代码复制、venv 设置、密钥部署、sudoers 规则、数据迁移、服务定义生成和服务生命周期(停止/启动)。使用 `--dry-run` 预览更改而不应用它们。 服务用户通过范围受限的 sudoers 规则读取密钥(仅对特定文件使用 `sudo cat`)。内部 Claude 进程无法读取密钥或修改源代码。 ## 许可证 Apache License 2.0。详情请参阅 [LICENSE](LICENSE)。
标签:AI 助手, Anthropic, API 代理, CIS基准, Claude Code, HTTP工具, IP 地址批量处理, LLM 应用, meg, Python, Shell 访问, Telegram 机器人, TOTP 认证, 个人助理, 人工智能, 信息安全, 定时任务, 开源, 持久化内存, 文字转语音, 无后门, 本地部署, 用户模式Hook绕过, 白名单, 纵深防御, 网络安全, 网络调试, 自动化, 语音转文字, 隐私保护