01 Technology Stack
Every component chosen for reliability, speed, and simplicity of operation on the Nanic server.
| Layer | Technology | Why | Tag |
| Telegram Interface |
python-telegram-bot 21.x |
Latest async PTB, built-in JobQueue (APScheduler), excellent group support |
Core |
| AI Backend |
Claude Code CLI (subprocess) |
User specified OAuth token approach; full tool use, file access, server control |
Core |
| Claude Model |
claude-sonnet-4-6 |
Best balance of intelligence and speed for group chat responses |
Core |
| Auth |
CLAUDE_CODE_OAUTH_TOKEN |
Long-lived token from ~/.claude/.credentials.json (re-authed April 2026) |
Auth |
| Primary DB |
PostgreSQL 16 |
Sessions, memory metadata, business data, message log — all persistent |
Data |
| Session Cache |
SQLite (local file) |
Ultra-fast session_id lookups without network overhead; file in /app/data/ |
Data |
| Memory Files |
Markdown files + MEMORY.md index |
Same pattern as ragul-bot; Claude reads/writes its own memory. Survives container restart via volume |
Memory |
| Scheduler |
APScheduler (via PTB JobQueue) |
Built into python-telegram-bot — zero extra dependency for daily briefing |
Jobs |
| Media Handling |
aiohttp + filesystem |
Download to /tmp/nanic_bot/{msg_id}/, tell Claude the path — uses its file tools |
Media |
| Deployment |
Docker Compose |
Isolated, restartable, mountable — matches existing Nanic server pattern |
Deploy |
02 System Architecture
Five-layer design from Telegram message to server action.
┌─────────────────────────────────────────────────────────────────┐
│ TELEGRAM LAYER │
│ GroupMessageHandler │ CallbackHandler │ CommandHandler │
│ [group/supergroup only — DMs silently dropped] │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ ORCHESTRATION LAYER │
│ ChatQueue (asyncio.Queue per chat_id — serial, no overlap) │
│ MediaProcessor │ TypewriterEffect │ IntentParser │ RateGuard │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ CLAUDE INTEGRATION LAYER │
│ ClaudeBridge → subprocess → --print --output-format stream-json │
│ SessionManager │ ContextBuilder │ MemoryInjector │ TokenGuard │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ PERSISTENCE LAYER │
│ PostgreSQL: sessions │ memory_meta │ business_data │ msg_log │
│ SQLite: fast session_id cache │
│ Files: /app/data/memory/*.md (MEMORY.md index) │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ SERVER CONTROL LAYER │
│ Workspace: /home/nanic (full mount) │
│ Docker: /var/run/docker.sock │
│ Claude: --dangerously-skip-permissions, cwd=/home/nanic │
└─────────────────────────────────────────────────────────────────┘
03 Project File Structure
Modular, production-grade layout. Each module has one clear responsibility.
/home/nanic/Bot/
├── handlers/
│ ├── group.py
│ ├── callback.py
│ └── commands.py
├── claude/
│ ├── bridge.py
│ ├── session.py
│ └── context.py
├── memory/
│ └── manager.py
├── db/
│ └── database.py
├── jobs/
│ └── briefing.py
├── utils/
│ ├── formatters.py
│ ├── media.py
│ └── queue.py
├── docs/
│ └── plan.html
├── bot.py
├── CLAUDE.md
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── entrypoint.sh
└── .env
# Docker volumes (persistent)
04 Message Flow
Every message follows this exact path. Non-streaming by design — wait for full response.
1
Receive & Filter
Message arrives from Telegram. Check chat.type — if private or channel, silently drop. Rate-check: max 5 msgs/min per user. Add to ChatQueue[chat_id].
↓
2
Show Thinking Indicator
Send typing action + a "🤔 Thinking..." reply message. This appears instantly, before Claude is called. Gives immediate feedback to the group.
↓
3
Prepare Context
Load session_id from SQLite. Download media to /tmp/nanic_bot/{msg_id}/. Build message string: "[Username]: {text}\n[Image: /tmp/...jpg]". Inject recent memory from MEMORY.md. Build system prompt.
↓
4
Call Claude (Blocking)
Run claude --print --output-format stream-json --model claude-sonnet-4-6 --dangerously-skip-permissions --resume <session_id> -- <message> as subprocess. Collect ALL output. Parse stream-json events. Wait up to 5 minutes. Extract response text + new session_id.
↓
5
Parse & Save
Parse [REMEMBER: ...] tags → save to MEMORY.md. Save new session_id to SQLite. Log message to PostgreSQL. Strip internal tags from response text.
↓
6
Send Response + Refresh Button
Delete the "🤔 Thinking..." message. Send the actual response as a new message. Attach a "🔄 Refresh" inline button. After 30 seconds, the button auto-removes (asyncio.sleep task).
↓
7
On Refresh Click
Edit the message to show "🔄 Refreshing...". Re-run Claude with the same original query (stored in callback data). Replace message content with new response. New 30s refresh window starts.
05 Memory & Session System
Context survives restarts. Claude builds its own memory over time.
Session Continuity
One shared session_id per group chat. Stored in SQLite for fast access. Claude resumes via --resume flag — the full conversation context is preserved in Claude's internal state.
Sessions expire after 8 hours of inactivity. On new session: injects last 5 memories as context.
File-Based Memory
Claude writes [REMEMBER: fact] tags in responses. The bot parses these and saves to /app/data/memory/ as individual .md files with frontmatter. MEMORY.md is the index.
On each new session, the top 5 relevant memories are injected into the system prompt.
Business Data (PostgreSQL)
Structured tables for: revenue logs, task lists, product catalog, customer notes. Claude can read/write via SQL commands.
Used for the daily briefing (yesterday's revenue, pending tasks).
Memory Tags
Claude uses inline tags to self-manage memory:
[REMEMBER: fact to save]
[GOAL: task | DEADLINE: date]
[DONE: completed task]
[TOPIC: current topic]
Tags are stripped from the final response before sending.
06 Daily Morning Briefing
Auto-sent to the group at 7:30 AM IST every day. Claude generates fresh content each morning.
🌿 Good morning, Nanic Ayurveda team! Here's your April 18 briefing:
📊 Yesterday's Summary
Revenue: ₹12,840 from 23 orders
Top seller: Ashwagandha Capsules (8 units)
New customers: 4 | Returns: 0
🌱 Ayurveda Tip of the Day
Focus on Chyawanprash for summer promotions — it's high in Vitamin C via Amla and perfectly aligns with immunity trends. Bundle with Giloy for a bestseller combo.
📋 Today's Plan
→ Follow up with 3 pending wholesale inquiries
→ Restock Triphala Churna (stock at 12 units, threshold: 20)
→ Update Instagram with new product photos
🐳 Server Health
All 5 Nanic containers: ✅ healthy
Disk: 62GB free / 97GB
nanic_frontend: Up 6 days
Technical Implementation
Trigger: APScheduler via python-telegram-bot's JobQueue. Runs at 02:00 UTC (= 7:30 AM IST) every day.
What it does: Calls Claude with: "Generate today's morning briefing. Read the revenue log from PostgreSQL, check Docker container health, pull pending tasks from memory, and give one actionable Ayurveda business tip for today."
Claude's actions: Runs server commands (docker ps, psql query), reads memory files, generates the brief. Sends to the registered GROUP_CHAT_ID.
Persistence: Works after restart — job is re-registered on bot startup.
07 System Prompt & CLAUDE.md Design
The identity, knowledge base, and guardrails that shape every response.
You are the Nanic Ayurveda Bot — the complete business brain and operational backbone of Nanic Ayurveda.
You work inside a Telegram group with the core Nanic team. Your job is to assist with EVERYTHING — no request is out of scope. You act like a trusted, highly capable team member who gets things done without being asked twice.
═══ IDENTITY ═══
Business: Nanic Ayurveda — an Ayurveda product brand
Role: Autonomous business brain, server manager, advisor
Server: 88.222.214.65, workspace at /home/nanic
Current user: {username} (in group with others)
Time: {current_time} IST
═══ WHAT YOU KNOW ═══
• Ayurveda knowledge: herbs, formulations, dosages, contraindications, seasonal recommendations
• Business operations: pricing, inventory, promotions, customer handling
• Server infrastructure: see CLAUDE.md for full container list and architecture
• Can run shell commands, manage Docker, edit files, create static sites
═══ HOW YOU WORK ═══
• Do things first, explain after — don't ask for permission on reversible actions
• For irreversible actions (delete database, stop production service): confirm once, then act
• When someone asks a question, answer it directly AND proactively add what they should know
• Remember things with [REMEMBER: fact] tags — these get saved to memory
• Respond in the same language the user writes in (English / Tamil)
═══ PERSONALITY ═══
• Like a sharp, knowledgeable younger sibling who runs the whole business backend
• Direct, helpful, zero corporate filler
• Proactively flag risks, low stock, missed tasks, stalled projects
═══ GUARDRAILS ═══
• Never expose passwords, tokens, or credentials in chat
• Never drop databases or delete production data without explicit confirmation
• Rate limit: if same request in last 60s, acknowledge and skip
• Group only — you are not available via DM (already enforced at code level)
═══ MEMORY ═══
[See injected memory below from previous sessions]
{memory_context}
08 CLAUDE.md — Server Context
Auto-injected into every Claude session. Gives Claude full awareness of the Nanic server.
# CLAUDE.md — Nanic Server Context
## Server Identity
- Host: 88.222.214.65 | OS: Ubuntu 22.04
- User: nanic | Workspace: /home/nanic
- Role: This is the Nanic Ayurveda production server
## Running Docker Containers
- nanic_frontend (6040→3000) → Nanic Ayurveda website frontend
- nanic_backend (6030→4000) → Nanic backend API
- nanic_postgres (6010→5432) → Main Nanic PostgreSQL DB
- nanic_redis (6020→6379) → Nanic Redis cache
- nanic_pgadmin (6050→80) → PGAdmin UI
- nanic_dozzle (6060→8080) → Docker log viewer
- nanic-bot-db (6070→5432) → This bot's PostgreSQL DB (new)
- nanic-bot-docs (8898→80) → This plan site (nginx)
- blood-frontend (5080→80) → Blood management frontend
- blood-backend (5070→3000) → Blood management API
- blood-postgres (5050→5432) → Blood DB
- blood-redis (5060→6379) → Blood Redis
- blood-pgadmin (5090→80) → Blood PGAdmin
- nextcloud (4038→80) → Internal file storage
- nextcloud-db (4039→5432) → Nextcloud DB
- nextcloud-redis (4040→6379) → Nextcloud Redis
- expense-bot (3050→3050) → Expense tracking bot (DO NOT MODIFY)
- expense-web (3049→3049) → Expense web UI (DO NOT MODIFY)
- gitea (3000→3000) → Internal Git server (SSH: 222→22)
- jenkins (3001→8080) → CI/CD (agent: 50000)
- nginx-proxy-manager (80/443→80/443, 127.0.0.1:81→81) → Reverse proxy
## Key Paths
- /home/nanic/Projects/website/dev → Nanic website code
- /home/nanic/Projects/BRMS → Business management system
- /home/nanic/Projects/nginx → Nginx proxy manager
- /home/nanic/Bot → THIS BOT
## How to Manage Static Sites
1. Place HTML in /home/nanic/Bot/docs/
2. Access via bot-docs nginx on port 6085
3. Or use nginx-proxy-manager admin at localhost:81 to add domain routing
## How to Manage Docker
- View logs: docker logs <name> -f --tail=100
- Restart: docker restart <name>
- Rebuild: cd /home/nanic/Projects/<project> && docker compose up -d --build
## Business Context
- Business: Nanic Ayurveda — Ayurvedic product brand
- Products: Ashwagandha, Triphala, Giloy, Chyawanprash, Brahmi, Neem, Turmeric formulations
- Operations: Online + wholesale, Instagram/social media presence
- Inventory threshold alerts: < 20 units = restock needed
09 Security & Guardrails
Built-in at both the bot layer and the Claude prompt layer.
🔒
DM Blocking: Any message where chat.type == "private" is silently dropped at the handler level. No response, no error. Bots can't be abused via DMs.
⏱️
Rate Limiting: Max 5 messages per user per minute in the group. Beyond that, they get a "⏳ Slow down" reply. Prevents API abuse and runaway Claude calls.
🛡️
Destructive Operation Guard: Claude's system prompt instructs it to confirm before: dropping databases, deleting files, stopping production services, removing Docker volumes. One confirmation required.
🔑
Credential Safety: Claude is instructed never to output passwords, API keys, or tokens in the Telegram chat. Logs are sanitized before being shown.
⏳
Response Timeout: Claude subprocess has a 5-minute hard timeout. On timeout, user receives: "⚠️ That took too long. Try a simpler request or split it into parts."
🐳
Docker Access Scoping: Docker socket is mounted read-only by default. Write access (restart/rebuild) requires explicit enable in compose. Claude uses docker logs freely but pauses on destructive compose commands.
📝
Audit Log: Every message + Claude response is logged to PostgreSQL with timestamp, user_id, username, chat_id, cost. Full audit trail.
10 Deployment Architecture
Docker Compose with host networking for full server access. Three services: bot, db, docs.
services:
bot:
build: .
container_name: nanic-ayurveda-bot
restart: unless-stopped
network_mode: host
volumes:
- /home/nanic:/home/nanic
- /var/run/docker.sock:/var/run/docker.sock
- /home/nanic/.claude:/home/nanic/.claude
- bot_data:/app/data
env_file: .env
environment:
HOME: /home/nanic
WORKSPACE_DIR: /home/nanic
depends_on:
db: {condition: service_healthy}
db:
image: postgres:16-alpine
container_name: nanic-bot-db
restart: unless-stopped
ports: ["6070:5432"]
environment:
POSTGRES_DB: nanic_bot
POSTGRES_USER: nanic_bot
POSTGRES_PASSWORD: NanicBot@2026
volumes: [pgdata:/var/lib/postgresql/data]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U nanic_bot"]
interval: 5s; timeout: 5s; retries: 5
docs:
image: nginx:alpine
container_name: nanic-bot-docs
restart: unless-stopped
ports: ["6085:80"]
volumes: [./docs:/usr/share/nginx/html:ro]
volumes:
pgdata:
bot_data:
Environment Variables (.env)
TELEGRAM_BOT_TOKEN=8247821796:AAH...
TELEGRAM_GROUP_ID=-100xxxxxxxxx
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-...
CLAUDE_MODEL=claude-sonnet-4-6
WORKSPACE_DIR=/home/nanic
DB_HOST=127.0.0.1
DB_PORT=6070
DB_NAME=nanic_bot
DB_USER=nanic_bot
DB_PASSWORD=NanicBot@2026
MORNING_BRIEF_HOUR=2
MORNING_BRIEF_MINUTE=0
SESSION_TIMEOUT_HOURS=8
RATE_LIMIT_PER_MINUTE=5
MAX_RESPONSE_TIMEOUT=300
Dockerfile
FROM python:3.11-slim
# Install Node.js 20 + Claude CLI
RUN curl -fsSL nodesource.com/setup_20.x | bash -
RUN apt-get install -y nodejs && npm install -g @anthropic-ai/claude-code
# Python deps
COPY requirements.txt .
RUN pip install -r requirements.txt
WORKDIR /app
COPY . .
RUN mkdir -p /app/data/memory
CMD ["python", "bot.py"]
11 Development Phases
Build in order. Each phase is independently deployable and testable.
1
Phase 1 — Core Bot (Foundation)
Get the bot talking with Claude in the group. Everything else builds on this.
- Dockerfile + docker-compose.yml (bot + db + docs)
- bot.py with group-only filter and DM blocking
- claude/bridge.py — subprocess, stream-json collect, parse
- "🤔 Thinking..." → response → "🔄 Refresh" (30s) flow
- SQLite session management with --resume
- db/database.py — asyncpg, create tables
- Basic .env, CLAUDE.md, entrypoint.sh
2
Phase 2 — Memory & Context
Claude remembers things across sessions. Business knowledge accumulates over time.
- memory/manager.py — MEMORY.md index + [REMEMBER] tag parsing
- Top 5 relevant memories injected into every session prompt
- Session expiry (8h) + context bridging on new session
- claude/context.py — dynamic system prompt builder with time, user, memory
- Log all messages + Claude responses to PostgreSQL (audit)
3
Phase 3 — Media & Commands
Handle images, documents. Add slash commands for power users.
- utils/media.py — download photo/doc to /tmp/, tell Claude the path
- handlers/group.py — photo handler, document handler
- /status — show bot health, current session, memory count
- /reset — clear current session (fresh context)
- /memory — list recent memories saved by Claude
- Message splitting for responses > 4096 chars
4
Phase 4 — Daily Briefing & Scheduler
Autonomous morning intelligence. Bot becomes proactive, not just reactive.
- jobs/briefing.py — APScheduler job at 02:00 UTC (7:30 AM IST)
- Claude checks Docker health, reads PostgreSQL revenue log, reads memory for tasks
- Generates formatted morning brief + sends to GROUP_CHAT_ID
- Revenue entry command: members can log sales (Claude parses, saves to DB)
- Task tracking: "add task: restock Triphala" → Claude saves, appears in briefing
5
Phase 5 — Polish & Hardening
Production-ready. Rate limiting, error handling, monitoring.
- Rate limiting (5 msgs/min per user) with graceful message
- Claude token auto-refresh (check expiry before each call)
- Graceful shutdown — finish current request before stopping
- Error messages that are actually helpful to non-technical users
- Optional: weekly revenue report on Sundays
- Telegram group ID auto-detection (log first group message)
12 Complete Feature List
Everything the bot will do out of the box.
🤖 AI Responses
Answers anything: product advice, business decisions, Ayurveda knowledge, technical tasks, creative writing, planning. Claude Sonnet 4.6 with full tool access.
🖼️ Image Analysis
Send product photos, prescriptions, receipts, screenshots. Claude analyzes them via file path (downloads to /tmp). Works for OCR, quality checks, description generation.
🐳 Server Management
Ask "restart the frontend" or "show me backend logs" — Claude runs docker commands via --dangerously-skip-permissions on the mounted server.
🌐 Static Sites
Ask Claude to create a product page, landing page, or any HTML. It writes to /home/nanic/Bot/docs/ and it's live immediately at port 6085.
🌅 Daily Briefing
7:30 AM IST — revenue summary, Ayurveda business tip, today's tasks, server health. Fully automated every morning.
🧠 Persistent Memory
Claude remembers product prices, customer preferences, team decisions, anything it's told. Memory survives restarts. Grows smarter over time.
📋 Task Tracking
"Add task: update website pricing" → saved. Appears in next morning briefing. Mark done: "done: update website pricing."
💬 Group-Native
Responds to all messages in the group. Aware of who's talking (username context). DMs are completely ignored. No allowlist — entire group team can use it.
🔄 Refresh Button
Not happy with the response? Click 🔄 within 30 seconds to regenerate. Claude re-runs the same request with a fresh perspective.
Nanic Ayurveda Bot — Development Plan v1.0
Generated: April 18, 2026 | Deployed: http://88.222.214.65:6085/plan.html