Blog

Eva-CLI Project Structure and Configuration Guide

A tour of the landed Eva-CLI folder layout, Rust workspace scaffold, flat Agent directories, configuration files, schema validation, and policy boundaries.

Published: Category: Runtime

Eva-CLI now has two concrete foundations in the repository: a compilable Rust workspace skeleton and a project configuration tree. That changes the project from "architecture notes only" into a structure that future runtime code can validate, inspect, and execute against.

The important design choice is that folders do not grant authority. Folders make things discoverable. Authority still comes from manifests, schemas, policies, routes, and the runtime composition root.

Eva-CLI project structure map showing Rust workspace crates, configuration folders, flat Agent directories, schemas, policies, routes, adapters, and runtime handoff.
The current repository separates implementation ownership, human-maintained configuration, and runtime authority.

What the top-level folders mean

The root layout is intentionally boring. The static website lives in website/, architecture documents live in docs/, shared diagrams live in assets/, configuration lives in config/, and Rust implementation boundaries live in crates/.

Folder Purpose Runtime rule
config/ Human-maintained YAML, JSON Schemas, Agent manifests, Adapter manifests, policies, routes, and capability declarations. Parsed and validated before runtime registration. Secrets are referenced by environment variable name, not stored inline.
crates/ Rust workspace crates for stable ownership boundaries such as core contracts, config, policy, scheduler, adapter, discovery, and runtime. Lower crates must not depend back on eva-runtime; the runtime crate is the composition root.
src/ A thin binary shim that delegates process startup to eva-cli. Keep it small. CLI behavior belongs in crates/eva-cli.
docs/ Architecture, module partitioning, configuration, discovery, memory, hardware, lifecycle, and roadmap documents. Docs describe contracts that implementation should preserve; they are not runtime configuration.
website/ Static website source and generated pages, including blog content and locale JSON. Generated from templates and i18n data; source data and generated HTML should be committed together.

The configuration tree

The main runtime file is config/eva.yaml. It describes environment, workspace paths, EventBus, scheduler defaults, state, memory, knowledge, observability, and where the rest of the config tree lives. It should stay global. Per-Agent subscriptions, per-Adapter commands, and MCP allowlists belong in their own files.

Config path Owns Does not own
config/agents/<agent-id>/ Agent manifest, Lua entry script, optional constraints, subscriptions, inbox, timeout, state namespace, and permissions. API keys, provider commands, global policy, or implicit parent-child behavior from folder nesting.
config/adapters/ Provider manifests for CLI, HTTP, MCP, skill, hardware, and other transports. Plaintext secrets or user-controlled shell snippets.
config/policies/ Sandbox, Adapter, MCP server, hardware, retry, and global permission floors. Business routing or provider-specific payload logic.
config/routes/topics.yaml Topic pattern to Agent delivery rules. Business logic or automatic recursive delivery through folder hierarchy.
config/schemas/ JSON Schemas for validating parsed YAML structures. Runtime policy decisions after validation.

Why Agents are flat now

The earlier nested example mixed Topic hierarchy with Agent storage. That was misleading because /sys/route-a/route-aa is a route, not an Agent. The current model keeps one Agent entity per directory:

config/agents/
  root-agent/
    agent.yaml
    constraints.md
    main.lua
  agent-a/
    agent.yaml
    constraints.md
    main.lua
  agent-a11/
    agent.yaml
    main.lua
  agent-a12/
    agent.yaml
    main.lua

Runtime parent-child relationships remain explicit in agent.yaml through fields such as parent, children, subscriptions, and permissions.emit. Topic delivery remains explicit in config/routes/topics.yaml. This makes discovery, hot reload, and policy audit simpler: scan for Agent manifests, then validate what they claim.

How config becomes runtime authority

The intended load order is deterministic: built-in defaults, config/eva.yaml, policy files, routes, Agent manifests, Adapter manifests, environment variable references, then low-risk CLI overrides. Each step may add information, but permissions only narrow as they approach effective policy.

YAML files
  -> parse into structured values
  -> validate with JSON Schema
  -> normalize manifests
  -> merge policy floors
  -> build effective config
  -> register runtime handles

The next practical implementation work is to make this visible through commands such as eva config validate, eva config inspect, and eva config dump-effective. Those commands should prove that the directory tree is not just tidy; it is executable evidence for the runtime.

Related technical documents: Project Configuration and Module Partitioning.