agentleFS
QubinodeQubinode/qubinode_navigator/CLAUDE.md

qubinode_navigator

CLAUDE.md1 starsChanged 10 months agoMITView on GitHub

Qubinode Navigator is an AI-enhanced, container-first infrastructure automation platform for deploying OpenShift clusters, VMs, and supporting services on KVM hypervisors. It combines: Plugins implement QubiNodePlugin base class with methods: Critical rules: kcli commands - IMPORTANT: kcli requires root/sudo privileges for VM operations. Use the helper from dag_helpers.py: The prefix is controlled by:

  • Reads credentials

The file

We split this CLAUDE.md into the rules it gives an agent

5 rules. About 0 are common, 1 is distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use """ (triple double quotes) for bash_command, NEVER '''

    line 90
  2. Very specific:

    No string concatenation in bash_command

    line 93
  3. Distinctive:

    No Unicode/emoji in bash commands

    line 94
  4. Very specific:

    Use [[ over [ for conditionals

    line 196
  5. Very specific:

    Use set -euo pipefail for scripts

    line 197

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Qubinode Navigator is an AI-enhanced, container-first infrastructure automation platform for deploying OpenShift clusters, VMs, and supporting services on KVM hypervisors. It combines:

  • Airflow for workflow orchestration (DAGs)
  • AI Assistant with PydanticAI orchestrator for intent-based deployment
  • MCP Servers for LLM tool integration
  • Plugin architecture for extensible deployments

Build Commands

# Full stack deployment (recommended)
sudo -E ./scripts/development/deploy-qubinode.sh

# Airflow installation (from airflow/ directory)
cd airflow && make install    # Full: prereqs + build + start
cd airflow && make uninstall  # Stop and remove containers/volumes

# Build execution environment container
make build-image

# Install ansible-navigator
make install-ansible-navigator

# Run tests
python3 -m pytest tests/unit/
python3 -m pytest tests/integration/
python3 -m pytest tests/unit/test_rhel10_plugin.py -v

# MCP server tests
make test-mcp           # Full suite
make test-mcp-airflow   # Airflow MCP only
make test-mcp-ai        # AI Assistant MCP only

Architecture

Core Framework (core/)

  • plugin_manager.py - Plugin discovery and dependency resolution
  • config_manager.py - Configuration loading from config/plugins.yml
  • base_plugin.py - Base class for all plugins (ADR-0028 compliant)
  • event_system.py - Event bus for inter-plugin communication

Plugin System (plugins/)

Plugins implement QubiNodePlugin base class with methods:

  • _initialize_plugin(), check_state(), get_desired_state(), apply_changes()

Families:

  • plugins/os/ - RHEL 9/10, Rocky Linux 9+, CentOS Stream 9/10 (RHEL 8: legacy only)
  • plugins/cloud/ - Hetzner, Equinix
  • plugins/services/ - AI Assistant, Vault, Log Analysis
  • plugins/environments/ - Deployment contexts

Airflow Layer (airflow/)

  • dags/ - Workflow DAG definitions
  • plugins/qubinode/ - Custom operators (KcliVMCreate/Delete/List)
  • scripts/mcp_server_fastmcp.py - Primary MCP server (20+ tools)

AI Assistant (ai-assistant/)

  • FastAPI service with PydanticAI orchestrator (ADR-0063, ADR-0066)
  • Three-agent system: Manager, Developer, Observer
  • RAG-powered documentation search

Services and Ports

ServicePortPurpose
AI Assistant8080PydanticAI orchestrator + RAG
Airflow UI8888DAG management
MCP Server8889Tool API for LLM integration
PostgreSQL5432Metadata + pgvector
Marquez API5001Lineage tracking
Marquez Web3000Lineage visualization

DAG Development Standards (ADR-0045)

Critical rules:

  1. Use """ (triple double quotes) for bash_command, NEVER '''
  2. DAG IDs must be snake_case matching filename
  3. ASCII-only log prefixes: [OK], [ERROR], [WARN], [INFO], [SKIP]
  4. No string concatenation in bash_command
  5. No Unicode/emoji in bash commands
  6. Always use get_kcli_prefix() for kcli commands (see below)

kcli commands - IMPORTANT:

kcli requires root/sudo privileges for VM operations. Use the helper from dag_helpers.py:

from dag_helpers import get_ssh_conn_id, get_kcli_prefix

# Get prefix once at module level (evaluated at DAG parse time)
KCLI = get_kcli_prefix()  # Returns "sudo " or "" based on environment

# Use in SSHOperator commands (f-string required)
create_vm = SSHOperator(
    task_id="create_vm",
    ssh_conn_id=get_ssh_conn_id(),
    command=f"""
    {KCLI}kcli list vm
    {KCLI}kcli create vm myvm -i centos9stream
    {KCLI}kcli info vm myvm
    """,
    dag=dag,
)

The prefix is controlled by:

  • QUBINODE_KCLI_SUDO=true|false - Explicit control
  • Auto-detect: Uses sudo if QUBINODE_SSH_USER is not root

SSH execution pattern (ADR-0046):

bash_command="""
ssh -o StrictHostKeyChecking=no root@localhost \
    "cd /opt/kcli-pipelines && ./deploy.sh"
"""

F-string + Jinja2 + Shell Escaping Rules (CRITICAL):

DAG commands pass through THREE interpreters. Memorize these rules:

GoalIn f-stringAfter f-stringAfter Jinja2
Literal { for awk{{{{
Jinja2 param{{{{ params.x }}}}{{ params.x }}value
Shell $VAR$VAR$VAR$VAR
Shell ${VAR}${{VAR}}${VAR}${VAR}
awk $2 (double-quoted)\\$2\$2$2

Common mistakes:

# WRONG: Quadruple braces for awk - Jinja2 interprets as template
awk "{{{{print \\$2}}}}"  # -> awk "{{print \$2}}" -> Jinja2 ERROR!

# CORRECT: Double braces for awk - passes through Jinja2 unchanged
awk "{{print \\$2}}"      # -> awk "{print \$2}" -> awk "{print $2}"

# CORRECT: Quadruple braces for Jinja2 params
DOMAIN="{{{{ params.domain }}}}"  # -> DOMAIN="{{ params.domain }}" -> DOMAIN="example.com"

Use helper snippets from dag_helpers.py:

from dag_helpers import get_vm_ip_snippet, get_awk_field_snippet

# Instead of writing complex escaping manually:
command = f'''
VM_NAME="freeipa"
{get_vm_ip_snippet()}  # Handles escaping correctly
echo "IP: $IP"
'''

Validate before committing:

# Syntax check
python3 -c "import ast; ast.parse(open('airflow/dags/my_dag.py').read())"

# Import check
python3 -c "from airflow.models import DagBag; db = DagBag('airflow/dags'); print(db.import_errors)"

# Lint for ADR compliance
cd airflow && make lint-dags

Code Style

Python:

  • PEP 8 compliant
  • Type hints required
  • f-strings preferred

Bash:

  • shellcheck compliant
  • Use [[ over [ for conditionals
  • Use set -euo pipefail for scripts

Key Commands

# CLI entry point
python3 qubinode_cli.py list                    # List plugins
python3 qubinode_cli.py execute --plugins RHEL10Plugin
python3 qubinode_cli.py ask "question"          # Query AI Assistant

# Airflow DAG management (from airflow/)
make list-dags
make validate-dags
make clear-dag-cache
make clear-dag-cache-id DAG_ID=freeipa_deployment

# VM operations (requires sudo)
sudo kcli list vm
sudo kcli info vm <name>

# Service status
sudo podman ps
curl http://localhost:8080/orchestrator/status
curl http://localhost:8888/health

# Agentic Workflows (gh-aw)
gh aw list                       # List all agentic workflows
gh aw run doc-noob-tester        # Validate docs for accuracy and consistency
gh aw run daily-qa               # Run weekly QA health check on demand
# ci-doctor triggers automatically on CI failure (no manual run needed)
gh aw compile                    # Recompile after editing .md workflow files
gh aw logs <workflow-name>       # View logs from a workflow run
gh aw status                     # Check workflow status

Container Runtime

Podman is the primary runtime (RHEL-based systems). Scripts assume Podman paths and commands.

Important ADRs

ADRTopic
ADR-0001Container-first execution model
ADR-0028Plugin architecture
ADR-0036Airflow integration architecture
ADR-0045DAG development standards (CRITICAL)
ADR-0046Validation pipeline & host execution
ADR-0063PydanticAI core orchestrator
ADR-0066Developer Agent DAG validation

Sensitive Files (Never Commit)

  • .env - Credentials
  • config/vault.yml - Vault tokens
  • *.pem, *.key - Certificates
  • pull-secret.json - OpenShift pull secrets

Commit Convention

feat|fix|docs|refactor|test|chore(scope): message

# Reference ADRs when applicable
feat(dag): Add keycloak deployment DAG (ADR-0047)

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.