A reference implementation for building persistent, Telegram-connected autonomous AI agents using Claude Code and a Claude Max subscription. Zero API cost. Full autonomy. Runs 24/7 on any Linux machine.
Claudex is an autonomous AI agent that runs as a persistent daemon on a Linux machine (tested on WSL2/Ubuntu). It:
- 💬 Connects to Telegram — real-time two-way messaging, just like a human chat
- 🧠 Has memory — CLAUDE.md for identity/rules + daily memory files for continuity across sessions
- 🔧 Has skills — 160 portable skill modules for everything from weather to code review to system monitoring
- 🤖 Spawns sub-agents — delegate parallel work to specialized agents (researcher, coder, reviewer, etc.)
- 🔄 Self-heals — watchdog cron + systemd auto-restart keeps it alive 24/7
- 💰 Zero API cost — runs on Claude Max subscription ($100/mo flat), not per-token billing
This repo documents the complete system architecture, provides templates for building your own, and includes the actual scripts and configurations used in production.
- Architecture
- Quick Start
- How It Works
- Comparison: Claudex vs OpenClaw
- Directory Structure
- Debugging & Gotchas
- Examples
- Contributing
- License
┌────────────────────────────────────────────────┐
│ YOUR LINUX MACHINE │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ CLAUDE CODE (tmux/systemd) │ │
│ │ │ │
│ │ ┌──────────┐ ┌────────┐ ┌──────────┐ │ │
│ │ │ CLAUDE.md│ │ Memory │ │Sub-agents│ │ │
│ │ │ (soul, │ │ (daily │ │(research,│ │ │
│ │ │ user, │ │ notes)│ │ coder, │ │ │
│ │ │ rules) │ │ │ │ writer) │ │ │
│ │ └──────────┘ └────────┘ └──────────┘ │ │
│ │ │ │
│ │ ┌──────────┐ ┌────────┐ │ │
│ │ │ Health │ │ Inbox │ │ │
│ │ └──────────┘ └────────┘ │ │
│ │ │ │
│ │ ┌────────────┐ ┌───────────────────┐ │ │
│ │ │ Telegram │ │ 160 Skills │ │ │
│ │ │ Channel │ │ (.claude/skills/)│ │ │
│ │ │ (plugin) │ │ │ │ │
│ │ └─────┬──────┘ └───────────────────┘ │ │
│ │ │ │ │
│ │ ┌─────┴──────┐ ┌───────────────────┐ │ │
│ │ │ Hooks │ │ MCP Servers │ │ │
│ │ │ (lifecycle)│ │ (fs, github, web) │ │ │
│ │ └────────────┘ └───────────────────┘ │ │
│ └──────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ systemd + watchdog cron (5 min) │ │
│ │ keeps the agent alive 24/7 │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
│
│ Telegram Bot API
▼
┌──────────────┐
│ User's │
│ Telegram │
└──────────────┘
- Claude Max subscription ($100/mo) — provides Opus 4.8 with 1M context, zero per-token cost
- Linux machine (WSL2, Ubuntu, Debian, etc.)
- Node.js 22+ and Bun (Bun required for the Telegram channel plugin runtime)
curl -fsSL https://claude.ai/install.sh | bash
claude auth login # authenticate with your Anthropic accountgit clone https://github.com/JansenAnalytics/claudex.git
cd claudex
bash scripts/bootstrap.shThis creates the workspace at ~/.claude-agent/, copies templates, and walks you through Telegram setup.
# Create workspace
mkdir -p ~/.claude-agent/{memory,logs,scripts,projects}
mkdir -p ~/.claude-agent/.claude/{skills,agents,rules}
# Copy templates (customize CLAUDE.md with your identity)
cp templates/CLAUDE.md.example ~/.claude-agent/CLAUDE.md
# Permissions — bypassPermissions (autonomous, no prompts). Required for a headless
# Telegram agent; there's no terminal to approve prompts. See "Permissions & Safety".
cp templates/settings.json ~/.claude-agent/.claude/settings.json
# Want the same setup with a deny safety net + inline docs (or to switch to a
# prompting mode for attended use)? Use templates/settings.json.example instead.
# Pre-approve the two one-time first-run gates so the first start needs no clicks
# (scripts/bootstrap.sh does this for you; manual equivalent below):
node -e 'const fs=require("fs"),os=require("os"),p=require("path");const ws=p.join(os.homedir(),".claude-agent");
const m=(f,fn)=>{let d={};try{d=JSON.parse(fs.readFileSync(f,"utf8"))}catch(_){}; fn(d); fs.mkdirSync(p.dirname(f),{recursive:true}); fs.writeFileSync(f,JSON.stringify(d,null,2)+"\n")};
m(p.join(os.homedir(),".claude","settings.json"),d=>d.skipDangerousModePermissionPrompt=true);
m(p.join(os.homedir(),".claude.json"),d=>{d.projects=d.projects||{};d.projects[ws]=d.projects[ws]||{};d.projects[ws].hasTrustDialogAccepted=true});'
# Copy skills you want
cp -r skills/* ~/.claude-agent/.claude/skills/
# Copy sub-agents
cp agents/* ~/.claude-agent/.claude/agents/
# Copy rules
cp rules/* ~/.claude-agent/.claude/rules/
# Start Claude Code with Telegram
cd ~/.claude-agent
claude --channels plugin:telegram@claude-plugins-official \
--dangerously-skip-permissions \
--continueSee the Telegram Setup Guide for detailed instructions.
Quick version:
- Create a bot via @BotFather on Telegram
- In Claude Code:
/plugin install telegram@claude-plugins-official - Configure:
/telegram:configure <your-bot-token> - Pair your account:
/telegram:access pair <code>(get code from bot) - Lock down:
/telegram:access policy allowlist
# Install management scripts
cp scripts/start-claudex.sh ~/.claude-agent/scripts/
cp scripts/watchdog-claudex.sh ~/.claude-agent/scripts/
# Enable systemd service
cp systemd/claudex.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable claudex
systemctl --user start claudex
loginctl enable-linger $USER # survive logout
# Add watchdog cron (auto-restarts if process dies)
(crontab -l 2>/dev/null; echo "*/5 * * * * bash ~/.claude-agent/scripts/watchdog-claudex.sh") | crontab -The CLAUDE.md file is the agent's soul — personality, rules, context, and operating instructions. It's loaded at session start and stays in context throughout.
# CLAUDE.md — Your Agent Name
## Who You Are
Name, personality, boundaries...
## About Your Human
Name, timezone, preferences, communication style...
## Operating Rules
1. Act, then report
2. Verify before announcing
3. Write things down
...
## Key Projects
Links to project directories, key context...See templates/CLAUDE.md.example for a complete annotated template.
| OpenClaw File | Claudex Equivalent | Purpose |
|---|---|---|
SOUL.md |
CLAUDE.md (personality section) |
Who the agent is |
USER.md |
CLAUDE.md (user section) |
Who it's helping |
AGENTS.md |
CLAUDE.md (rules section) |
Operating rules |
MEMORY.md |
Auto Memory + memory/*.md |
Long-term memory |
TOOLS.md |
.claude/CLAUDE.md |
Environment-specific notes |
HEARTBEAT.md |
Scheduled tasks + /loop |
Periodic checks |
IDENTITY.md |
CLAUDE.md (identity section) |
Name, creature, vibe |
Skills are modular instruction sets that teach the agent how to handle specific tasks. Each skill is a markdown file with YAML frontmatter:
---
name: weather
description: Get current weather and forecasts. Use when the user asks about weather.
---
# Weather Skill
Fetch weather using wttr.in:
\```bash
curl -s "wttr.in/LOCATION?format=%l:+%c+%t+%h+%w"
\```Claude Code auto-selects relevant skills based on the task description. Place skills in .claude/skills/<name>/SKILL.md.
This repo includes all 160 production-tested skills covering:
- 🌤️ Weather, web monitoring, research
- 💻 GitHub workflow, code review, testing
- 📊 Data analysis, market data, trading
- 🔧 System admin, Docker, CI/CD
- 📝 Documentation, LaTeX, note-taking
- 🔔 Notifications (ntfy), webhooks
- And many more — see skills/
Custom sub-agents handle specialized parallel work:
# ~/.claude/agents/researcher.md
---
name: researcher
description: Deep research tasks — web search, multi-source analysis, report writing.
model: opus
---
You are a research agent. Given a topic:
1. Search multiple sources
2. Cross-reference findings
3. Synthesize into a clear summaryAvailable sub-agents in this setup:
| Agent | Model | Purpose |
|---|---|---|
researcher |
Opus | Multi-source research and analysis |
coder |
Opus | Feature implementation, bug fixes |
reviewer |
Opus | Code review and PR analysis |
analyst |
Opus | Data analysis and market research |
sysadmin |
Opus | Infrastructure and ops tasks |
writer |
Opus | Documentation, reports, plans |
tester |
Opus | Run test suites, parse failures, propose fixes |
incident-responder |
Opus | Diagnose incidents from logs/metrics, root-cause, post-mortem |
documentarian |
Opus | Inline docs, READMEs, and API references after code changes |
The Telegram channel plugin provides native two-way messaging:
- Messages from Telegram → Claude Code receives and processes
- Claude Code responses → sent back to Telegram
- Supports: text, code blocks, bold/italic, inline keyboards
- Access control: allowlist mode locks to specific Telegram user IDs
See docs/telegram-setup.md for the full setup guide.
Three layers keep the agent alive:
- tmux session — detaches from terminal, survives SSH disconnect
- systemd user service — auto-starts on boot, restarts on crash
- watchdog cron — every 5 minutes, three checks: process alive, session age (72h proactive restart), and Telegram delivery health (detects stuck outbound channel without interrupting long tasks)
systemd (boot/crash restart)
└── tmux session "claudex"
└── claude code process
└── telegram plugin (bun subprocess)
cron (every 5 min) ──► 1. process alive?
──► 2. session age > 24h? → proactive restart
──► 3. inbound stuck > 10min AND idle? → delivery restart
Key: loginctl enable-linger $USER makes the systemd user service survive logout.
See docs/persistence.md for details and troubleshooting.
Claudex has a two-layer memory system: file-based markdown notes (simple, durable) plus a vector RAG system for semantic search across all memories and conversation history.
CLAUDE.md— permanent identity and rules (rarely changes)memory/YYYY-MM-DD.md— daily notes (decisions, tasks, context)- Claude's auto-memory — Claude Code's built-in cross-session learning
The file-based memory is supplemented by a semantic search engine (scripts/memory-search.cjs) that indexes everything into a SQLite database for hybrid search. It supports three embedding providers with automatic fallback:
- OpenAI (
text-embedding-3-small) — best quality, ~$0.02/month. Used whenOPENAI_API_KEYis set. - Ollama (
nomic-embed-text) — local, completely free. Used when Ollama is running. - TF-IDF — zero-dependency fallback, pure Node.js. No API key, no installs needed. Automatically activates when neither OpenAI nor Ollama is available.
The system auto-detects the best available provider, or you can force one:
export CLAUDEX_EMBEDDING_PROVIDER=tfidf # or openai, ollamaWhat gets indexed:
- All markdown memory files (
CLAUDE.md,memory/*.md) - Claude Code session transcripts (full conversation history from
~/.claude/projects/) - Cross-agent memories (search what other agents know — Kite, Poe, Argus, etc.)
How it works:
┌──────────────┐
User asks about → │ memory-search│ → Top N relevant chunks
past work │ .cjs │ with scores
└──────┬───────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Markdown │ │ Session │ │ Cross- │
│ Memory │ │ Trans- │ │ Agent │
│ Files │ │ cripts │ │ Memory │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└────────────┼────────────┘
▼
┌──────────────┐
│ SQLite DB │
│ + FTS5 │
│ + Embeddings│
└──────────────┘
Search is hybrid — combines three signals:
- Vector similarity (70% weight) — OpenAI
text-embedding-3-smallembeddings, cosine similarity - Full-text search (30% weight) — SQLite FTS5 with Porter stemming
- Recency decay — recent memories rank higher (60-day half-life)
Usage:
# Search across all memories
node --experimental-sqlite scripts/memory-search.cjs --search "Harkerud property business plan"
# Filter by source
node --experimental-sqlite scripts/memory-search.cjs --search "query" --source session
node --experimental-sqlite scripts/memory-search.cjs --search "query" --source cross-agent
# Filter by agent
node --experimental-sqlite scripts/memory-search.cjs --search "query" --agent kite
# Full reindex
node --experimental-sqlite scripts/memory-search.cjs --index
# Incremental reindex (only changed files)
node --experimental-sqlite scripts/memory-search.cjs --index --incremental
# Show statistics
node --experimental-sqlite scripts/memory-search.cjs --statsAutomatic indexing:
- SessionStart hook — incremental reindex every time the agent starts a new session
- Cron job — reindexes every 30 minutes to catch changes from other agents
- Embedding cache — unchanged text is never re-embedded (saves API cost)
See docs/memory-search.md for the full technical guide, including cross-agent setup, configuration, and troubleshooting.
Hooks fire at lifecycle events:
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo \"[$(date)] Session started\" >> logs/sessions.log"
}]
}],
"Stop": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo \"[$(date)] Session stopped\" >> logs/sessions.log"
}]
}]
}
}{ matcher, hooks: [{ type, command }] } structure — NOT a flat { type, command } at the top level. This was a debugging gotcha during our setup.
See docs/automation.md for scheduled tasks, /loop, and event-driven patterns.
The default settings.json ships with three hooks:
- SessionStart →
session-init.sh— logs start, checks for interrupted tasks, processes inbox, rotates logs, runs incremental memory reindex - PostToolUse → auto-stages git changes after Write/Edit operations
- Stop →
session-shutdown.sh— saves interrupted task state, records health event
For a locked-down production setup, see templates/settings.production.json.
Claudex runs bypassPermissions by default — every tool call executes without a prompt. This is deliberate, not a footgun: an always-on agent driven over Telegram has nobody at the terminal to click "yes." Any prompting mode (default, acceptEdits, plan) would freeze the session waiting for input that never arrives. Bypass is what lets Claudex act on a message the instant it lands.
The safety story for an unattended agent isn't "prompt the human" — it's:
- A
denylist that fires even in bypass mode (your real guardrail), and - A dedicated, trusted, single-user host that is not shared or internet-exposed.
Zero-click first start — two one-time gates. bypassPermissions is only prompt-free after two acceptances are recorded. scripts/bootstrap.sh pre-seeds both, so a fresh install behaves like a long-running one (this is why the maintainer never clicks, and now you won't either):
| Gate | File | Key |
|---|---|---|
| Accept bypass mode | ~/.claude/settings.json |
skipDangerousModePermissionPrompt: true |
| Trust the workspace dir | ~/.claude.json |
projects["<workspace>"].hasTrustDialogAccepted: true |
Settings files:
| File | defaultMode |
Use it when |
|---|---|---|
templates/settings.json |
bypassPermissions |
Default. The maintainer's exact setup — fully autonomous, zero prompts. |
templates/settings.json.example |
bypassPermissions |
Same, + a deny safety net + inline docs for every option. Recommended starting point. |
templates/settings.production.json |
bypassPermissions |
Bypass with a scoped allow + deny list. |
Rule precedence — deny → ask → allow, first match wins:
"permissions": {
"defaultMode": "bypassPermissions", // run everything, no prompts (headless)
"allow": ["Bash(*)", "Read(*)", "Write(*)"], // ignored under bypass; used if you switch to 'default'
"ask": [], // ignored under bypass
"deny": ["Bash(rm -rf *)", "Bash(sudo *)", "Write(/etc/*)"] // ALWAYS blocked, even in bypass
}denyalways wins — even underbypassPermissions. Because bypass ignoresallow/ask, thedenylist is the only guardrail that fires when the agent runs autonomously — so keep one.rm -rf /andrm -rf ~additionally hard-prompt as a circuit breaker.- Running attended instead? Set
defaultModetodefault(prompt on first use of each tool) oracceptEdits(auto-approve edits, prompt for other Bash); then theallow/asklists govern what runs silently vs. prompts. - Bash patterns match a prefix at a word boundary:
Bash(ls *)matchesls -labut notlsof.Bash(cmd:*)is a trailing-only alias forBash(cmd *). defaultModevalues:default,acceptEdits,plan,dontAsk(auto-deny anything not allowlisted),auto(auto-approve with safety checks — research preview),bypassPermissions.
Track agent health metrics in SQLite — session counts, restart events, uptime:
# Record events (called automatically by hooks and watchdog)
node --experimental-sqlite scripts/health-check.cjs --record session_start
node --experimental-sqlite scripts/health-check.cjs --record watchdog_ok
# View health report
node --experimental-sqlite scripts/health-check.cjs --reportOutput:
📊 Claudex Health Report
Uptime (today): 8h 30m
Sessions (today): 3
Restarts (today): 0
Restarts (7d): 1
Last session: 2026-04-13 14:22
Last restart: 2026-04-10 03:15
Avg sessions/day (30d): 4.2
Health events are recorded automatically by the lifecycle hooks (SessionStart, Stop) and watchdog cron. Use status-claudex.sh --full for a combined process + health view.
Queue tasks for the agent from cron jobs, webhooks, or manually:
# Add tasks
node scripts/inbox.cjs --add "Check email for urgent messages" --priority high --source cron
node scripts/inbox.cjs --add "Review PR #42" --priority normal --source webhook
# List pending
node scripts/inbox.cjs --list📥 Inbox (2 pending)
🔴 [a1b2c3] Check email for urgent messages (cron, 2h ago)
🟡 [d4e5f6] Review PR #42 (webhook, 30m ago)
The agent checks the inbox automatically on session start and processes pending tasks. See docs/inbox.md for the full guide.
MCP (Model Context Protocol) servers extend Claude Code with external tool access:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-filesystem", "/home/user"]
},
"github": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-github"],
"env": { "GITHUB_TOKEN": "..." }
}
}
}See docs/mcp-servers.md for recommended servers and configuration.
This system was built as an alternative to OpenClaw, replicating its autonomous agent capabilities using Claude Code. Here's an honest comparison:
| Feature | Detail |
|---|---|
| ** Cost model** | Flat $100/mo (Max subscription) vs variable API billing ($30-100+/mo). No per-token surprises. Heavy users save significantly. |
| ** Context window** | 1M tokens (Opus 4.8 via Max) vs ~200K typical API. Massive context for complex tasks. |
| ** Mobile control** | claude.ai/code Remote Control — manage from phone/browser. OpenClaw: Telegram only. |
| ** Native sub-agents** | Built-in agent teams with shared task lists and direct communication. OpenClaw: sessions_spawn with manual polling. |
| ** Skills auto-loading** | Skills auto-selected by description match. OpenClaw: manual scan of <available_skills> list. |
| ** Lifecycle hooks** | Rich hook system (SessionStart, Stop, PostToolUse, etc.). OpenClaw: limited hook support. |
| ** Scheduled tasks** | Desktop + Cloud scheduled tasks, /loop polling. OpenClaw: cron-only scheduling. |
| ** Permission modes** | Granular: default, acceptEdits, plan, dontAsk, bypassPermissions with per-tool allow/ask/deny lists. OpenClaw: binary policy. |
| ** Agent Teams** | Multi-agent coordination with shared context (experimental). OpenClaw: independent sub-agent sessions. |
| ** No infrastructure** | No gateway daemon, no config files, no port management. Just claude + workspace. |
| ** Cross-agent RAG** | Built-in cross-agent semantic search — query what Kite, Poe, or Argus know. OpenClaw: requires manual symlinks. |
| ** Health monitoring** | Built-in health metrics, uptime tracking, session counts. OpenClaw: manual monitoring only. |
| Feature | Detail |
|---|---|
| 📡 Multi-channel | Telegram, Discord, WhatsApp, Signal, Slack, iMessage, IRC, Google Chat — all native. Claudex: Telegram + Discord + iMessage only (via plugins). |
| ** Paired nodes** | Camera/screen/location control on phones and other devices. Claudex: no equivalent. |
| ** Browser control** | Dual mode: headless Playwright + live Chrome relay via extension. Claudex: Bash + Playwright only (no live browser relay). |
| ** Canvas** | Render HTML/React UIs inline in chat. Claudex: no equivalent. |
| ** ClawHub** | Skill marketplace with clawhub install/publish. Claudex: manual skill management only. |
| ** TTS** | Built-in tts tool + ElevenLabs integration. Claudex: needs MCP server or manual setup. |
| ** Heartbeat system** | Native heartbeat polling with HEARTBEAT.md. Claudex: approximated via scheduled tasks. |
| ** Always-on guarantee** | Gateway daemon designed for 24/7 uptime. Claudex: sessions can timeout, need restart infrastructure. |
| ** Image analysis** | Native image tool with vision model. Claudex: via Bash + API or MCP. |
| ** Message tool** | Rich message tool with reactions, polls, buttons, effects. Claudex: basic send/receive. |
| ** Session management** | sessions_list, sessions_send, sessions_history for cross-session communication. Claudex: independent sessions only. |
| ** Secret management** | Built-in secret/token handling. Claudex: env vars + manual management. |
| Feature | Notes |
|---|---|
| Telegram messaging | Both native, both work well. OpenClaw slightly richer (reactions, buttons, polls). |
| Skills | Both have skill systems. OpenClaw has 160 skills via ClawHub; Claudex can port them. |
| Memory & RAG | Both have vector semantic search + FTS5 hybrid. OpenClaw: built-in memory_search tool. Claudex: custom RAG engine with cross-agent search. Both index session transcripts. |
| Sub-agents | Both spawn sub-agents. OpenClaw: sessions_spawn. Claudex: built-in subagents. |
| GitHub integration | Both use gh CLI. Claudex also supports MCP GitHub server. |
| File operations | Both: Read/Write/Edit/Exec. Identical capability. |
| Web search | Both supported. OpenClaw: built-in Brave API. Claudex: MCP or Bash. |
| Systemd persistence | Both use systemd. Claudex additionally has tmux + watchdog layers. |
| Task queuing | Both can queue tasks. Claudex: inbox.json + cron. OpenClaw: HEARTBEAT.md + cron. |
Choose Claudex if: You want zero API cost, maximum context window (1M tokens), simple setup (no gateway/config), and you primarily use Telegram. Great for single-user autonomous agents.
Choose OpenClaw if: You need multi-channel support (WhatsApp, Discord, Signal, etc.), paired device control, browser relay, or the full ClawHub skill ecosystem. Better for complex multi-surface deployments.
Use both: They can coexist on the same machine — Claudex as the "always thinking" daemon with huge context, OpenClaw for its unique multi-channel and device capabilities. This is exactly what we do.
claudex/
├── README.md # You're reading it
├── LICENSE # MIT
├── CONTRIBUTING.md # Contribution guidelines
├── docs/ # Comprehensive documentation
│ ├── architecture.md # System architecture + Mermaid diagrams
│ ├── memory-search.md # Vector RAG system (setup, config, API)
│ ├── telegram-setup.md # Telegram integration step-by-step
│ ├── persistence.md # 3-layer persistence (tmux+systemd+cron)
│ ├── automation.md # Hooks, scheduled tasks, /loop
│ ├── skills-guide.md # Skill format, auto-selection, porting
│ ├── skills-catalog.md # Full catalog of all 160 skills
│ ├── subagents.md # Custom sub-agents and teams
│ ├── claude-md-guide.md # Writing an effective CLAUDE.md
│ ├── mcp-servers.md # MCP server configuration
│ ├── inbox.md # Task inbox — full guide and API
│ ├── commands-guide.md # Slash commands — anatomy + the 12 shipped
│ ├── hooks-guide.md # Lifecycle hooks — events, wiring, examples
│ ├── mcp-guide.md # MCP registry — configs + install
│ ├── plugins-guide.md # Marketplace plugins that pair with Claudex
│ └── skill-anatomy.md # SKILL.md schema — categories, maturity, tags
├── skills/ # 160 production-tested skill modules
│ ├── weather/SKILL.md
│ ├── github-workflow/SKILL.md
│ ├── memory-search/SKILL.md
│ ├── watchdog/SKILL.md
│ └── ... (160 total)
├── agents/ # Custom sub-agent definitions (9)
│ ├── researcher.md
│ ├── coder.md
│ ├── reviewer.md
│ ├── analyst.md
│ ├── sysadmin.md
│ ├── writer.md
│ ├── tester.md
│ ├── incident-responder.md
│ └── documentarian.md
├── commands/ # 12 slash commands (/audit, /ship, /recap, …)
├── hooks/ # 4 lifecycle hook scripts
├── mcp/ # MCP server registry + configs + install.sh
├── plugins/ # Recommended marketplace plugins
├── rules/ # Global behavior rules
│ ├── safety.md
│ └── telegram.md
├── templates/ # Setup templates
│ ├── CLAUDE.md.example # Annotated identity template
│ ├── settings.json # Permissions + hooks config
│ ├── settings.production.json # Locked-down production hook config
│ ├── .mcp.json.example # Example MCP server configuration
│ └── rag-config.json.example # Example RAG/embedding provider config
├── scripts/ # Management + infrastructure
│ ├── bootstrap.sh # Automated setup script
│ ├── memory-search.cjs # Vector RAG search engine (multi-provider)
│ ├── memory-reindex.sh # Cron-based incremental reindexing
│ ├── health-check.cjs # Health metrics recorder and reporter
│ ├── inbox.cjs # Task inbox — add, list, consume tasks
│ ├── session-init.sh # SessionStart hook — inbox check, reindex, log rotate
│ ├── session-shutdown.sh # Stop hook — save interrupted tasks, record health
│ ├── start-claudex.sh # Start agent (tmux)
│ ├── stop-claudex.sh # Stop agent
│ ├── restart-claudex.sh # Restart agent
│ ├── status-claudex.sh # Status check (all layers + health)
│ ├── watchdog-claudex.sh # Auto-restart watchdog
│ ├── skill-audit.sh # Audit SKILL.md frontmatter + path leaks
│ └── skill-index.sh # Generate skill-index.json + skills-catalog.md
├── systemd/ # Systemd user service
│ └── claudex.service
└── examples/ # Complete workspace example
└── workspace/ # Sanitized production workspace
~/.claude-agent/ # Agent workspace root
├── CLAUDE.md # Your agent's identity (customize this!)
├── .claude/
│ ├── settings.json # Permissions, hooks, env vars
│ ├── skills/ # 160 skill modules (copied from repo)
│ ├── agents/ # 9 sub-agent definitions
│ └── rules/ # Safety + Telegram formatting rules
├── data/
│ └── memory.sqlite # Vector RAG database (auto-created)
├── memory/ # Daily memory files
│ └── YYYY-MM-DD.md
├── logs/ # Session, watchdog, and reindex logs
├── scripts/ # Management scripts (copied from repo)
│ ├── memory-search.cjs # Vector RAG search engine
│ ├── memory-reindex.sh # Incremental reindexer
│ ├── start-claudex.sh
│ ├── stop-claudex.sh
│ ├── restart-claudex.sh
│ ├── status-claudex.sh
│ └── watchdog-claudex.sh
└── projects/ # Symlinks to your project directories
Real issues we encountered during setup, and their fixes:
Problem: If ANTHROPIC_API_KEY is set in your environment (e.g., from .bashrc), Claude Code prompts to use the API key instead of your Max subscription OAuth. This breaks autonomous restart because the prompt requires interactive confirmation.
Fix: Explicitly unset ANTHROPIC_API_KEY in your start script before launching Claude Code:
# In start-claudex.sh
unset ANTHROPIC_API_KEY
exec claude --channels plugin:telegram@claude-plugins-official ...Problem: Hooks silently fail if you use a flat structure.
// ❌ WRONG — hooks won't fire
"SessionStart": [{ "type": "command", "command": "echo hi" }]
// ✅ CORRECT — matcher + hooks array
"SessionStart": [{ "matcher": "", "hooks": [{ "type": "command", "command": "echo hi" }] }]The matcher field filters which events trigger the hook (empty string = match all).
Problem: The Telegram channel plugin (telegram@claude-plugins-official) uses Bun as its runtime, not Node.js.
Fix: Install Bun and ensure it's in PATH:
curl -fsSL https://bun.sh/install | bash
export PATH="$HOME/.bun/bin:$PATH" # add to your start scriptProblem: systemctl --user stop claudex sends SIGTERM, which kills Claude Code with exit code 143. Systemd sees this as a crash and triggers Restart=on-failure.
Workaround: Use KillMode=process and TimeoutStopSec=30 in the systemd unit. The watchdog cron is the primary restart mechanism; systemd is the backup.
Problem: Even with bypassPermissions in settings.json, the first session start requires an interactive "yes" confirmation — twice: once to accept bypass mode, once to trust the workspace folder. Fatal for a headless agent with nobody at the terminal.
Fix: scripts/bootstrap.sh now pre-seeds both acceptances, so a fresh install starts prompt-free:
| Gate | File | Key |
|---|---|---|
| Accept bypass mode | ~/.claude/settings.json |
skipDangerousModePermissionPrompt: true |
| Trust workspace dir | ~/.claude.json |
projects["<workspace>"].hasTrustDialogAccepted: true |
If you set up manually (without bootstrap), write those two keys before the first launch — see the one-liner in the Manual setup section. Then --continue resumes the session on every auto-restart. (Note: --dangerously-skip-permissions refuses to run as root/sudo outside a recognized sandbox — run as a normal user or use the dev-container config.)
Problem: Claude Code needs a TTY, but systemd doesn't provide one. Without a PTY, the process fails silently.
Fix: Use script -qc "..." /dev/null or tmux to provide a pseudo-terminal:
exec script -qc "claude --channels ... --dangerously-skip-permissions --continue" logfile.logThe Telegram channel plugin stores its access config at:
~/.claude/channels/telegram/access.json
Not in the workspace — in the user-level .claude directory. The allowlist and paired accounts live here.
Problem: If you switch embedding providers (e.g., from OpenAI to TF-IDF), existing chunks have embeddings from the old provider with different dimensions. Vector search returns 0 similarity for those chunks.
Fix: Run a full reindex after changing providers:
node --experimental-sqlite scripts/memory-search.cjs --index # full reindex (not --incremental)The system handles dimension mismatches gracefully (falls back to FTS-only scoring), but a full reindex ensures optimal search quality.
See examples/workspace/ for a sanitized version of a production Claudex setup with all components configured.
See skills/ for production-tested skills including:
weather— fetch forecasts from wttr.ingithub-workflow— full git + GitHub operationswatchdog— system health monitoringweb-monitor— URL change detection with alertssystem-admin— server management and diagnostics
See agents/ for specialized sub-agent definitions.
This system was built by @JansenAnalytics with Kite (an OpenClaw-based AI agent) as a way to replicate and extend OpenClaw's autonomous agent capabilities using Claude Code's native features.
The goal: prove that a persistent, Telegram-connected, skill-equipped, self-healing AI agent can be built entirely on Claude Code's subscription model — no custom gateway, no API billing, no infrastructure beyond a Linux box.
It works. We run both systems side by side.
Contributions welcome! Areas where help is needed:
- More skills — port your favorite OpenClaw skills or create new ones
- More channels — Discord, WhatsApp integration patterns
- Better persistence — improvements to session stability and auto-restart
- Scheduled tasks — patterns for recurring autonomous work
- MCP servers — useful server configurations
Please open an issue or PR. See CONTRIBUTING.md for guidelines.
MIT — see LICENSE.
Built with Claude Code by Anthropic. Claudex is not affiliated with or endorsed by Anthropic.