{"id":47293822,"url":"https://github.com/catiesgames/catclaw","last_synced_at":"2026-05-11T05:01:55.356Z","repository":{"id":344791033,"uuid":"1182980047","full_name":"CatiesGames/catclaw","owner":"CatiesGames","description":"Personal AI assistant gateway powered by Claude Code — multi-agent, multi-channel (Discord/Telegram/TUI), session management, tool approval, memory system","archived":false,"fork":false,"pushed_at":"2026-04-07T06:58:04.000Z","size":1557,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-07T08:31:55.723Z","etag":null,"topics":["ai","ai-assistant","claude","claude-code","discord-bot","mcp","multi-agent","rust","self-hosted","telegram-bot"],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/CatiesGames.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"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-03-16T06:35:04.000Z","updated_at":"2026-04-07T06:57:55.000Z","dependencies_parsed_at":"2026-04-01T21:03:26.362Z","dependency_job_id":null,"html_url":"https://github.com/CatiesGames/catclaw","commit_stats":null,"previous_names":["catiesgames/catclaw"],"tags_count":74,"template":false,"template_full_name":null,"purl":"pkg:github/CatiesGames/catclaw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatiesGames%2Fcatclaw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatiesGames%2Fcatclaw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatiesGames%2Fcatclaw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatiesGames%2Fcatclaw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CatiesGames","download_url":"https://codeload.github.com/CatiesGames/catclaw/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatiesGames%2Fcatclaw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31639524,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-10T07:40:12.752Z","status":"ssl_error","status_checked_at":"2026-04-10T07:40:11.664Z","response_time":98,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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","ai-assistant","claude","claude-code","discord-bot","mcp","multi-agent","rust","self-hosted","telegram-bot"],"created_at":"2026-03-16T12:08:52.919Z","updated_at":"2026-05-11T05:01:55.348Z","avatar_url":"https://github.com/CatiesGames.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/rust-1.75+-orange?logo=rust\" alt=\"Rust\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/claude_code-CLI-blueviolet\" alt=\"Claude Code\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/status-alpha-yellow\" alt=\"Status\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/splash.png\" alt=\"CatClaw Splash\" width=\"600\"\u003e\n\u003c/p\u003e\n\n---\n\n**English** | [繁體中文](README.zh-TW.md)\n\nCatClaw is a Rust daemon that turns your **Claude Code subscription** into a personal AI assistant accessible from Discord, Telegram, Slack, and a beautiful terminal UI. Inspired by OpenClaw, built from scratch in Rust for performance, reliability, and full Anthropic compliance.\n\n## Why CatClaw?\n\n- **Use your Claude Code subscription** \u0026mdash; no API keys, no surprise bills. CatClaw spawns `claude -p` subprocesses that use your existing Claude Code plan.\n- **Multi-agent** \u0026mdash; define multiple AI personas (main assistant, research expert, code reviewer), each with their own personality, memory, and tool permissions.\n- **Multi-channel** \u0026mdash; talk to your agents from Discord, Telegram, Slack, or the built-in TUI. All channels share the same session and memory system.\n- **Tool approval system** \u0026mdash; require user confirmation before agents execute sensitive tools (Bash, Edit, etc.) with inline approval UI in TUI and Discord/Telegram/Slack buttons.\n- **Stateless gateway** \u0026mdash; all state persisted to SQLite. Kill the daemon anytime, restart, and everything picks up where it left off.\n- **Beautiful TUI** \u0026mdash; Catppuccin Mocha themed terminal interface with 8 panels for managing everything.\n\n## Quick Start\n\n### Prerequisites\n\n- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated\n\n### Install\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CatiesGames/catclaw/main/install.sh | sh\n```\n\nOr build from source:\n```bash\ngit clone https://github.com/CatiesGames/catclaw.git\ncd catclaw\ncargo build --release\n```\n\n### Launch\n\n```bash\ncatclaw onboard\n```\n\nOn first run, CatClaw will:\n1. Show the splash logo\n2. Run the interactive setup wizard (verify Claude Code CLI, create your agent, configure channels)\n3. Optionally install as a system service (auto-start on boot)\n4. Start the gateway in the background\n5. Launch the TUI\n\nOn subsequent runs, it skips setup and goes straight to gateway + TUI.\n\n```bash\n# Other ways to run:\ncatclaw onboard                   # Re-run the setup wizard\ncatclaw gateway start             # Start gateway in foreground\ncatclaw gateway start -d          # Start gateway as background daemon\ncatclaw gateway stop              # Stop the background gateway\ncatclaw gateway status            # Show gateway status\ncatclaw tui                       # Launch TUI only (connects to running gateway)\n\n# Updates \u0026 auto-start:\ncatclaw update                    # Self-update to latest version (manual; for the human user)\ncatclaw update --resume           # Self-update + restart + auto-resume the current session (for the agent to call itself)\ncatclaw update --check            # Check for updates without installing\ncatclaw gateway install           # Install as system service (auto-start on boot)\ncatclaw gateway uninstall         # Remove the system service\ncatclaw uninstall                 # Full uninstall (stop, remove service, delete binary)\n```\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────────────┐\n│                       CatClaw Gateway (Rust)                     │\n│                                                                  │\n│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐                 │\n│  │  Discord     │ │  Telegram   │ │  Slack      │  Adapters      │\n│  │  Adapter     │ │  Adapter    │ │  Adapter    │                │\n│  └──────┬───────┘ └──────┬──────┘ └──────┬──────┘                │\n│         └────────────────┘                                        │\n│                  ▼                                                │\n│  ┌────────────────────────────────────────────────────────────┐  │\n│  │  Message Router  →  Agent Registry  →  Session Manager    │  │\n│  │  (binding table)    (SOUL/tools)       (claude -p spawn)  │  │\n│  └────────────────────────────────────────────────────────────┘  │\n│                                                                  │\n│  ┌──────────────────┐  ┌──────────────────┐                     │\n│  │  State DB         │  │  Scheduler       │                     │\n│  │  (SQLite WAL)     │  │  (cron/heartbeat)│                     │\n│  └──────────────────┘  └──────────────────┘                     │\n│                                                                  │\n│  ┌──────────────────────────────────────────────────────────┐   │\n│  │  WS Server (/ws)  +  MCP Server (/mcp)  — port 21130    │   │\n│  └──────────────────────────────────────────────────────────┘   │\n└──────────────────────────────────────────────────────────────────┘\n          ▲                              ▲\n          │ WebSocket                    │ MCP JSON-RPC\n    ┌─────┴─────┐                 ┌──────┴──────┐\n    │  TUI      │                 │  Claude CLI │\n    │ (ratatui) │                 │  (tool use) │\n    └───────────┘                 └─────────────┘\n```\n\n**How it works**: When a message arrives from any channel, CatClaw resolves which agent should handle it (via binding table), finds or creates a session, spawns a `claude -p --output-format stream-json` subprocess, and streams the response back to the originating channel.\n\nEach `claude -p` subprocess uses your Claude Code subscription \u0026mdash; no API keys needed.\n\n## CLI Reference\n\nAll configuration is managed through the CLI or TUI. No manual file editing required.\n\n### Gateway\n\n```bash\ncatclaw onboard                   # Onboarding: setup wizard → start gateway → launch TUI\ncatclaw gateway start             # Start gateway in foreground\ncatclaw gateway start -d          # Start as background daemon\ncatclaw gateway stop              # Stop background gateway\ncatclaw gateway restart           # Restart daemon (manual; for the human user)\ncatclaw gateway restart --resume  # Restart + auto-resume the current channel session (for the agent to call itself; user does not need to ping again)\ncatclaw gateway status            # Show running status and PID\ncatclaw onboard                      # Re-run the setup wizard\ncatclaw tui                       # Launch TUI only\n```\n\n### Agent Management\n\n```bash\ncatclaw agent new \u003cname\u003e                          # Create a new agent\ncatclaw agent list                                # List all agents\ncatclaw agent edit \u003cname\u003e \u003cfile\u003e                  # Open file in $EDITOR\ncatclaw agent tools \u003cname\u003e                        # Show current tool permissions\ncatclaw agent tools \u003cname\u003e \\\n  --allow \"Read,Grep,WebFetch\" \\\n  --deny \"Bash\" \\\n  --approve \"Edit,Write\"                          # Configure tool permissions\ncatclaw agent delete \u003cname\u003e                       # Delete an agent\n```\n\n`\u003cfile\u003e` values: `soul`, `user`, `identity`, `agents`, `tools`, `boot`, `heartbeat`, `memory`\n\n### Channels\n\n```bash\ncatclaw channel list                              # List configured channels\ncatclaw channel add discord \\\n  --token-env CATCLAW_DISCORD_TOKEN \\\n  --guilds \"123456789\" \\\n  --activation mention                            # Add Discord channel\ncatclaw channel add telegram \\\n  --token-env CATCLAW_TELEGRAM_TOKEN              # Add Telegram channel\ncatclaw channel add slack \\\n  --token-env CATCLAW_SLACK_BOT_TOKEN \\\n  --app-token-env CATCLAW_SLACK_APP_TOKEN         # Add Slack channel\n```\n\n### Bindings (Channel → Agent routing)\n\n```bash\ncatclaw bind \"discord:channel:222222\" research    # Bind a channel to an agent\ncatclaw bind \"telegram:*\" main                    # Bind all Telegram to main\ncatclaw bind \"slack:channel:C12345\" research      # Bind a Slack channel to an agent\ncatclaw bind \"*\" main                             # Global fallback\ncatclaw unbind \"discord:channel:222222\"           # Remove a binding\n```\n\nBindings hot-reload through the running gateway — no restart needed. When the gateway is offline, changes save to `catclaw.toml` and load on next start.\n\n### Sessions\n\n```bash\ncatclaw session list                              # List all sessions\ncatclaw session delete \u003ckey\u003e                      # Delete a session\n```\n\n### Skills\n\n```bash\ncatclaw skill list \u003cagent\u003e                        # List skills (built-in + installed)\ncatclaw skill enable \u003cagent\u003e \u003cskill\u003e              # Enable a skill\ncatclaw skill disable \u003cagent\u003e \u003cskill\u003e             # Disable a skill\ncatclaw skill install \u003csource\u003e                    # Install from remote source\ncatclaw skill uninstall \u003cskill\u003e                   # Remove a skill\n```\n\nInstall sources: `@anthropic/\u003cname\u003e`, `github:\u003cowner\u003e/\u003crepo\u003e/path`, `/local/path`\n\n### Scheduled Tasks\n\n```bash\ncatclaw task list                                 # List scheduled tasks\ncatclaw task add \u003cname\u003e --agent main \\\n  --prompt \"Check inbox\" --every 30               # Repeat every 30 minutes\ncatclaw task add \u003cname\u003e --agent main \\\n  --prompt \"Morning briefing\" --cron \"0 9 * * *\"  # Cron schedule\ncatclaw task enable \u003cid|name\u003e                     # Enable a task (by ID or name)\ncatclaw task disable \u003cid|name\u003e                    # Disable a task\ncatclaw task delete \u003cid|name\u003e                     # Delete a task\n```\n\n### Configuration\n\n```bash\ncatclaw config show                               # Show full config (TOML)\ncatclaw config get \u003ckey\u003e                          # Get a specific value\ncatclaw config set \u003ckey\u003e \u003cvalue\u003e                  # Set a value (hot-reload when possible)\n```\n\n### Environment variables\n\nTokens (LINE / Discord / Slack / Telegram / Meta) are referenced from config by `*_env` keys; the actual values live in `~/.catclaw/.env`:\n\n```bash\ncatclaw env list                                  # Show all (values masked)\ncatclaw env set CATCLAW_LINE_CHANNEL_ACCESS_TOKEN xxx\ncatclaw env get \u003cKEY\u003e\ncatclaw env remove \u003cKEY\u003e\ncatclaw mcp_env set \u003cserver\u003e \u003cKEY\u003e \u003cVALUE\u003e        # Per-MCP-server env (separate scope)\n```\n\n`catclaw onboard` does this for you when adding channels. For manual / scripted deployments use `catclaw env set` — **don't** rely on shell `export`, the daemon (`catclaw gateway start -d`) won't inherit interactive shell env.\n\n### Logs\n\n```bash\ncatclaw logs                                      # Show recent logs\ncatclaw logs -f                                   # Stream in real-time\ncatclaw logs --level debug                        # Filter by level\ncatclaw logs --grep \"discord\"                     # Search by pattern\ncatclaw logs --json                               # Raw JSON output\n```\n\n## TUI\n\nThe TUI provides a beautiful Catppuccin Mocha themed interface with 8 panels:\n\n| Panel | Description |\n|---|---|\n| **Dashboard** | Overview with agent count, active sessions, uptime |\n| **Sessions** | View all sessions, chat directly with agents, inline tool approval |\n| **Agents** | Manage agents, edit personality files, configure tool permissions (allowed/denied/approval) |\n| **Skills** | Enable/disable/install skills per agent |\n| **Tasks** | View and manage scheduled tasks (heartbeat, cron) |\n| **Bindings** | Map channels to agents |\n| **Config** | View and edit gateway configuration with hot-reload |\n| **Logs** | Live log viewer with search, level filter, structured fields |\n\n**Keyboard shortcuts**: `Tab`/`Shift+Tab` cycle panels, `Alt+1-8` jump directly, `q` quit. Mouse scroll supported in Sessions and Logs.\n\n**Chat commands**: `/new` start fresh session, `/model \u003cname\u003e` switch model, `/help` show help.\n\n## Agent System\n\nEach agent has its own workspace with personality, memory, skills, and tool permissions:\n\n```\nworkspace/agents/main/\n├── SOUL.md              # Personality, tone, values\n├── USER.md              # Who the user is\n├── IDENTITY.md          # Agent name, role\n├── AGENTS.md            # Workspace conventions\n├── TOOLS.md             # Tool usage guidelines\n├── BOOT.md              # Startup instructions (prepended to first message)\n├── HEARTBEAT.md         # Periodic check tasks\n├── MEMORY.md            # Long-term memory (curated)\n├── memory/              # Daily notes (YYYY-MM-DD.md)\n├── transcripts/         # Session logs (JSONL)\n└── tools.toml           # Tool permissions\n```\n\n### Tool Permissions\n\nEach tool exists in exactly one of three states:\n\n```toml\n# workspace/agents/research/tools.toml\nallowed = [\"Read\", \"Grep\", \"Glob\", \"WebFetch\", \"WebSearch\"]\ndenied = [\"Bash\"]\nrequire_approval = [\"Edit\", \"Write\"]\n```\n\n- **allowed** \u0026mdash; tool runs freely\n- **denied** \u0026mdash; tool is completely blocked\n- **require_approval** \u0026mdash; tool runs only after user approves (via TUI inline widget, Discord button, Telegram keyboard, or Slack Block Kit button)\n\nManage via TUI (Agents → `t` Tools → Space to cycle states) or CLI (`catclaw agent tools`).\n\n### Skills\n\nCatClaw ships with built-in skills and supports installing custom ones:\n\n| Skill | Description |\n|---|---|\n| `catclaw` | CatClaw system administration (agent knows all CLI commands) |\n| `discord` | Discord formatting and MCP tool usage |\n| `telegram` | Telegram formatting and MCP tool usage |\n| `slack` | Slack formatting and MCP tool usage |\n| `sessions-history` | Query transcripts from other sessions |\n| `injection-guard` | Defend against prompt injection from external content |\n\nSkills are shared across agents via `workspace/skills/`. Each agent can enable/disable skills independently.\n\n### User MCP Servers\n\nAdd custom MCP servers in `workspace/.mcp.json` (shared across all agents):\n\n```json\n{\n  \"mcpServers\": {\n    \"my-api\": {\n      \"type\": \"http\",\n      \"url\": \"https://api.example.com/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer ${MY_API_KEY}\" }\n    }\n  }\n}\n```\n\nMCP tools appear in the TUI Tools panel under \"User MCP Servers\" and can be denied or set to require approval per agent.\n\n## Channel Adapters\n\n| Channel | Status | Features |\n|---|---|---|\n| **Discord** | ✅ | Threads, typing indicator, approval buttons, 32 MCP actions |\n| **Telegram** | ✅ | Long polling, forum topics, approval keyboard, 26 MCP actions |\n| **Slack** | ✅ | Socket Mode, threads, native AI streaming, approval buttons, 17 MCP actions |\n| **LINE** | ✅ | Webhook + HMAC verify, reply-token + push, image/video/file inbound, 11 MCP actions (rich menu / flex / quota / profile) |\n| **TUI** | ✅ | Direct chat with streaming, inline approval widget |\n\n**Activation modes** (DMs always respond; this controls group/server channels):\n- `mention` (default) \u0026mdash; respond only when @mentioned\n- `all` \u0026mdash; respond to every message\n\n### Built-in MCP Server\n\nCatClaw exposes channel adapter operations as MCP tools, so agents can autonomously perform platform actions:\n\n```\nAgent wants to list Discord channels\n  → Claude calls mcp__catclaw__discord_get_channels\n  → CatClaw MCP server → serenity → Discord REST API\n  → JSON result back to agent\n```\n\n**Discord** (32 tools): messages, reactions, pins, threads, channels, categories, permissions, guilds, members, roles, emojis, moderation, events, stickers.\n\n**Telegram** (26 tools): messages, pins, chat info/management, moderation, polls, forum topics, permissions, invite links.\n\n**Slack** (17 tools): messages, reactions, pins, channels, threads, users.\n\n## Session Management\n\n```\nSessionKey = catclaw:{agent_id}:{origin}:{context_id}\n```\n\n**Lifecycle**:\n```\nNew → Active (claude -p subprocess alive)\n       ↓ idle 30 min\n     Idle (subprocess exited, session_id preserved for --resume)\n       ↓ idle 7 days\n     Archived (summary written to memory, start fresh)\n```\n\n**Concurrency**: configurable max (default 3) with priority queue (DM \u003e mention \u003e cron). Excess requests queued.\n\n**Stateless restart**: all state in SQLite. Kill and restart — sessions resume via `--resume`.\n\n## Configuration\n\n```toml\n[general]\nworkspace = \"./workspace\"\nstate_db = \"./state.sqlite\"\nmax_concurrent_sessions = 3\nsession_idle_timeout_mins = 30\nsession_archive_timeout_hours = 168\nport = 21130                        # WS + MCP on single port\nstreaming = true\ndefault_model = \"opus\"              # optional: opus, sonnet, haiku\n\n[[channels]]\ntype = \"discord\"\ntoken_env = \"CATCLAW_DISCORD_TOKEN\"\nguilds = [\"123456789\"]\nactivation = \"mention\"\n\n[[channels]]\ntype = \"telegram\"\ntoken_env = \"CATCLAW_TELEGRAM_TOKEN\"\n\n[[channels]]\ntype = \"slack\"\ntoken_env = \"CATCLAW_SLACK_BOT_TOKEN\"\napp_token_env = \"CATCLAW_SLACK_APP_TOKEN\"\nactivation = \"mention\"\n\n[[agents]]\nid = \"main\"\nworkspace = \"./workspace/agents/main\"\ndefault = true\n\n[agents.approval]\ntimeout_secs = 120                  # approval timeout (global)\n```\n\n## Social Inbox\n\nCatClaw integrates Instagram and Threads via an independent Social Inbox subsystem — separate from channel adapters. Events flow: poll/webhook → dedup → rule-based action router → forward card or auto-reply draft → staged admin approval → send via Meta API.\n\n### Architecture\n\n```\nInstagram Graph API ──┐\n                       ├─→ SocialItem channel ─→ run_ingest()\nThreads API ──────────┘         │\nWebhook (POST /webhook/*)        ↓\n                          action router (rules)\n                               │\n         ┌─────────────────────┼──────────────────┐\n         ↓                     ↓                  ↓\n      forward              auto_reply          template / ignore\n      card → admin       Claude session →      call Meta API\n      [AI Reply]         stage_reply →         directly\n      [Manual Reply]     draft review card →\n      [Ignore]           admin approves →\n                         call Meta API\n```\n\n### Config\n\n```toml\n[social.instagram]\nmode = \"polling\"                           # polling | webhook | off\npoll_interval_mins = 5\ntoken_env = \"INSTAGRAM_TOKEN\"              # System User Token env var (never expires)\napp_secret_env = \"INSTAGRAM_APP_SECRET\"   # For HMAC webhook verification\nuser_id = \"17841412345678\"\nadmin_channel = \"discord:channel:123456\"  # Forward card destination\nagent = \"main\"\n\n[[social.instagram.rules]]\nmatch = \"comments\"        # event type: comments | mentions | messages | *\naction = \"forward\"        # forward | auto_reply | auto_reply_template | ignore\n\n[[social.instagram.rules]]\nmatch = \"mentions\"\nkeyword = \"price\"         # optional keyword filter\naction = \"auto_reply\"\nagent = \"support\"\n\n[[social.instagram.rules]]\nmatch = \"*\"\naction = \"ignore\"\n\n[social.instagram.templates]\ndefault_mention = \"Thank you for the mention! We will be in touch soon.\"\n\n[social.threads]\nmode = \"polling\"\npoll_interval_mins = 3\ntoken_env = \"THREADS_TOKEN\"               # Threads OAuth token (expires 60 days)\napp_secret_env = \"THREADS_APP_SECRET\"\nuser_id = \"12345678\"\nadmin_channel = \"slack:channel:C0A9FFY7QAZ\"\nagent = \"main\"\n\n[[social.threads.rules]]\nmatch = \"replies\"\naction = \"forward\"\n\n[[social.threads.rules]]\nmatch = \"*\"\naction = \"ignore\"\n```\n\n### Webhook Setup\n\nAdd `webhook_verify_token_env` to the config and register the callback URL in Meta Developer Console:\n\n```\nGET/POST https://yourhost:PORT/webhook/instagram\nGET/POST https://yourhost:PORT/webhook/threads\n```\n\nThe GET handler validates `hub.verify_token`; the POST handler verifies HMAC-SHA256 signature against the app secret.\n\n### CLI\n\n```bash\ncatclaw social inbox                              # List all inbox items\ncatclaw social inbox --platform instagram         # Filter by platform\ncatclaw social inbox --status pending             # Filter by status\ncatclaw social poll instagram                     # Trigger manual poll\ncatclaw social mode instagram polling             # Switch mode (hot-reload)\ncatclaw social reprocess \u003cid\u003e                     # Reset inbox item, restore card with buttons,\n                                                   # re-run the action router (recovery tool for stuck cards)\n```\n\nDiscord also exposes `/social-reprocess id:\u003cid\u003e` as a slash command for the same purpose.\n\n### TUI\n\nAlt+9 opens the Social Inbox tab. Use Tab/BackTab to filter by status, Enter to view details, A to approve a draft, D to discard.\n\n### Agent MCP Tools\n\nWhen social is configured, agents get `instagram_*` and `threads_*` MCP tools for direct API access. The `*_stage_reply` tools store a draft and trigger an admin review card — no approval hook needed.\n\n---\n\n## Contacts\n\nCross-platform identity layer. CatClaw stores **who** you talk to (across Discord/Telegram/Slack/LINE) plus forward \u0026 approval rules — but **not the business data**. Business data (nutrition logs, training records, counseling notes, etc.) is the agent's responsibility — store wherever fits (Notion MCP, memory palace, your own SQLite).\n\n**Use when**: a single user (nutritionist / trainer / consultant / customer-service rep) manages multiple \"clients\" through the bot, and wants per-client routing, approval, or AI pause/resume.\n\n**Enable** (off by default to save ~3-4KB tokens per agent conversation):\n```bash\ncatclaw config set contacts.enabled true\n```\nWhen disabled, `contacts_*` MCP tools are not advertised to agents. Schema, CLI, and TUI remain functional — you can still build up contacts manually before flipping the switch.\n\n**Auto-registration of unknown contacts (LINE)**: when enabled, every LINE inbound sender (including follow events) is auto-registered as a `role=unknown` contact — **no LLM invoked**. These are storage-only until promoted to `client`/`admin` via `contacts_update`. This prevents strangers adding your OA from burning agent tokens. Optionally mirror unknown inbound to a channel for admin review:\n```bash\ncatclaw config set contacts.unknown_inbox_channel \"discord:guild_id/channel_id\"\n```\nIf unset, unknown inbound is only logged (`info!`); browse via TUI Contacts tab or `catclaw contact list --role unknown`.\n\nUnfollow events on LINE set `ai_paused=true` + tag `unfollowed` on the corresponding contact, preserving history.\n\n### Schema\n\n| Table | Purpose |\n|---|---|\n| `contacts` | id, agent_id, display_name, role (admin/client/unknown), tags, forward_channel, approval_required, ai_paused, external_ref (JSON), metadata (JSON) |\n| `contact_channels` | (platform, platform_user_id) → contact_id, with last_active_at for routing |\n| `contact_drafts` | Outbound draft queue (status: pending → awaiting_approval → sent / ignored / revising / failed) |\n\n### Outbound pipeline\n\n```\nagent → contacts_reply → draft → mirror to forward channel\n                              → approval gate (if approval_required)\n                              → adapter.send (platform = via OR last_active)\n                              → status=sent / failed\n```\n\nThe agent **cannot bypass** this pipeline — direct calls to platform native send tools won't go through forward + approval. Always use `contacts_reply`.\n\n### Inbound flow\n\nWhen an inbound message comes from a sender bound to a contact:\n1. `contact_channels.last_active_at` is touched (used for last-active routing).\n2. The message is mirrored to `forward_channel` (if set).\n3. If `ai_paused` is true → mirror only, agent is **not** invoked.\n4. Otherwise the agent receives the message with `[Contact: name=…, role=…, tags=…, external_ref=…, metadata=…]` injected into the system prompt.\n\nA message arriving in a forward_channel (admin's monitoring channel) and not bound to a contact is treated as a **manual reply** — forwarded to the corresponding contact directly under the agent's identity, bypassing the agent.\n\n### CLI\n\n```bash\ncatclaw contact add \u003cname\u003e [--role admin|client|unknown] [--tag ...] [--no-approval]\ncatclaw contact list [--agent ID] [--role ...]\ncatclaw contact show \u003cid\u003e\ncatclaw contact update \u003cid\u003e [--name ...] [--role ...] [--forward-channel ...] [--approval|--no-approval]\ncatclaw contact bind \u003cid\u003e --platform line --user-id U123...\ncatclaw contact unbind --platform line --user-id U123...\ncatclaw contact pause \u003cid\u003e\ncatclaw contact resume \u003cid\u003e\ncatclaw contact draft list [--status ...]\ncatclaw contact draft approve \u003cdraft_id\u003e\ncatclaw contact draft discard \u003cdraft_id\u003e\n```\n\n### TUI\n\n`Contacts` tab provides two sub-views (Tab toggles):\n- **Contacts**: list + role/tags/forward/approval/paused; `P`=toggle pause, `A`=toggle approval\n- **Drafts**: outbound draft queue; `a`=approve, `D`=discard\n\n### Agent MCP Tools\n\n`contacts_create / get / list / update / delete / bind_channel / unbind_channel / reply / ai_pause / ai_resume / drafts_list / draft_approve / draft_discard / draft_request_revision`\n\n`contacts_reply` payload supports `{type:\"text\"}`, `{type:\"image\"}`, `{type:\"flex\"}` (LINE-only Flex passes through to the LINE adapter).\n\n### Multi-agent extension path\n\nv1 binds each contact to a single agent (`contacts.agent_id`). All read paths go through `Contact::owning_agents() -\u003e Vec\u003cAgentId\u003e` which currently returns one entry. To support sharing a contact across multiple agents in v2, migrate to a `contact_agents` join table and update the helper — call sites unchanged.\n\n---\n\n## LINE (optional channel)\n\nLINE Messaging API integration. **Optional** — the adapter only starts when a `line` channel is configured; otherwise zero impact on the rest of the system.\n\n### Setup\n\nYou need:\n- A LINE Official Account with Messaging API enabled\n- Channel Access Token (long-lived) → set `LINE_CHANNEL_ACCESS_TOKEN`\n- Channel Secret → set `LINE_CHANNEL_SECRET`\n- A public HTTPS endpoint (cloudflared / ngrok / your own domain) pointing at the gateway port\n\n### Config\n\n```toml\n[[channels]]\ntype = \"line\"\ntoken_env = \"LINE_CHANNEL_ACCESS_TOKEN\"\nsecret_env = \"LINE_CHANNEL_SECRET\"\n```\n\nIn LINE Developer Console, set the webhook URL to `https://your.host/webhook/line` and verify.\n\n### Capabilities\n\n- **Inbound**: text, image, video, audio, file (auto-download via Content API + Bearer token), follow / unfollow / postback events\n- **Outbound**: 5-minute reply-token (free) → fallback to push API (counts toward quota)\n- **HMAC-SHA256** signature verification on every webhook delivery\n- **Rich Menu** fully managed by the agent — CatClaw stores no menu↔role mapping\n\n### Agent MCP Tools (`line_*`)\n\n| Tool | Purpose |\n|---|---|\n| `line_rich_menu_create` | Create a rich menu |\n| `line_rich_menu_upload_image` | Upload background image (JPEG/PNG) |\n| `line_rich_menu_list` | List all menus |\n| `line_rich_menu_delete` | Delete a menu |\n| `line_rich_menu_set_default` | Set as OA-wide default |\n| `line_rich_menu_link_user` | Apply menu to specific user |\n| `line_rich_menu_unlink_user` | Remove per-user override |\n| `line_get_quota` | Push API monthly quota |\n| `line_get_profile` | LINE user displayName + picture URL |\n| `line_send_flex` | Send Flex message |\n| `line_show_loading` | Show loading animation in 1:1 chat |\n\nFor LINE-side outbound to actual contacts, use `contacts_reply` (which routes through the contacts pipeline). `line_send_flex` is for direct out-of-band Flex sends (e.g. broadcasts not tied to a contact).\n\n---\n\n## Tech Stack\n\n| Component | Crate |\n|---|---|\n| Async runtime | `tokio` |\n| Discord | `serenity` + `poise` |\n| Telegram | `teloxide` |\n| Slack | `reqwest` + `tokio-tungstenite` (Socket Mode) |\n| HTTP server (WS + MCP) | `axum` |\n| CLI | `clap` (derive) |\n| Database | `rusqlite` (bundled SQLite, WAL) |\n| TUI | `ratatui` + `crossterm` + `tui-textarea` |\n| Config | `toml` + `serde` |\n| Scheduling | `croner` (cron expressions) |\n| Logging | `tracing` |\n\n## Feedback\n\nFound a bug or have a feature request? [Open an issue](https://github.com/CatiesGames/catclaw/issues).\n\n## License\n\nMIT\n\n---\n\n\u003cp align=\"center\"\u003e\n  Built with Rust and Claude Code\u003cbr\u003e\n  \u003cstrong\u003eCatiesGames\u003c/strong\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcatiesgames%2Fcatclaw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcatiesgames%2Fcatclaw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcatiesgames%2Fcatclaw/lists"}