# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. --- ## Project Overview **Clownfischserver** is a self-hosted, AI-driven Linux server manager controlled exclusively via Telegram. The core principle: admins write naturally, the bot understands, generates commands, creates scripts, manages the server. - **Version:** v0.5.0 (in development) - **License:** GPL-3.0 - **Status:** Active Development (feature/homeip-auto-update branch) - **Core Dev:** Mehlzoerwer-Claude (Thomas Matthes) --- ## Architecture & Key Patterns ### Core Data Flow ``` Telegram User → bot.py → {ollama_client, shell.py, aider_wrapper} → Server Actions ↓ Chat-Model (gemma3) + Coder-Model (qwen2.5-coder) Fallback: OpenRouter Free (if Ollama unavailable) ``` ### Central Patterns **Multi-Distro Abstraction:** The codebase abstracts firewall & package managers: - **install.sh Step 2:** Detects `apt`/`dnf`/`pacman` → installs appropriate packages - **install.sh Step 4:** Installs firewall (`ufw` for apt, `firewalld` for dnf, manual for pacman) - **homeip-updater.sh:** Detects active firewall at runtime (`detect_firewall()` at line 18-26) → adapts rule syntax This is critical: **Any Firewall change must support all three backends** (ufw, firewalld, iptables). **Dual-Model KI Strategy:** - **Coder-Model (qwen2.5-coder:7b):** `/shell`, `/code`, command generation → requires good programming ability - **Chat-Model (gemma3:4b):** Freetext, explanations, translations → requires good German + multilingual - **Fallback:** OpenRouter free tier if Ollama times out (optional, configured in `.env`) **Telegram Safety Patterns:** - `safe_reply()` wraps all bot responses (Markdown fallback for special chars) - Long responses auto-split (Telegram 4096 char limit) - Command confirmation: `/shell` generates → `/ja` confirms → executes (no auto-exec) --- ## File Structure & Responsibilities ### `bot/` – Core Bot Logic - **bot.py** (700+ lines): Main handler, all commands, auth guard, self-update dialog - **ollama_client.py**: Dual-model manager, OpenRouter fallback, context-window config - **openrouter_client.py**: Cloud fallback (openrouter/free auto-router) - **shell.py**: Command execution (shlex.quote for safety), result capture - **aider_wrapper.py**: Code agent wrapper (--edit-format diff, 600s timeout) - **snapshot.py**: tar.gz backups, workspace tracking, package list snapshots - **boot_notify.py**: Sends Telegram message 120s after server boot (systemd oneshot) - **knock_notify.py**: Alerts on port-knock SSH access attempts ### `scripts/` – Utility Scripts (NEW in v0.5.0) - **clownfischserver-homeip-updater.sh**: Auto-update firewall rule for home IP (5-min cron) - Detects firewall type (ufw/firewalld/iptables) - Resolves myfritz DNS (dig/nslookup/getent fallbacks) - State-file tracking to skip redundant updates - **Critical:** Must work on Ubuntu/Debian/Fedora/Arch/openSUSE - **README-HOMEIP.md**: Complete homeip-updater documentation (setup, troubleshooting, firewall details) ### `install.sh` – Multi-Step Installation (900+ lines) 8-step installer with full automation: 1. **System checks** → RAM, disk, distro detection 2. **Packages** → distro-specific (apt/dnf/pacman) 3. **User setup** → custom username, passwordless sudo 4. **SSH + Firewall** → sshd_config tuning, ufw/firewalld setup, **NEW: myfritz prompt** 5. **Ollama** → download, models selection (RAM-aware defaults) 6. **Python venv** → bot + aider (separate venvs due to dependency conflicts) 7. **Telegram bot** → BotFather token, chat-ID, optional OpenRouter key 8. **Systemd** → clownfisch service + boot-notification service, **NEW: cron-job for homeip-updater** **Key Pattern:** `install.sh` runs **as root** and manages root-level resources. The homeip-updater cron-job runs as root (for firewall access). ### Configuration & Data - **config/.env** → All secrets, model choices, paths (generated by install.sh, permissions 0600) - **config/.env.example** → Template (must be kept in sync with install.sh additions) - **config/knockd.conf** → Port-knocking rules (7000→8000→9000) - **systemd/clownfisch.service** → Bot service (User patched dynamically from MGMT_USER) - **systemd/clownfisch-boot.service** → Boot notification (oneshot, 120s delay) --- ## Critical Design Decisions ### 1. Firewall Abstraction (New in v0.5.0) The homeip-updater.sh demonstrates the new **multi-firewall abstraction pattern**: ```bash detect_firewall() { systemctl is-active ufw → use: ufw allow from X port 22 systemctl is-active firewalld → use: firewall-cmd rich-rule command -v iptables → use: iptables -I INPUT } ``` **Why this matters:** When adding firewall-dependent features, always implement for all three. This is not optional. ### 2. No Interactive Commands in /shell The `/shell` command uses a "non-interactive only" prompt. Why? - **Cron-friendly:** homeip-updater runs in cron, can't wait for user input - **Safety:** No `nano`, `vim`, `crontab -e` (can't pipe credentials) - **Pattern:** UFW delete needs `echo "y" |` confirmation (line 81 in homeip-updater.sh) ### 3. .env Parsing Robustness Variable loading must handle CRLF (Windows git clones): ```bash MYFRITZ_DOMAIN=$(grep "^VAR=" .env | cut -d= -f2 | tr -d '\r\n') ``` This trims trailing newlines/carriage returns. Critical for .env variables used in firewall rules. ### 4. State File Tracking in homeip-updater The `/var/lib/clownfischserver-homeip-state` file prevents redundant UFW updates: - If DNS resolves to same IP → skip rule updates (idempotent) - If IP changed → remove old rule, add new rule - Logging includes old IP vs new IP for audit trail This is important because UFW rule deletion prompts interactively (hence the `echo "y" |` workaround). ### 5. Package Dependency Management - **dnsutils** must be in apt install (Step 2) for `dig` command - **firewalld** installed for dnf systems (handled in Step 4) - **iptables** assumed on pacman (Arch) systems - The homeip-updater has DNS fallbacks: dig → nslookup → getent (lines 43-52) --- ## Development Workflow ### Testing on Multiple Distros The project must work on: - **Ubuntu/Debian** (primary, uses ufw) - **Fedora/RHEL** (uses firewalld) - **Arch/Manjaro** (uses iptables/nftables) - **openSUSE** (uses firewalld) **Recommended setup (from project notes):** - Pop!_OS on laptop → development & editing - Homlab VMs (Arch, openSUSE) → local testing of install.sh + homeip-updater - VPS Server (Ubuntu) → real-world myfritz testing ### Bash Script Syntax Check ```bash bash -n install.sh bash -n scripts/clownfischserver-homeip-updater.sh ``` Run before commits. CRLF warnings are harmless (Windows git clones), but scripts must be syntactically valid. ### Python Syntax Check ```bash python3 -m py_compile bot/*.py ``` ### Testing Firewall Rules **ufw (Ubuntu/Debian):** ```bash ufw status numbered ufw allow from 192.168.1.100 to any port 22 comment "test" echo "y" | ufw delete allow from 192.168.1.100 to any port 22 ``` **firewalld (Fedora/openSUSE):** ```bash firewall-cmd --list-all firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.100' port protocol='tcp' port='22' accept" firewall-cmd --reload ``` **iptables (Arch):** ```bash iptables -L INPUT -n iptables -I INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT iptables -D INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT ``` --- ## Git Workflow & Policies ### Push Policy **Maximum 4 pushes per hour** (one every ~15 minutes). This is documented in `memory/feedback_github_policy.md`. **Why:** Reduces GitHub notification spam, allows batching commits logically, leaves review time between updates. ### Branch Strategy - **main:** Stable releases only (v0.4.13, v0.5.0, etc.) - **feature/*** → PR reviewed → merged to main after testing - Current: `feature/homeip-auto-update` (v0.5.0 preparation) ### Commit Message Style ``` : – <Subtitle if complex> Details paragraph (optional, multi-line OK) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> ``` Examples: - `v0.5.0 – Clownfischserver HomeIP Auto-Update: myfritz Automatik für SSH (5-Min Cron)` - `Bugfix: Clownfischserver HomeIP Updater – Fehlerbehandlung & Fallbacks` - `Feature: Multi-Distro Firewall-Support für HomeIP Updater` --- ## Important Gotchas & Caveats ### 1. iptables Persistence on Arch The homeip-updater uses `iptables -I INPUT` to add rules. On some systems, these don't persist after reboot. **Future enhancement:** integrate with `iptables-persistent` or `nftables` for persistence. Current status: evaluating. ### 2. Firewall Rule Comments UFW and firewalld support rule comments (`comment "..."`) for tracking. **iptables does not.** This makes tracking which rules were added by clownfischserver harder on Arch. Document this if implementing rule deletion on iptables. ### 3. systemd Service User Patching The MGMT_USER (arbitrary username) must be patched into systemd service files during installation. This uses regex: `User=\S+` (line 822 in install.sh). If systemd syntax changes, update regex. ### 4. Ollama Model Download Brittleness `ollama pull` can hang or timeout. The installer includes progress bars but no retry logic. Users on slow/intermittent connections may need manual intervention. ### 5. .env Variable Escaping Variables like `CLOWNFISCHSERVER_HOME_IP_DOMAIN=vorname.myfritz.net` are read with `grep` and `cut`. They must not contain `=` characters. Document constraints in `.env.example`. --- ## Code Patterns to Follow ### Safe Telegram Replies Always use `safe_reply()` wrapper (bot.py). Never call `send_message()` directly. ### Async Telegram Handlers All message handlers must be `async def`. Use `@app.message_handler()` decorator pattern from existing code. ### Shell Command Safety Use `shlex.quote()` for untrusted user input in shell.py. Example: ```python cmd = f"rm {shlex.quote(user_path)}" ``` ### Firewall Rule Matching When detecting or modifying firewall rules, match exact patterns to avoid false positives: - UFW: `"22.*ALLOW.*FROM\s+$IP"` (line 79, homeip-updater.sh) - firewalld: exact rule with family + port + protocol - iptables: exact `-s $IP -p tcp --dport 22` match --- ## Memory & Context Files For other Claude instances working on this project: - **project_status_v05.md** – Current v0.5.0 status, tested scenarios, known limitations - **feedback_github_policy.md** – Push frequency policy, batching rules These are in `.claude/projects/.../memory/`. They provide context for continued development. --- ## Key References - **CLOWNFISCHSERVER.md** – Detailed project context (architecture, .env variables, roadmap) - **README.md** – User-facing documentation - **scripts/README-HOMEIP.md** – Complete homeip-updater guide - **CONTRIBUTING.md** – Contribution guidelines (already aligned with multi-distro goals) --- ## Quick Commands ```bash # Syntax check bash -n install.sh python3 -m py_compile bot/*.py # Test homeip-updater (dry-run, logs to stdout) bash -x scripts/clownfischserver-homeip-updater.sh # Check git status git status git log --oneline -5 # Build release ZIP (from install.sh docs) cd .. && zip -r v0.5.0-clownfischserver.zip clownfischserver/ -x "*__pycache__*" "*.pyc" ".git/*" ``` --- **Last Updated:** 2026-05-01 (v0.5.0 HomeIP Feature) **Next Version:** v0.5.0 (pending VPS/VM testing, then merge to main)