a515912537c7d83a1614137cec01988f1a00655f
Widen Message.content from string to string | MessageContentPart[] to support multimodal content. Add Attachment type to channel layer, media conversion utilities, and image extraction to all channel adapters (Telegram, Discord, Slack, WhatsApp). Update all model clients (Anthropic, OpenAI, Gemini, Bedrock) to convert structured content to provider-specific formats. Fix downstream consumers (tokens, compaction, TUI, local models) to handle the widened type via getMessageText() helper.
Flynn
Self-hosted personal AI assistant with Telegram and Terminal interfaces.
Features
- Multi-Frontend: Telegram bot + Terminal UI (minimal & fullscreen modes)
- Multi-Model: Anthropic Claude, OpenAI, Ollama with intelligent routing
- Model Switching: Switch between cloud/local models on demand
- Session Persistence: SQLite-backed conversation history
- Fallback Chains: Automatic failover when primary model fails
- Hook Engine: Confirmation system for sensitive operations
- Session Transfer: Move conversations between frontends
- CLI: Full command-line interface (
flynn start,send,doctor, etc.) - Cron Scheduling: Automated messages on cron schedules with output routing
- Health Diagnostics:
flynn doctorvalidates config, connectivity, and system state
Quick Start
# Install dependencies
pnpm install
# Copy and configure
cp config/default.yaml ~/.config/flynn/config.yaml
# Edit config with your API keys and Telegram bot token
# Build and run
pnpm build
flynn start
# Or run without building
pnpm start
CLI Commands
Flynn provides a full CLI via the flynn binary (or npx tsx src/cli/index.ts during development):
| Command | Description |
|---|---|
flynn start |
Start the Flynn daemon (Telegram, WebChat, cron) |
flynn tui |
Launch the interactive terminal UI |
flynn send <message> |
Send a one-shot message and print the response |
flynn sessions |
List active sessions |
flynn doctor |
Validate config and check system health |
flynn config |
Show resolved configuration (secrets redacted) |
Examples
# Start daemon with custom config
flynn start --config ~/my-config.yaml
# One-shot query
flynn send "What's the weather in London?"
# Check system health
flynn doctor --config ~/.config/flynn/config.yaml
# Show current config (secrets masked)
flynn config
# List sessions
flynn sessions
Configuration
Config location: ~/.config/flynn/config.yaml (or set FLYNN_CONFIG)
telegram:
bot_token: "your-telegram-bot-token"
allowed_chat_ids: [123456789] # Your Telegram user ID
models:
default:
provider: anthropic
model: claude-opus-4-5-20251101
api_key: sk-ant-api03-...
local:
provider: ollama
model: qwen2.5:14b
fallback_chain: [local]
hooks:
confirm: [shell.*, file.write]
log: [web.*, file.read]
silent: [notify]
Model Providers
| Provider | Config |
|---|---|
| Anthropic | provider: anthropic, api_key or auth_token |
| OpenAI | provider: openai, api_key, optional endpoint |
| Ollama | provider: ollama, model, optional endpoint |
Model Tiers
Configure multiple models for different purposes:
models:
fast: { provider: anthropic, model: claude-sonnet-4-... }
default: { provider: anthropic, model: claude-opus-4-5-... }
complex: { provider: anthropic, model: claude-opus-4-5-... }
local: { provider: ollama, model: qwen2.5:14b }
Telegram Commands
| Command | Description |
|---|---|
/start |
Initialize bot |
/reset |
Clear conversation history |
/status |
Show current model and status |
/local |
Switch to local model |
/cloud |
Switch to cloud model |
/model |
Show model info and options |
Terminal UI
# Minimal mode (readline)
pnpm tui
# Fullscreen mode (React/Ink)
pnpm tui:fs
TUI Commands
| Command | Description |
|---|---|
/help |
Show help |
/reset |
Clear history |
/status |
Show session info |
/fullscreen |
Switch to fullscreen mode |
/transfer telegram |
Transfer session to Telegram |
/quit |
Exit |
Running as Service
# Create systemd user service
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/flynn.service << 'EOF'
[Unit]
Description=Flynn Personal AI Assistant
After=network.target ollama.service
[Service]
Type=simple
WorkingDirectory=/path/to/flynn
ExecStart=/usr/bin/pnpm start
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
[Install]
WantedBy=default.target
EOF
# Enable and start
systemctl --user daemon-reload
systemctl --user enable --now flynn
# View logs
journalctl --user -u flynn -f
Hook Engine
Control sensitive operations with pattern matching:
hooks:
confirm: # Requires user approval via Telegram
- shell.*
- file.write
log: # Logs but doesn't block
- web.*
- file.read
silent: # Executes without notification
- notify
Cron Scheduling
Schedule automated messages on cron schedules. Each job fires an inbound message through the agent pipeline and routes the response to a configured output channel.
automation:
cron:
- name: daily-summary
schedule: "0 9 * * *" # 9 AM daily
message: "Give me a summary of today's tasks"
output:
channel: telegram # Route response to Telegram
peer: "123456789" # Chat ID to send to
timezone: Europe/London # Optional timezone
enabled: true
- name: hourly-check
schedule: "0 * * * *" # Every hour
message: "Check system status"
output:
channel: telegram
peer: "123456789"
enabled: false # Disabled, won't fire
Cron Config Fields
| Field | Required | Description |
|---|---|---|
name |
yes | Unique job identifier |
schedule |
yes | Cron expression (standard 5-field) |
message |
yes | Text sent to the agent when the job fires |
output.channel |
yes | Channel name to route the response (e.g. telegram) |
output.peer |
yes | Peer/chat ID on the output channel |
timezone |
no | IANA timezone (defaults to system timezone) |
enabled |
no | Whether the job is active (default: true) |
Doctor Diagnostics
flynn doctor runs 10 health checks to validate your setup:
$ flynn doctor
Flynn Doctor
============
[PASS] Config file exists (/home/user/.config/flynn/config.yaml)
[PASS] Config parses (valid YAML)
[PASS] Config validates (schema valid)
[PASS] Env vars resolved
[PASS] Data directory writable (/home/user/.local/share/flynn)
[PASS] Session DB accessible (sessions.db)
[PASS] Model connectivity (anthropic: claude-sonnet)
[PASS] Telegram bot configured (1 allowed chat(s))
[SKIP] MCP servers configured (none configured)
[PASS] Skills loaded (3 skill(s))
Results: 8 passed, 0 failed, 0 warnings, 1 skipped
Check Details
| Check | What it validates |
|---|---|
| Config file exists | Config YAML file is present at the expected path |
| Config parses | File is valid YAML syntax |
| Config validates | YAML content passes Zod schema validation |
| Env vars resolved | Any ${VAR} references in config have values set |
| Data directory writable | Can write to ~/.local/share/flynn/ |
| Session DB accessible | SQLite database opens and queries succeed |
| Model connectivity | Default model provider and model name are configured |
| Telegram bot configured | Bot token is present and reasonable length |
| MCP servers configured | Lists configured MCP tool servers |
| Skills loaded | Discovers and loads skill packages |
Exit code is 1 if any check fails, 0 otherwise. Checks that depend on a valid config are skipped when config is invalid.
Session Management
- Sessions persist in
~/.local/share/flynn/sessions.db - Session ID format:
{frontend}:{userId}(e.g.,telegram:123456789) - History survives restarts
- Transfer sessions between frontends with
/transfer
Architecture
src/
├── cli/ # CLI commands (commander)
├── config/ # YAML config + Zod validation
├── models/ # Model providers + router
├── backends/native/ # Agent implementation
├── session/ # SQLite persistence
├── hooks/ # Confirmation engine
├── daemon/ # Lifecycle management
├── channels/ # Channel adapter abstraction
├── automation/ # Cron scheduler
├── gateway/ # WebSocket gateway + web UI
├── mcp/ # MCP tool server integration
├── skills/ # Skill packages
├── tools/ # Builtin tools (shell, file, web)
└── frontends/
├── telegram/ # Telegram bot
└── tui/ # Terminal UI
Development
# Dev mode with watch
pnpm dev # Daemon
pnpm tui:dev # TUI
# Type check
pnpm typecheck
# Lint
pnpm lint
# Test
pnpm test
Environment Variables
| Variable | Description |
|---|---|
FLYNN_CONFIG |
Override config path |
ANTHROPIC_API_KEY |
Anthropic API key (fallback) |
OPENAI_API_KEY |
OpenAI API key (fallback) |
License
MIT
Description
Languages
TypeScript
92.3%
JavaScript
6.4%
HTML
0.4%
Swift
0.3%
Makefile
0.2%
Other
0.1%