# iEvo

Self-evolving AI agent framework — interactive console tool.

## Interactive model

iEvo is an **interactive console tool** like Claude Code itself — not a set of separate CLI commands. The primary interface is the **Textual TUI** (must-have).

```
ievo (start)
  ├── Textual TUI — interactive dashboard (agents, pipeline, evolution, files)
  ├── Generate session ID
  ├── Check Claude auth → if missing, prompt login → save to config
  ├── Telemetry opt-in (first run) → Sentry + evolution sharing
  └── When Claude needed → Docker sandbox starts interactively
      ├── Full native Claude Code access preserved (user is NOT limited)
      ├── iEvo orchestration layered on top (agents, teams, tools)
      ├── .claude/ mounted for session persistence + hooks
      └── Session ID passed for continuity (--resume)
```

Key principle: **preserve full native Claude Code access + add orchestration on top**. Never limit what the user can do with Claude.

## Project

- **Name**: ievo
- **Language**: Python 3.13+
- **Framework**: Typer + Rich + Textual (TUI)
- **Package manager**: uv (hatchling build)
- **Entry point**: `ievo` → TUI dashboard | `ievo <cmd>` → CLI

## Architecture

```
src/ievo/
├── cli.py              # Typer app, registers all commands
├── commands/           # One file per command group
│   ├── init.py         # ievo init — project scaffold
│   ├── add.py          # ievo add — install from marketplace
│   ├── remove.py       # ievo remove
│   ├── update.py       # ievo update
│   ├── list_cmd.py     # ievo list
│   ├── run.py          # ievo run — launches Claude session
│   ├── team.py         # ievo team (Phase 2)
│   ├── learn.py        # ievo learn log/push/status — EVO
│   └── dev.py          # ievo dev new/test/publish
├── core/               # Business logic
│   ├── config.py       # Paths, URLs, project root detection
│   ├── project.py      # .ievo/manifest.yaml manifest model
│   ├── agent.py        # agent.yaml model (AgentPackage, SandboxConfig)
│   ├── docker.py       # Docker sandbox (check, build, command builder)
│   └── registry.py     # Marketplace registry (fetch, cache, download)
├── tui/                # Textual TUI dashboard (must-have)
│   └── app.py          # IevoApp: agents table, pipeline, evo log, file tree
└── utils/
    └── console.py      # Rich theme, success/error/info helpers
```

## Data map — what iEvo saves

### Global (`~/.ievo/`)

| File | Purpose |
|------|---------|
| `config.json` | default_model, marketplace_url, github_auth, telemetry opt-in |
| `credentials.enc` | encrypted secrets (RSA + AES-256-GCM) |
| `ievo_key` / `ievo_key.pub` | RSA key pair (generated on first init) |
| `cache/registry.yaml` | marketplace registry cache |

### Project (`./.ievo/`)

| File | Purpose |
|------|---------|
| `.ievo/manifest.yaml` | project manifest (name, version, agents, overrides) |
| `.claude/settings.local.json` | Claude Code hooks config (PreCompact → claude-mem) |
| `.claude/hooks/precompact_save.py` | session observation extractor → SQLite |
| `spec/` | SDD specs (requirements, changes, questions, templates) |
| `plans/` | architecture plans (PLAN-REQ-xxx.md) |
| `agents/` | installed agents directory |
| `.github/workflows/` | CI/CD for spec-writer, architect, coder agents |

### Per-Agent (`./agents/<name>/`)

| File | Purpose |
|------|---------|
| `agent.yaml` | manifest (model, sandbox config, tools, hooks, deps, disclosure) |
| `ROLE.md` | system prompt (loaded as `--system-prompt`) |
| `EVOLUTION_LOG.md` | self-evolution history (errors → lessons) |
| `memory/CONTEXT.md` | persistent context across sessions |
| `memory/DECISIONS.md` | architectural decisions log |
| `memory/VOCABULARY.md` | domain-specific terms |
| `memory/HISTORY.md` | session history index with Status column |
| `memory/sessions/NNN/plan.md` | session plan (goals, steps) |
| `memory/sessions/NNN/log.md` | session log (what happened, commits, errors) |

## Session journal convention

Same convention as Eva. Every agent maintains a session journal.

**Structure:**
```
agents/<name>/memory/
  HISTORY.md              ← index with STATUS column
  sessions/
    001/
      plan.md             ← session plan (written when plan is approved)
      log.md              ← session log (written during/after session)
    002/
      plan.md
      log.md
```

**HISTORY.md format:**
```
| # | Date | Topic | Status | Key outcome |
|---|------|-------|--------|-------------|
```

Statuses: `planned` → `in_progress` → `completed`

**Session plan (`plan.md`)**: written as soon as the plan is approved, BEFORE starting implementation. Contains: goals, phases, steps, decisions to make.

**Session log (`log.md`)**: written during and after the session. Things change during implementation — the log captures what actually happened. Contains: what was built, commits, errors, pending items.

**Session plan = first priority**: as soon as a plan is approved, IMMEDIATELY save it. Update throughout the session. If the session crashes with a stale plan, recovery is blocked.

### Project-level sessions (future)

```
.ievo/
  sessions/
    <session-id>/
      meta.yaml           ← session metadata (id, start time, agents used, model)
      log.md              ← session log (auto-generated from Claude transcript)
```

## Startup data flow

