Files
Cortex-Inara/CLAUDE.md
Scott Idem 9b818aa5c7 feat: orchestrator Agent mode UI + claude_allow_dir tool + fix DDG search
- Add Agent mode toggle to web UI input row — routes through POST /orchestrate
  instead of /chat; polls for result with live tool-call count in thinking bubble
- Add cortex/tools/system.py with claude_allow_dir tool; registers in tool registry
- Fix web search: duckduckgo_search renamed to ddgs, update import + requirements.txt
- Allow WebSearch and WebFetch in ~/.claude/settings.json for Claude CLI fallback
- Add claude-allow-dir script docs and security note to CLAUDE.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 22:42:44 -04:00

8.1 KiB
Raw Blame History

CLAUDE.md — Cortex / Inara Project

This file is loaded automatically by Claude Code when working in this directory. Read it before touching any files.


Identity & Context

  • Project: Cortex (dispatcher) + Inara (resident agent)
  • Owner: Scott Idem (One Sky IT / Danger Zone)
  • Machine context: See ~/CLAUDE.md for fleet identity (scott_lpt = General Manager)
  • Named after: The 'verse-wide communications network (Firefly)

Directory Map

Cortex_and_Inara_dev/
  cortex/                ← FastAPI service (the dispatcher)
    main.py              ← App entry point, router registration
    config.py            ← All settings (pydantic-settings, reads .env)
    llm_client.py        ← Claude CLI + Gemini CLI subprocess backends
    orchestrator_engine.py ← Gemini API ReAct tool loop → Claude handoff
    context_loader.py    ← Loads Inara's system prompt from inara/ files
    session_store.py     ← In-memory + file session persistence
    session_logger.py    ← Writes session turns to inara/sessions/
    memory_distiller.py  ← Short/mid/long distill jobs (APScheduler)
    scheduler.py         ← APScheduler setup
    event_bus.py         ← Internal SSE pub/sub (NC Talk → browser)
    routers/
      chat.py            ← POST /chat (streaming SSE)
      orchestrator.py    ← POST /orchestrate, GET /orchestrate/{job_id}
      auth.py            ← GET /auth/status (Claude + Gemini CLI token checks)
      distill.py         ← POST /distill/*, GET /distill/status
      files.py           ← GET /files (inara/ file browser)
      nextcloud_talk.py  ← POST /webhook/nextcloud (NC Talk bot)
      google_chat.py     ← POST /webhook/google (Google Chat — stub)
    tools/
      __init__.py        ← Tool registry (Gemini FunctionDeclarations + dispatcher)
      web.py             ← DuckDuckGo web_search tool
      system.py          ← Local machine tools (claude_allow_dir)
    static/              ← Single-page web UI (index.html, style.css, app.js)
    data/sessions/       ← Persisted session JSON files

  inara/                 ← Inara identity, memory, context files
    IDENTITY.md          ← Who Inara is
    SOUL.md              ← Values, personality, voice
    PROTOCOLS.md         ← Behavioral rules
    CONTEXT_TIERS.md     ← What each tier (13) includes in the system prompt
    USER.md              ← Scott's profile (loaded into context)
    HELP.md              ← In-app help content (rendered in UI)
    MEMORY.md            ← Persistent facts (written by distiller or manually)
    MEMORY_SHORT.md      ← Rolling short-term memory (auto-distilled daily)
    MEMORY_MID.md        ← Mid-term memory (auto-distilled weekly)
    MEMORY_LONG.md       ← Long-term memory (auto-distilled monthly)
    sessions/            ← Session turn logs (YYYY-MM-DD_<id>.md)

  docs/                  ← Integration reference docs
    NEXTCLOUD_TALK_BOT.md

  documentation/         ← Architecture decisions and agent task list
    TODO__Agents.md      ← READ THIS FIRST — active task list
    ARCH__Intelligence_Layer.md ← Orchestrator, dev agent, knowledge architecture

  docker-compose.yml     ← Docker deployment
  .env.default           ← Reference config (copy to .env, fill in secrets)
  README.md              ← Project orientation

Run Commands

# Start (Docker)
docker compose up -d

# Restart service (after any Python change)
sudo systemctl restart cortex

# Syntax check a file before restarting
python3 -m py_compile cortex/<file>.py

# Syntax check all routers
for f in cortex/routers/*.py cortex/tools/*.py cortex/orchestrator_engine.py; do
    python3 -m py_compile "$f" && echo "OK: $f"
done

# Install/update dependencies
cd cortex && .venv/bin/pip install -r requirements.txt

# Logs
journalctl -u cortex -f

# Web UI (local)
http://localhost:8000

# Swagger docs
http://localhost:8000/docs

Key Design Decisions

Two-Brain Architecture (Orchestrator / Responder)

  • Gemini API (orchestrator_engine.py) — runs the ReAct tool loop; handles tool calling, planning, research
  • Claude CLI (llm_client.py) — produces all user-facing responses; receives enriched context from Gemini
  • Direct chat bypasses the orchestrator entirely — POST /chat goes straight to Claude (faster)
  • Orchestrated tasks go to POST /orchestrate — returns a job_id, result is polled

LLM Backends

  • llm_client.py manages Claude CLI (claude --print) and Gemini CLI (gemini -p) subprocesses
  • orchestrator_engine.py uses the Gemini API (google-genai SDK) — completely separate from the Gemini CLI
  • Claude OAuth token is read live from ~/.claude/.credentials.json (never rely on stale env var)

Tool Strategy

  • Orchestrator tools live in cortex/tools/ — separate from the ae_* MCP tools
  • Do not modify the ae_* MCP server to support orchestrator needs; add new tools to cortex/tools/ instead
  • Tools are registered in cortex/tools/__init__.py as both Gemini FunctionDeclarations and Python callables

Context / Memory

  • context_loader.py assembles Inara's system prompt from inara/ files based on tier (13)
  • Tier 1 = minimal (identity only); Tier 2 = standard (+ memory + user profile); Tier 3 = full
  • Memory files are written by the distiller or manually — do not delete them

Security / Safety

  • Never rm — move files to ~/tmp/gemini_trash
  • Never commit secrets.env is gitignored; use .env.default as the reference
  • NEXTCLOUD_TALK_BOT_SECRET and GEMINI_API_KEY live in .env only
  • Cortex should only be accessible via WireGuard — never internet-exposed without VPN

Adding a New Tool

  1. Implement the tool function in cortex/tools/<domain>.py
    • Must be async def; use asyncio.to_thread for blocking calls
    • Return a plain string result
  2. Add a FunctionDeclaration and register it in cortex/tools/__init__.py
  3. Syntax check: python3 -m py_compile cortex/tools/<domain>.py
  4. Restart Cortex

Managing Claude Code Directory Permissions

Claude Code prompts (or silently hangs) when it needs to read or write a directory outside its current working directory. The claude-allow-dir script patches ~/.claude/settings.json to add auto-allow rules so Claude no longer blocks on those paths.

Script: ~/.local/bin/claude-allow-dir

# Allow read + write (default)
claude-allow-dir ~/OSIT_dev/aether_api_fastapi

# Read-only
claude-allow-dir ~/agents_sync r

# Write-only
claude-allow-dir /tmp w

Adds Read(path/*) and/or Edit(path/*) + Write(path/*) entries to the permissions.allow array in ~/.claude/settings.json. Idempotent — safe to run twice on the same path. Changes take effect in the next Claude Code session (or after opening /hooks in the UI).

Orchestrator tool: claude_allow_dir

Cortex exposes this as a Gemini tool (cortex/tools/system.py) so the orchestrator can add allow rules on Inara's behalf without human intervention.

Security note: This tool modifies Claude Code's own permission settings. The Gemini orchestrator calling it can grant Claude access to any directory on the machine. Keep this in mind when evaluating orchestrator behavior — it should only be invoked when Scott has clearly asked for a directory to be unblocked.

Adding a New Router

  1. Create cortex/routers/<name>.py with router = APIRouter()
  2. Import and register in cortex/main.py
  3. Syntax check, restart

Active Tasks

See documentation/TODO__Agents.md for the current task list. High priority items as of 2026-03-18:

  • Ollama backend (third LLM option — local, no API cost)
  • NC Talk integration stabilization
  • Knowledge consolidation (markdown → AE Journals)

File Purpose
documentation/TODO__Agents.md Active task list — read before starting work
documentation/ARCH__Intelligence_Layer.md Full architecture design
~/agents_sync/projects/CORTEX.md High-level project vision and phases
~/agents_sync/CLAUDE.md Fleet coordination rules
~/CLAUDE.md Machine identity (scott_lpt)