Files
clownfischserver/CLAUDE.md
T
mehlzoerwerandClaude Haiku 4.5 5c1f56a60e Docs: CLAUDE.md für zukünftige Claude-Instanzen
Context für nachfolgende Entwicklung:
- Architektur & Multi-Distro/Firewall-Patterns
- Dateistruktur & Responsibilities
- Critical Design Decisions (iptables Persistierung, .env Parsing)
- Development Workflow (Ubuntu/Fedora/Arch Testing)
- Git Policies (4 pushes/hour)
- Code Patterns & Gotchas
- Quick Reference Commands

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-02 00:00:50 +02:00

11 KiB
Raw Blame History

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:

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):

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 -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

python3 -m py_compile bot/*.py

Testing Firewall Rules

ufw (Ubuntu/Debian):

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):

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):

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

<Type>: <Title> – <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:

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

# 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)