```
ievo (first run)
  ├── Generate session ID (UUID)
  ├── Check ~/.ievo/config.json for Claude auth
  │   └── If missing: run `claude auth` → save token
  ├── Check telemetry opt-in (first run only)
  │   └── "Help improve iEvo?" → save to config.json
  │       ├── Yes: enable Sentry (hardcoded DSN), enable evolution sharing
  │       └── No: local-only mode
  ├── Start Docker sandbox (if agents require it)
  │   ├── Mount project → /workspace
  │   ├── Mount .claude/ → /workspace/.claude  (session persistence)
  │   ├── Pass CLAUDE_CODE_OAUTH_TOKEN
  │   └── Pass --resume <session-id> for continuity
  └── Transparent Claude Code session with agents loaded
```

Sentry DSN (hardcoded): `https://09d4c54e8ac3b9cc79efea50bf635efb@o4510962988482560.ingest.us.sentry.io/4510963845758976`

## Key patterns

- **Project detection**: `find_project_root()` walks up looking for `.ievo/manifest.yaml`
- **Registry**: cached at `~/.ievo/cache/registry.yaml`, fetched from GitHub raw
- **Agent install**: downloads from marketplace or creates local scaffold
- **Run**: Docker sandbox by default, `--local` for direct Claude CLI. Builds command with ROLE.md as system prompt + memory files + `--allowedTools`
- **Docker sandbox**: agents run in `ievoai/sandbox:latest` container with project as volume mount. Tool-level isolation via `--allowedTools` (not `--network none` — Claude needs API access). Auto-builds image if missing
- **TUI**: `ievo` without args launches Textual dashboard (must-have, 4 tabs: Agents, Pipeline, Evolution, Files)
- **Async**: registry fetch/download use httpx async

## Commands reference

```bash
# Project lifecycle
ievo init [name]                    # Create .ievo/, spec/, plans/, agents/
ievo add <agent> [agent...]         # Pull from marketplace + resolve deps
ievo remove <agent> [--force]       # Remove agent (checks dependents)
ievo update [agent]                 # Update to latest marketplace version
ievo list [--marketplace]           # Show installed or available agents

# Running
ievo run <agent> [-m msg] [-p file] [--model opus|sonnet|haiku] [--local]
ievo team <agents...>               # Phase 2

# Evolution
ievo learn log <agent> [--last N]   # Show EVOLUTION_LOG.md
ievo learn push [agent]             # Send anonymized logs (opt-in)
ievo learn status [agent]           # Evolution stats

# Development
ievo dev new <name>                 # Scaffold agent locally
ievo dev test <agent>               # Run eval suite (Phase 2)
ievo dev publish <agent>            # Publish to marketplace (Phase 2)
```

## Dependencies

- typer — CLI framework
- rich — terminal formatting
- textual — TUI dashboard (from Rich creators)
- pyyaml — YAML parsing (manifest.yaml, agent.yaml, registry.yaml)
- httpx — async HTTP for marketplace registry
- pydantic — data validation (future use)
- cryptography — RSA/AES encryption for credentials

## Working rules

- **Session plan = first priority**: as soon as a plan is approved, IMMEDIATELY save it to the agent's `memory/sessions/NNN/plan.md`. Update throughout the session. A stale plan blocks recovery after crashes.
- **Incremental session bookkeeping**: after completing a phase or milestone, immediately update session files (plan.md + log.md) before starting the next phase.
- **100% test coverage**: all code must have 100% test coverage. Run `uv run pytest --cov --cov-report=term-missing` to verify. Never lower `fail_under` threshold.
- **Complete test coverage per feature**: every feature must be covered by ALL relevant test types:
  - **Unit tests**: individual functions, edge cases, error paths, boundary values
  - **Integration tests**: verify actual outcomes — files created, state changed, real objects returned. If a test only asserts `.assert_called_once()` without checking real side effects, it's incomplete
  - **Edge case tests**: empty inputs, missing files, permission errors, malformed data, concurrent access
  - **TUI tests**: use Textual's `app.run_test()` + `Pilot` API for real widget interaction — `pilot.press()`, `pilot.click()`, verify widget content with `app.query_one()`. Don't just mock widgets, test the real Textual app lifecycle
  - Mocks are acceptable ONLY for true external boundaries (Docker daemon, network APIs, subprocess calls). Everything else should use real objects and real filesystems (`tmp_path`)
- **Acceptance before done**: before marking any requirement as complete, self-review: all test types present (unit, integration, edge cases, UI), real outcomes verified (not just mock assertions), coverage on changed files is 100%, docs updated if user-facing. A requirement is NOT done until this passes.
- **Pre-commit after edits**: always run `uv run pre-commit run --files <changed-files>` after editing files.
- **Tests before push**: always run full test suite before pushing.
- **Don't reinvent the wheel**: use existing packages from PyPI. Before adding a dependency, search for well-maintained packages, evaluate stars/downloads/maintenance, then use. Don't write custom implementations for solved problems.
- **Context economy**: don't load all sessions into context. Load only the active session. If that's not enough, search previous sessions and docs on demand.
- **15-minute rule**: Architect decomposes every requirement into tasks of ≤15 minutes. If a task grows beyond this, stop — decompose further, implement what's ready, queue the rest in Backlog. Spec Writer does NOT own time estimates — only Architect does.

## Related repos

- [ievo-ai/eva](https://github.com/ievo-ai/eva) — mother agent (private)
- [ievo-ai/ievo.ai](https://github.com/ievo-ai/ievo.ai) — landing page
- ievo-ai/marketplace — agent registry
- ievo-ai/sdk — dev template
- ievo-ai/curator — cross-agent pattern curator

## Conventions

- Use `from ievo.utils.console import success, error, info, warn, step` for output
- All commands are separate files in `commands/`
- Async operations (network) use `asyncio.run()` at command level
- Project root required: use `require_project()` which exits with error if no `.ievo/manifest.yaml`
