Your personal AI assistant with Telegram interface, multi-model support, ClawHub skills, and SOUL.md personality.
Inspired by OpenClaw and built with the same philosophy - a self-hosted AI agent that you control.
- Node.js 22+ (required)
- Telegram account (for bot interface)
- API Key for one of:
- Anthropic Claude (recommended)
- Kimi (Moonshot)
- MiniMax
# Clone the repository
git clone https://github.com/Softorize/mikiclaw
cd mikiclaw
# Install dependencies
npm install
# Build the project
npm run buildnpm run setupThe setup wizard will guide you through:
- AI Provider Selection - Choose your preferred AI model
- Telegram Bot Token - Get from @BotFather
- API Key - Enter your chosen provider's API key
- Personality - Select your assistant's personality
- Security Settings - Configure tool policies (allowlist recommended)
- Encryption - Enable credential encryption (highly recommended)
- Rate Limiting - Protect against abuse
npm startMessage your Telegram bot to get started!
- Features
- Quick Start
- Documentation
- Configuration
- Security
- Commands
- Personality (SOUL.md)
- Skills System
- Deployment Options
- Troubleshooting
- Development
- Contributing
- Architecture Guide - components, request lifecycle, and extension points
- Automation Workflows - webhook/heartbeat triggers, conditions, actions, and signed request examples
- Operations & Observability - health, metrics, logging, approvals, and runbooks
- Deployment Guide
- Troubleshooting Guide
- Memory & Learning
| Feature | Description |
|---|---|
| π€ Multi-Channel | Telegram, Discord, Slack, WebChat |
| π§ Multi-Model AI | Anthropic, OpenAI, Kimi, MiniMax, and local providers |
| π Router + Failover | Strategy-based routing with automatic provider fallback |
| πΈοΈ Gateway | WebSocket control plane for all channels |
| π¦ ClawHub Skills | Extend capabilities with community skills |
| π« SOUL.md Personality | Define your assistant's personality |
| β€οΈ Heartbeat | Scheduled tasks and check-ins |
| βοΈ Workflows | Trigger -> condition -> action automation engine |
| β Approval Gate | Risky actions require explicit in-chat approval |
| π Observability | Runtime metrics, provider/tool stats, and health endpoints |
| π Self-Hosted | Your data stays on your machine |
| π Web Interface | Built-in web chat UI |
| π€ Browser Automation | Headless browser control |
| π¬ Session Management | Multi-session support with history |
| Provider | Models | Status |
|---|---|---|
| Anthropic | claude-sonnet-4, claude-3.5-sonnet, claude-3-opus | β Recommended |
| OpenAI | gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-4, gpt-3.5-turbo | β Supported |
| Kimi | kimi-k2.5, kimi-k2-thinking | β Supported |
| MiniMax | M2.5, M2.5-highspeed, M2.1 | β Supported |
| Local | OpenAI-compatible local endpoint | β Supported |
| Tool | Description | Security |
|---|---|---|
bash |
Execute shell commands | β Allowlist/Blocklist |
applescript |
Control macOS via AppleScript | β
Permission-gated (/grant_access) |
read_file |
Read files from filesystem | β Path validation |
write_file |
Write files to filesystem | β Path validation |
list_directory |
List directory contents | β Scoped to workspace |
glob |
Find files by pattern | β Pattern validation |
grep |
Search in files | β Pattern validation |
search |
Web search (DuckDuckGo) | β SSRF protection |
git |
Git version control | β Command validation |
get_system_info |
System information | β Safe |
browser_* |
Browser automation | β Session-scoped |
gac_* |
Google Analytics account/property listing | β Requires local access grant |
Control a headless browser to interact with websites:
browser_navigate- Open a webpagebrowser_screenshot- Capture current pagebrowser_click- Click elementsbrowser_type- Type in input fieldsbrowser_content- Get page textbrowser_evaluate- Run JavaScriptbrowser_fill- Fill form fieldsbrowser_select- Select dropdown optionsbrowser_scroll- Scroll pagebrowser_back/forward- Navigationbrowser_snapshot- Structured page snapshot
Use these commands in Telegram (default channel adapter):
| Command | Description |
|---|---|
/status |
Show session and system status |
/help |
Show available commands |
/health |
Show health server summary |
/session |
Show current session details |
/metrics |
Show runtime metrics snapshot |
/joke |
Send a random joke |
/fact |
Send a random fun fact |
/grant_access |
Grant AppleScript machine control |
/revoke_access |
Revoke AppleScript machine control |
/access_status |
Show machine-control permission |
/approvals |
List pending risky tool actions |
/approve [id] |
Approve latest/specific risky action |
/deny [id] |
Deny latest/specific risky action |
| File | Location | Purpose |
|---|---|---|
config.json |
~/.mikiclaw/config.json |
Main configuration |
SOUL.md |
~/.mikiclaw/workspace/SOUL.md |
Personality definition |
MEMORY.md |
~/.mikiclaw/workspace/Memory.md |
Long-term memory |
HEARTBEAT.md |
~/.mikiclaw/workspace/HEARTBEAT.md |
Scheduled tasks |
rate_limits.json |
~/.mikiclaw/rate_limits.json |
Rate limit data |
.mikiclaw_key |
~/.mikiclaw_key |
Encryption master key |
{
"telegram": {
"botToken": "encrypted:...", // Your Telegram bot token
"allowedUsers": [] // Limit to specific users (optional)
},
"discord": {
"botToken": "...", // Discord bot token
"allowedGuilds": [], // Limit to specific guilds (optional)
"allowedChannels": [] // Limit to specific channels (optional)
},
"slack": {
"appToken": "...", // Slack app-level token
"botToken": "...", // Slack bot token
"signingSecret": "...", // Slack signing secret
"allowedChannels": [] // Limit to specific channels (optional)
},
"webchat": {
"enabled": true, // Enable web interface
"port": 18791, // WebChat port
"bindAddress": "127.0.0.1" // Bind address
},
"ai": {
"provider": "anthropic", // anthropic | openai | kimi | minimax | local
"model": "claude-sonnet-4-20250514",
"routing": {
"enabled": true, // Enable provider routing + failover
"strategy": "balanced", // quality-first | speed-first | cost-first | balanced
"fallbackProviders": ["openai", "kimi", "minimax", "local"]
},
"providers": {
"anthropic": { "apiKey": "encrypted:..." },
"openai": { "apiKey": "encrypted:..." },
"kimi": { "apiKey": "encrypted:..." },
"minimax": { "apiKey": "encrypted:...", "groupId": "..." },
"local": {
"baseUrl": "http://localhost:8000/v1",
"apiKey": "not-needed"
}
}
},
"webhooks": {
"enabled": false,
"port": 19091,
"secret": "replace-me",
"maxPayloadBytes": 1048576,
"rateLimitPerMinute": 60,
"endpoints": [
{
"path": "/incoming/build-fail",
"url": "https://example.com/webhooks/build-fail",
"method": "POST",
"events": ["*"],
"secret": "replace-me"
}
]
},
"automation": {
"enabled": false,
"workflows": [
{
"id": "build-failure-alert",
"enabled": true,
"trigger": { "type": "webhook", "path": "/incoming/build-fail" },
"condition": { "field": "data.status", "equals": "failed" },
"action": {
"type": "emit_webhook_event",
"eventType": "alerts.build.failed",
"message": "Build failed for {{data.project}} on {{data.branch}}"
}
}
]
},
"heartbeat": {
"enabled": true, // Enable periodic check-ins
"intervalMinutes": 30
},
"memory": {
"perUserEntryCap": 500, // Max entries per user in long-term memory
"maxConnectedContextEntries": 8,
"semanticMinSimilarity": 0.75
},
"channels": {
"default": "telegram",
"enabled": ["telegram"]
},
"security": {
"encryptCredentials": true, // Encrypt API keys
"toolPolicy": "allowlist-only", // allowlist-only | block-destructive | allow-all
"allowedCommands": ["git status", "ls", "cat", "echo"],
"blockedCommands": ["rm -rf /", "dd if=", "mkfs"]
},
"rateLimit": {
"enabled": true, // Enable rate limiting
"maxRequestsPerMinute": 20
}
}# Copy .env.example to .env
cp .env.example .env| Variable | Description | Default |
|---|---|---|
TELEGRAM_BOT_TOKEN |
Telegram bot token | - |
ANTHROPIC_API_KEY |
Anthropic API key | - |
ANTHROPIC_MODEL |
Model to use | claude-sonnet-4-20250514 |
HEARTBEAT_ENABLED |
Enable heartbeat | true |
HEARTBEAT_INTERVAL_MINUTES |
Heartbeat interval | 30 |
| Feature | Description |
|---|---|
| Credential Encryption | API keys encrypted with AES-256-GCM |
| Tool Policy Engine | Allowlist-only by default |
| Path Traversal Protection | All file paths validated and scoped |
| Command Injection Prevention | Input validation on all commands |
| Rate Limiting | Persistent rate limiting per user |
| Risky Action Approval | bash/write_file/applescript/risky browser actions need explicit approval |
| Health Endpoint Auth | Token-based authentication required |
| Obfuscation Detection | Detects base64, eval, reverse shells |
- Always use allowlist-only policy for production
- Enable credential encryption (default)
- Restrict allowed users in config if possible
- Keep the master key file secure:
~/.mikiclaw_key - Review allowed commands regularly
- Monitor logs in
~/.mikiclaw/logs/
{
"security": {
// MOST SECURE: Only explicitly allowed commands
"toolPolicy": "allowlist-only",
"allowedCommands": [
"git status", "git log", "git diff",
"ls", "cat", "head", "tail",
"grep", "find", "pwd", "echo",
"npm run", "tsc"
],
// Defense in depth: always block these
"blockedCommands": [
"rm -rf /", "dd if=", "mkfs", "fdisk",
"curl | sh", "wget | sh",
"base64 -d", "eval $(",
"/dev/tcp/", "nc -e", "bash -i"
],
// Encrypt all credentials
"encryptCredentials": true
}
}π See SECURITY.md for detailed security documentation.
| Command | Description |
|---|---|
/start |
Start the bot and see welcome message |
/help |
Show available commands and help |
/status |
Check system status and configuration |
/health |
Health check with detailed status |
/metrics |
Runtime metrics summary (requests, failures, estimated tokens/cost) |
/session |
Show current session metadata |
/joke |
Send a random joke |
/fact |
Send a random fun fact |
/grant_access |
Allow AppleScript machine control in this chat |
/revoke_access |
Revoke AppleScript machine control |
/access_status |
Check AppleScript access status |
/approvals |
List pending risky tool approvals |
/approve [id] |
Approve latest or specific risky action |
/deny [id] |
Deny latest or specific risky action |
| Command | Description |
|---|---|
npm run setup |
Run interactive setup wizard |
npm start |
Start the bot |
npm run status |
Show system status |
npm run build |
Build TypeScript to JavaScript |
npm run dev |
Run in development mode |
npm test |
Run test suite |
Define your assistant's personality by editing ~/.mikiclaw/workspace/SOUL.md:
# Identity
- Name: Miki
- Role: Your personal AI assistant
- Voice: Warm, curious, friendly but competent
# Principles
1. Be helpful without being overwhelming.
2. Ask clarifying questions when needed.
3. Admit what you don't know.
4. Keep responses concise and actionable.
# Boundaries
- Don't execute destructive commands without confirmation.
- Don't share private system details.
- Stop and ask if something seems unsafe.
# Interaction Style
- Use light formatting (bold for emphasis)
- Use emojis sparingly (1-2 per message)
- Format code in code blocks
- End with a question or offerDuring setup, choose from:
| Template | Description |
|---|---|
| Miki (default) | Friendly and helpful |
| Professional | Concise and business-focused |
| Mentor | Educational and patient |
| Power User | Technical and efficient |
Extend mikiclaw with skills from ClawHub.
# List installed skills
node dist/index.js skills list
# Install a skill
node dist/index.js skills install <skill-name>
# Show config location
node dist/index.js configCreate a skill manifest at ~/.mikiclaw/skills/<name>/claw.json:
{
"name": "my-custom-skill",
"version": "1.0.0",
"description": "My custom skill description",
"author": "Your Name",
"tools": [
{
"name": "my_tool",
"description": "What this tool does",
"command": "echo",
"inputSchema": {
"type": "object",
"properties": {
"input": { "type": "string" }
}
}
}
]
}| Platform | Recommended Service Manager |
|---|---|
| Linux | systemd |
| macOS | launchd (LaunchAgent) |
| Windows | NSSM (Windows Service) |
| Any | PM2 |
Use this for development only:
npm install
npm run build
npm run setup
npm startBuild once before configuring any service:
npm install
npm run build
npm run setupCreate /etc/systemd/system/mikiclaw.service:
[Unit]
Description=mikiclaw AI assistant service
After=network.target
[Service]
Type=simple
User=YOUR_USER
WorkingDirectory=/ABSOLUTE/PATH/TO/mikiclaw
ExecStart=/usr/bin/env node /ABSOLUTE/PATH/TO/mikiclaw/dist/index.js start
Restart=always
RestartSec=10
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target# Enable + start
sudo systemctl daemon-reload
sudo systemctl enable mikiclaw
sudo systemctl start mikiclaw
# Verify + logs
sudo systemctl status mikiclaw
sudo journalctl -u mikiclaw -fCreate ~/Library/LaunchAgents/com.softorize.mikiclaw.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.softorize.mikiclaw</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/env</string>
<string>node</string>
<string>/ABSOLUTE/PATH/TO/mikiclaw/dist/index.js</string>
<string>start</string>
</array>
<key>WorkingDirectory</key>
<string>/ABSOLUTE/PATH/TO/mikiclaw</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/ABSOLUTE/PATH/TO/mikiclaw/logs/launchd-out.log</string>
<key>StandardErrorPath</key>
<string>/ABSOLUTE/PATH/TO/mikiclaw/logs/launchd-err.log</string>
</dict>
</plist>mkdir -p ./logs
# Load + start
launchctl load -w ~/Library/LaunchAgents/com.softorize.mikiclaw.plist
launchctl start com.softorize.mikiclaw
# Status + logs
launchctl list | grep mikiclaw
tail -f ./logs/launchd-out.logInstall NSSM, then in elevated PowerShell:
npm install
npm run build
npm run setup
nssm install MikiClaw "C:\Program Files\nodejs\node.exe" "C:\ABSOLUTE\PATH\mikiclaw\dist\index.js" start
nssm set MikiClaw AppDirectory "C:\ABSOLUTE\PATH\mikiclaw"
nssm set MikiClaw AppStdout "C:\ABSOLUTE\PATH\mikiclaw\logs\service-out.log"
nssm set MikiClaw AppStderr "C:\ABSOLUTE\PATH\mikiclaw\logs\service-err.log"
nssm start MikiClawnpm install -g pm2
pm2 start dist/index.js --name "mikiclaw" -- start
pm2 save
pm2 startup
pm2 status
pm2 logs mikiclawdocker build -t mikiclaw .
docker run -d \
--name mikiclaw \
-v mikiclaw-data:/home/nodejs/.mikiclaw \
mikiclawSee docs/DEPLOYMENT.md for Railway/Render/GCP/AWS examples.
After pulling new code:
git pull
npm install
npm run buildThen restart based on service manager:
# systemd
sudo systemctl restart mikiclaw
# launchd
launchctl kickstart -k gui/$(id -u)/com.softorize.mikiclaw
# PM2
pm2 restart mikiclaw| Endpoint | URL | Auth Required |
|---|---|---|
| Health | http://localhost:19090/health |
β Token |
| Metrics | http://localhost:19090/metrics |
β Token |
| Token | http://localhost:19090/token |
Localhost only |
# Check health (with auth token)
curl -H "X-Auth-Token: YOUR_TOKEN" http://localhost:19090/health
# Get auth token (localhost only)
curl http://localhost:19090/tokenLogs are stored in ~/.mikiclaw/logs/ with daily rotation.
# View today's log
tail -f ~/.mikiclaw/logs/mikiclaw-$(date +%Y-%m-%d).log
# Search logs
grep "ERROR" ~/.mikiclaw/logs/*.log- Check if bot is running:
npm run status - Verify Telegram token is correct
- Check logs:
~/.mikiclaw/logs/ - Ensure bot is not rate limited
- Review your tool policy in config
- Add command to
allowedCommandslist - Consider switching to
block-destructivepolicy temporarily
- Verify API key is correct and has credits
- Check network connectivity
- Review rate limits on your API plan
- Check logs for detailed error messages
# Check key file permissions
ls -la ~/.mikiclaw_key
# Fix permissions if needed
chmod 600 ~/.mikiclaw_key- By default, only localhost can access without auth
- Get auth token:
curl http://localhost:19090/token - Use token in header:
curl -H "X-Auth-Token: TOKEN" http://localhost:19090/health
- Check logs:
~/.mikiclaw/logs/ - Run status:
npm run status - Review configuration:
cat ~/.mikiclaw/config.json - Open an issue on GitHub
mikiclaw/
βββ src/
β βββ agent/ # Agent logic and tools
β βββ ai/ # AI providers + router/failover
β βββ automation/ # Workflow engine (trigger/condition/action)
β βββ bot/ # Telegram bot handlers
β βββ channels/ # Channel adapters
β βββ commands/ # CLI commands
β βββ config/ # Configuration and encryption
β βββ heartbeat/ # Scheduled tasks
β βββ observability/ # Runtime metrics store
β βββ personality/ # SOUL.md and memory
β βββ security/ # Access grants + risky action approvals
β βββ skills/ # Skills system
β βββ utils/ # Utilities (validation, retry, logging)
β βββ webhooks/ # Signed webhook server + event delivery
β βββ index.ts # Entry point
βββ tests/ # Test suite
βββ dist/ # Compiled JavaScript
βββ workspace/ # Runtime workspace
# Run in development mode (with hot reload)
npm run dev
# Build TypeScript
npm run build
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Generate coverage report
npm run test:coverage# Run all tests
npm test
# Run specific test file
npx vitest tests/validation.test.ts
# Run with coverage
npm run test:coverageContributions are welcome! Please see CONTRIBUTING.md for guidelines.
# Fork and clone
git clone https://github.com/YOUR_USERNAME/mikiclaw
cd mikiclaw
# Install dependencies
npm install
# Create a branch
git checkout -b feature/your-feature
# Make changes and test
npm run dev
npm test
# Commit and push
git commit -m "feat: add your feature"
git push origin feature/your-featureMIT License - see LICENSE for details.
- Inspired by OpenClaw
- Built with Telegraf for Telegram
- AI integration via @anthropic-ai/sdk
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: This README and inline code comments
Made with β€οΈ by Softorize