# Folder Structure

Every VeilCLI workspace is a directory with a `.veil/` subfolder. Here is the complete layout:

---

## Workspace Layout

```
my-workspace/
└── .veil/
    ├── auth.json               ← Provider config and routing rules
    ├── custom_models.json      ← User-defined custom model entries
    ├── settings.json           ← Server and runtime settings
    ├── settings.local.json     ← Local overrides (gitignore this)
    ├── data.db                 ← SQLite database (sessions, messages)
    ├── runtime.pid             ← PID of the running server
    │
    ├── agents/
    │   └── <agent-name>/
    │       ├── agent.json      ← Agent configuration (required)
    │       ├── AGENT.md        ← System prompt / personality (required)
    │       ├── SOUL.md         ← Optional extra identity layer
    │       └── tools/          ← Optional custom tools for this agent (one folder per tool)
    │           └── my_tool/
    │               ├── tool.json   ← Schema manifest (name, description, input_schema, timeout)
    │               └── index.js    ← module.exports = async function execute(...) { ... }
    │
    ├── tools/                  ← Optional project-level custom tools (shared across agents)
    │   └── my_shared_tool/
    │       ├── tool.json
    │       └── index.js
    │
    ├── memory/
    │   ├── MEMORY.md           ← Project-level (global) memory
    │   └── agents/
    │       └── <agent-name>/
    │           └── MEMORY.md   ← Per-agent memory
    │
    └── heartbeats/
```

---

## File Descriptions

### `auth.json`

Stores API credentials. Separated from `settings.json` so you can gitignore it independently.

```json
{
  "providers": {
    "openrouter": {
      "type": "openai",
      "base_url": "https://openrouter.ai/api/v1",
      "api_key": "sk-or-v1-..."
    },
    "claude-local": {
      "type": "claude-cli",
      "path": "claude",
      "permission_mode": "acceptEdits"
    }
  },
  "routing": {
    "default": "openrouter",
    "fallback": [],
    "per_agent": {
      "coder": { "default": "claude-local", "fallback": [] }
    }
  }
}
```

Routing resolution order:
- **`per_agent`** — if the agent name matches, use that provider
- **`per_model`** — if the model ID matches, use that provider
- **`default`** — fallback provider for everything else
- **`fallback`** — array of providers to try if the default fails

---

### `custom_models.json`

User-defined custom model entries. These are merged with built-in models and appear in `GET /models`. Useful for adding models not yet in the OpenRouter catalog or defining aliases for frequently used models.

---

### `settings.json`

Runtime configuration. See [Configuration Reference](03-configuration.md) for all fields.

```json
{
  "port": 5050,
  "maxIterations": 20,
  "maxDurationSeconds": 120,
  "permissions": {
    "allow": [],
    "deny": [],
    "ask": []
  }
}
```

---

### `settings.local.json`

Same format as `settings.json`. Applied last (highest priority among file layers). Useful for developer overrides that should not be committed. Add to `.gitignore`.

---

### `data.db`

SQLite database file. Contains all sessions, messages, todos, and agent messages. Created automatically on first run.

**Do not edit manually.** If you need to reset state, stop the server and delete this file — it will be recreated.

---

### `runtime.pid`

Contains the process ID of the running server. Written by `veil start`, removed by `veil stop` / graceful shutdown. If it exists but the process is gone, it is a stale PID file and can be deleted.

---

### `agents/<name>/agent.json`

Agent configuration. JSON Schema-validated on load. See [Agent Configuration](04-agents.md).

---

### `agents/<name>/AGENT.md`

The agent's system prompt. Loaded and injected into every conversation for this agent. Supports variables:

| Variable | Resolves to |
|----------|-------------|
| `$AGENT_FOLDER` | Absolute path to the agent's folder |
| `$PROJECT_ROOT` | Absolute path to the workspace root |

Example:
```markdown
You are Analyst, a code analysis agent.

Your working directory is $PROJECT_ROOT.
Your files are in $AGENT_FOLDER.
```

---

### `agents/<name>/SOUL.md`

Optional. An additional identity/personality layer merged into the system prompt after `AGENT.md`. Useful for separating static capabilities from dynamic persona.

---

### `agents/<name>/tools/`

Optional directory for agent-specific custom tools. **One folder per tool**, each folder containing `tool.json` (schema manifest) + `index.js` (execute module). These tools are visible only to this agent.

```
tools/
└── my_tool/
    ├── tool.json     ← { "name", "description", "input_schema", "timeout" }
    └── index.js      ← module.exports = async function execute(input) { ... }
```

`index.js` exports the execute function **directly**, NOT an object with `{schema, execute}` (that shape is for built-in tools). See [Built-in Tools → Custom Tools](06-tools.md#custom-tools) for the full spec including injected context fields (`_cwd`, `_agent`, `_sessionId`, `_emitToolChunk`, etc.) and project/global-level tool directories (`.veil/tools/`, `~/.veil/tools/`).

---

### `memory/MEMORY.md`

Project-level shared memory. Written by agents using `memory_write` with `scope: "global"`. Injected into the system prompt of agents that have memory enabled.

---

### `memory/agents/<name>/MEMORY.md`

Per-agent memory. Written by agents using `memory_write` with `scope: "agent"` (default). Only injected for that agent.

---

## Global Config

VeilCLI also reads from a global config directory at `~/.veil/`:

```
~/.veil/
├── auth.json       ← Global API keys (overridden by project auth.json)
└── settings.json   ← Global defaults (overridden by project settings.json)
```

The global config is useful for sharing an API key across multiple workspaces without duplicating it. See [Settings Layers](03-configuration.md#settings-layers).

---

## What to Gitignore

Add these to `.gitignore` in your workspace:

```gitignore
.veil/data.db
.veil/runtime.pid
.veil/auth.json
.veil/settings.local.json
.veil/memory/
```

Keep `agents/`, `settings.json`, and `heartbeats/` in version control.
